Skip to content

Conversation

@PruthiviRaj27
Copy link
Contributor

@PruthiviRaj27 PruthiviRaj27 commented Jul 11, 2025

Changes done

Reason for the changes

Fixes # .

Summary by CodeRabbit

  • New Features

    • Introduced numerous new layout, color, and string resources across modules to enhance UI components, error handling, and localization.
    • Added new drawable resources for visual indicators and backgrounds.
    • Expanded support for exam, course, and store modules with new layouts for lists, empty/error states, and content items.
    • Added new styles for consistent dialog appearance.
    • Improved app name retrieval logic in order confirmation screens.
  • Refactor

    • Updated build configurations to use Java 17 and defined explicit namespaces for modules.
    • Replaced switch statements with if-else chains for improved code clarity in sample activities.
  • Bug Fixes

    • Corrected view references in video quality selection dialogs to ensure compatibility with external libraries.
  • Chores

    • Upgraded Gradle and Android Gradle Plugin versions for improved build performance and compatibility.

@coderabbitai
Copy link

coderabbitai bot commented Jul 11, 2025

Walkthrough

This update introduces extensive enhancements and modernization across the Android project. It upgrades build tools and Java/Kotlin compatibility to version 17, adds explicit namespace declarations, and introduces a wide array of new UI resources including layouts, drawables, colors, and strings for richer exam, course, and store modules. Several code refactors replace switch statements with if-else chains, and resource references are updated for consistency. New methods and styles are introduced to improve dynamic app name retrieval and dialog appearance.

Changes

Files / Groups Change Summary
build.gradle, gradle/wrapper/gradle-wrapper.properties Upgraded Android Gradle plugin to 8.0.2 and Gradle to 8.0.
core/build.gradle, course/build.gradle, exam/build.gradle, samples/build.gradle, store/build.gradle Added namespace declarations; updated Java/Kotlin compatibility to Java 17.
core/src/main/res/values/strings.xml, course/src/main/res/values/strings.xml, exam/src/main/res/values/strings.xml, store/src/main/res/values/strings.xml Added numerous new string resources for UI, errors, analytics, permissions, and features.
course/src/main/res/values/color.xml, exam/src/main/res/values/color.xml, store/src/main/res/values/color.xml Added new color resource files with named color values for UI consistency.
course/src/main/res/values/style.xml, exam/src/main/res/values/styles.xml, store/src/main/res/values/styles.xml Added new style: TestpressAppCompatAlertDialogStyle for dialogs.
course/src/main/res/layout/*.xml, exam/src/main/res/layout/*.xml, store/src/main/res/layout/*.xml Introduced many new layout XML files for lists, containers, empty/error views, exam details, spinners, and more.
course/src/main/res/drawable/*.xml Added new drawable resources for difficulty indicators with rounded corners.
course/src/main/java/in/testpress/course/ui/VideoDownloadQualityChooserDialog.kt, course/src/main/java/in/testpress/course/util/TrackSelectionDialog.kt Updated resource IDs to use ExoPlayer's track selection view resource.
course/src/main/java/in/testpress/course/fragments/LiveStreamFragment.kt Commented out line hiding duration view in player initialization.
samples/src/main/java/in/testpress/samples/*/*.java Refactored switch statements to if-else chains for menu and button handling; updated login credentials and URLs in core sample.
store/src/main/java/in/testpress/store/ui/OrderConfirmActivity.java Added method to dynamically retrieve app name for payment sheet.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant App
  participant UIResources
  participant BuildSystem

  User->App: Launches app or triggers UI
  App->BuildSystem: Compiles with Java 17, new namespace
  App->UIResources: Loads new layouts, colors, strings
  App->App: Handles menu/button (if-else logic)
  App->UIResources: Shows new dialog with custom style
  App->UIResources: Retrieves dynamic app name (store)
  App->User: Presents updated UI and features
Loading

Poem

🐇
New colors, strings, and layouts bloom,
Java 17 sweeps away the gloom!
Switches become ifs, code flows anew,
Dialogs styled in a crisp white hue.
With namespaces set and resources bright,
This bunny hops in pure delight!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@codetortoiseai
Copy link

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jul 11, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @PruthiviRaj27, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request primarily focuses on a significant technical upgrade of the Android project's build infrastructure, including Gradle and Java versions, alongside a broad expansion of UI components and string resources across various modules. It also includes minor code style refactoring and an enhancement to the Stripe payment integration.

Highlights

  • Build System and Language Version Upgrades: I've upgraded the Android Gradle Plugin from 7.4.2 to 8.0.2 and the Gradle wrapper from 7.5 to 8.0. Additionally, the Java/Kotlin compatibility and JVM target versions across core, course, exam, and samples modules have been updated to Java 17. This ensures compatibility with the latest Android development environment and leverages newer language features.
  • Android Namespace Migration: Explicit namespace declarations have been added to the build.gradle files for the core, course, exam, and samples modules. This aligns the project with modern Android Gradle Plugin requirements and best practices for library and application module identification.
  • Extensive UI/UX Component Additions: A significant number of new layout XML files, drawable resources, and string resources have been introduced across the core, course, and exam modules. These additions suggest a substantial expansion or overhaul of the application's user interface, including new components for lists, empty states, loading indicators, exam details, quiz questions, and video playback features.
  • Code Style Refactoring in Samples: The sample application's Java code has been refactored to convert switch statements into if-else if blocks in several navigation and SDK demonstration activities. This is a minor code style improvement for consistency and readability.
  • Stripe Payment Integration Enhancement: In the store module, the Stripe Payment Sheet configuration has been improved to dynamically retrieve the application's name using a new helper method. This enhances the flexibility and localization of the payment flow.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai coderabbitai bot changed the title @coderabbitai Upgrade to Java/Kotlin 17, add UI resources, and refactor code structure Jul 11, 2025
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request primarily focuses on upgrading the Android Gradle Plugin to version 8.0.2, Gradle to 8.0, and updating the Java/Kotlin versions to 17 across all modules. This is a significant and beneficial update for keeping the project modern and maintainable.

The changes also include adding namespaces to modules, which is required by the new AGP version, and introducing a large number of new resources such as layouts, drawables, and strings. The new layouts seem to follow good practices by using ShimmerFrameLayout for loading states.

While the majority of the changes are positive, I've identified several areas for improvement:

  • User-facing strings: There are multiple typos and inconsistencies in the newly added string resources across different modules.
  • Hardcoded values: The sample app now contains hardcoded credentials, which is a security concern, even for a demo.
  • Code and Layout Cleanliness: I've found some commented-out code that should be removed and a non-descriptive contentDescription in a layout file that impacts accessibility.

I've provided specific suggestions to address these points. Overall, this is a solid upgrade, and addressing these minor issues will improve the code quality.

Comment on lines +113 to +114
authenticate("111",
"111", TestpressSdk.Provider.TESTPRESS);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Hardcoding credentials, even for a sample app, is a bad practice and can lead to security risks if accidentally used in production or if the sample is copied. The previous implementation that read from the EditText fields was better. Please revert this change.

Suggested change
authenticate("111",
"111", TestpressSdk.Provider.TESTPRESS);
authenticate(usernameEditText.getText().toString().trim(),
passwordEditText.getText().toString().trim(), TestpressSdk.Provider.TESTPRESS);

<string name="session_cleared_message">Your session has been cleared. Please log out and login again.</string>
<string name="lockout_limit_info">Note : Admin has restricted login attempts to %d</string>

<string name="failed_loading_pdf"> Failed to load the PDF </string>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This string has leading and trailing spaces, which are likely unintentional. Please remove them.

    <string name="failed_loading_pdf">Failed to load the PDF</string>

<string name="permission_denied">Permission Denied</string>
<string name="content_scheduled">This content is scheduled!</string>
<string name="testpress_no_permission">You do not have permission to view this.</string>
<string name="testpress_some_thing_went_wrong_try_again">Some thing went wrong, please try again later.</string>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Typo: "Some thing" should be "Something".

    <string name="testpress_some_thing_went_wrong_try_again">Something went wrong, please try again later.</string>


<string name="window_monitoring_warning_description">Before you proceed, please be aware:\n\n<b>WINDOW MONITORING IS ENABLED:</b> This exam monitors if you leave the app.\n\n<b>DO NOT SWITCH APPS:</b> If you minimize this app or switch to another app more than 2 times, your exam will be automatically ended.\n\nStay focused in the exam screen to avoid violations and complete your attempt without interruption. </string>

<string name="exam_combined_warning_description">Before you proceed, please be aware:\n\n<b>RESUME IS DISABLED:</b> The admin has disabled the resume feature for this exam. Once you begin, if you close or navigate away from this app, you will NOT be able to resume your attempt. Your attempt will be permanently ended.\n\n<b>WINDOW MONITORING IS ENABLED:</b> This exam monitors if you leave the app. Minimizing this app or switching to another app more than 2 times will automatically end your exam.\n\nEnsure you are ready to take the exam without any interruptions. Double-check your internet connection, silence notifications, and make sure your device has sufficient power. </string>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the window_monitoring_warning_description, the number of allowed app switches is hardcoded here. It's better to use a placeholder for consistency and maintainability.

exoPlayerView.visibility = View.VISIBLE
exoPlayerView.setAspectRatio(16f / 9f)
exoPlayerView.findViewById<TextView>(R.id.exo_duration).visibility = View.GONE
//exoPlayerView.findViewById<TextView>(R.id.exo_duration).visibility = View.GONE

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This line is commented out. If it's no longer needed, it should be removed to keep the code clean. If it's for debugging, it should not be part of the final pull request.

<string name="testpress_search_hint">Search…</string>
<string name="testpress_no_results_found">Sorry, No results found</string>
<string name="testpress_try_with_other_keyword">Please try with some other keywords</string>
<string name="testpress_speech_recognition_not_supported">Opps! Your device doesn\'t support Speech to Text</string>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There's a typo in this string. "Opps!" should be "Oops!".

    <string name="testpress_speech_recognition_not_supported">Oops! Your device doesn\'t support Speech to Text</string>

<string name="testpress_error_loading_contents">Loading contents failed</string>
<string name="testpress_content_not_available">Content not available</string>
<string name="testpress_content_not_available_description">Content is no longer available or not published yet.</string>
<string name="video_id_locked"> This Video is locked!</string>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This string has an unnecessary leading space. Please remove it to avoid potential UI issues.

    <string name="video_id_locked">This Video is locked!</string>

<string name="session_cleared_message">Your session has been cleared. Please log out and login again.</string>
<string name="lockout_limit_info">Note : Admin has restricted login attempts to %d</string>

<string name="failed_loading_pdf"> Failed to load the PDF </string>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This string has unnecessary leading and trailing spaces. Please remove them.

    <string name="failed_loading_pdf">Failed to load the PDF</string>


<string name="exam_resume_disable_warning_description">Before you proceed, please be aware:\n\n<b>DO NOT CLOSE THIS APP:</b> Once you begin your exam, if you close or navigate away from this app, you will NOT be able to resume your attempt.\n\n<b>RESUME IS DISABLED:</b> The admin has disabled the resume feature for this exam. Once closed, your attempt will be permanently ended.\n\nEnsure you are ready to take the exam without interruptions. Double-check your internet connection and make sure your device has sufficient power.</string>

<string name="exam_resume_disable_warning_title">"IMPORTANT NOTICE!"</string>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The quotes around "IMPORTANT NOTICE!" are unnecessary and inconsistent with other dialog titles in the app. It's better to remove them and let the dialog's style handle the presentation.

    <string name="exam_resume_disable_warning_title">IMPORTANT NOTICE!</string>

<string name="testpress_tap_to_retry">Tap to retry</string>

<string name="testpress_network_error">Network Error</string>
<string name="testpress_some_thing_went_wrong_try_again">Some thing went wrong, please try again later.</string>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Typo: "Some thing" should be "Something".

    <string name="testpress_some_thing_went_wrong_try_again">Something went wrong, please try again later.</string>

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 39

🔭 Outside diff range comments (4)
course/src/main/res/values/strings.xml (1)

82-82: Build-breaking invalid XML comment

Line 82 contains //, which is not a valid XML comment and will break AAPT compilation.

-    //
+    <!--  placeholder for logical grouping – remove if not needed -->
core/src/main/res/values/strings.xml (3)

14-18: Fix duplicate key and grammar issues

  1. You have both permission_denied (l.14) and testpress_permission_denied (l.40) conveying the same idea → pick one key name and remove the other to avoid translation drift.
  2. testpress_please_login (l.16) reads “see this exams”. Should be “see these exams”.
-    <string name="testpress_please_login">Please login to see this exams</string>
+    <string name="testpress_please_login">Please log in to see these exams.</string>

54-55: Deprecated <font> tag – switch to <b>, <i> or span styling

hint (l.54) uses <font size="14">, which is deprecated in Android 8+. Use android:textSize in the view or <string name="hint"><![CDATA[<b>…]]></string> with a span instead.


22-23: Leading space in key video_id_locked

video_id_locked (l.22) starts with a space before “This Video is locked!”. That space will be rendered and looks like a layout bug.

-    <string name="video_id_locked"> This Video is locked!</string>
+    <string name="video_id_locked">This Video is locked!</string>
♻️ Duplicate comments (2)
exam/src/main/res/layout/testpress_empty_view_with_image.xml (1)

12-19: Duplicate issues as highlighted in course/.../testpress_empty_view_with_image.xml (missing contentDescription, hard-coded strings/colours, use of left/right). Please apply the same fixes for consistency.

Also applies to: 24-25, 38-39, 27-30, 42-44

course/src/main/res/layout/testpress_list.xml (1)

22-48: Same “placholder” typo and excessive duplicates

See comment in base_list_layout.xml; identical issue here. Apply the same rename & de-duplication.

🧹 Nitpick comments (73)
course/src/main/res/values/style.xml (1)

18-23: Prefer resource references over hard-coded hex values

Hard-coding colors here makes global theming harder (e.g. dark-mode, brand re-skin).
Consider moving these to @color/... entries (as was done for cb_dark_grey earlier) and reference them instead:

-        <item name="colorAccent">#08AE9E</item>
-        <item name="android:textColorPrimary">#333333</item>
-        <item name="android:background">#FFFFFF</item>
+        <item name="colorAccent">@color/testpress_teal</item>
+        <item name="android:textColorPrimary">@color/testpress_text_primary</item>
+        <item name="android:background">@color/white</item>

Keeps colours in one place, simplifies future palette changes and enables automated night-mode substitution.

gradle/wrapper/gradle-wrapper.properties (1)

3-3: Gradle wrapper updated – missing checksum

It’s good to align with Gradle 8.0, but AGP 8.0.2 is also compatible with Gradle 8.1. Consider jumping straight to 8.1 for the latest fixes, and add the distributionSha256Sum entry for supply-chain integrity.

store/src/main/res/values/color.xml (1)

1-4: Expand 3-digit hex for readability & consistency

#777 is valid, yet most project colours use 6-digit notation. Expanding improves grep-ability and avoids confusion around alpha channels:

-    <color name="testpress_text_gray">#777</color>
+    <color name="testpress_text_gray">#777777</color>

Also, file naming is usually colors.xml (plural) to align with Android Studio templates.

course/src/main/java/in/testpress/course/fragments/LiveStreamFragment.kt (1)

88-93: Prefer requireView() and delete commented-out code

  1. The non-null assertion view!! can crash at runtime; requireView() is the safe equivalent after onViewCreated.
  2. Leaving the exo_duration line commented clutters the codebase. Either restore the GONE behaviour or delete the line entirely to keep intent clear.
-        exoPlayerView = view!!.findViewById(R.id.exo_player_main_frame)
+        exoPlayerView = requireView().findViewById(R.id.exo_player_main_frame)

-        //exoPlayerView.findViewById<TextView>(R.id.exo_duration).visibility = View.GONE
store/build.gradle (1)

8-35: Verify Java 17 migration across tool-chain & dependencies

Upgrading to Java 17 is fine from AGP 8.0+, but:

  • Ensure compileSdkVersion ≥ 34 and AGP version supports 17 byte-code.
  • Stripe SDK ≤ 20.38.0 (per long-term learning) is still Java 11; check for any transitive incompatibility.
  • CI images may require JAVA_HOME 17; confirm pipeline.

If all checks pass, no changes needed.

samples/src/main/java/in/testpress/samples/exam/ExamSampleActivity.java (1)

88-103: If-else chain is functionally identical but harder to scan

Given six mutually-exclusive constants, the original switch/case (or a modern if-else with early returns) is more readable than a long if-else ladder. Not blocking, but consider:

switch (clickedButtonId) {
    case R.id.start_exam:            TestpressExam.startExam(this, examSlug, session); break;
    case R.id.attempt_state:         TestpressExam.showExamAttemptedState(this, examSlug, session); break;
    ...
}
store/src/main/res/values/styles.xml (1)

22-26: Extract hard-coded colors into dedicated resources.

Embedding hex values directly in style attributes makes global palette changes harder and risks subtle mismatches between modules (course/exam/store all define the same colors separately).
Please move #08AE9E, #333333, and #FFFFFF to values/colors.xml (or reuse existing color resources) and reference them here to keep them DRY.

samples/src/main/java/in/testpress/samples/store/NavigationDrawerActivity.java (1)

31-37: Add a defensive else / default branch.

The previous switch handled any unknown item via its default clause; the new if-else chain silently ignores unexpected IDs.
Consider adding an else logging branch (or delegating to super) to aid future debugging and preserve parity with the old behaviour.

samples/src/main/java/in/testpress/samples/store/StoreSampleActivity.java (1)

60-66: Re-evaluate button-ID mapping logic.

showSDK only enters the first branch when clickedButtonId == R.id.store, yet no caller passes that ID (they use new_activity_button).
Either:

  • Change the first comparison to R.id.new_activity_button, or
  • Pass R.id.store from the click listener intended to launch the store screen.

As-is, the extra branch is dead code and may confuse future readers.

samples/src/main/java/in/testpress/samples/course/NavigationDrawerActivity.java (1)

30-40: Leverage Java 17 switch-expression for clarity & conciseness

The new if-else chain works but is more verbose than necessary. With Java 17 already enabled in the build, you can adopt the modern switch-expression syntax which is both shorter and less error-prone:

-        int itemId = menuItem.getItemId();
-
-        if (itemId == R.id.courses) {
-            showSDK(1);
-        } else if (itemId == R.id.leaderboard) {
-            showSDK(2);
-        } else if (itemId == R.id.running_content) {
-            showSDK(3);
-        } else if (itemId == R.id.upcoming_content) {
-            showSDK(4);
-        }
+        switch (menuItem.getItemId()) {
+            case R.id.courses          -> showSDK(1);
+            case R.id.leaderboard      -> showSDK(2);
+            case R.id.running_content  -> showSDK(3);
+            case R.id.upcoming_content -> showSDK(4);
+        }

This removes the nested else branches, automatically handles break, and makes future additions simpler.

samples/build.gradle (1)

52-62: Possible stdlib mismatch with JVM 17 target

kotlinOptions.jvmTarget = "17" is fine, but the root project still references kotlinStdlibJdk7. Shipping classes compiled for 17 while linking a JDK-7 stdlib could cause runtime method-handle issues on older devices.

Consider moving to org.jetbrains.kotlin:kotlin-stdlib (no JDK suffix) or kotlin-stdlib-jdk8, which is the recommended artifact when targeting ≥ 1.8.

samples/src/main/java/in/testpress/samples/BaseNavigationDrawerActivity.java (1)

58-65: Same comment as course activity: switch-expression would reduce boilerplate

You can apply the Java 17 switch-expression here too:

-        int itemId = menuItem.getItemId();
-
-        if (itemId == R.id.home) {
-            displayHome();
-            selectedItem = 0;
-        } else if (itemId == R.id.logout) {
-            logout();
-        }
+        switch (menuItem.getItemId()) {
+            case R.id.home   -> { displayHome(); selectedItem = 0; }
+            case R.id.logout -> logout();
+        }
exam/src/main/res/values/styles.xml (1)

146-150: Avoid hard-coded colors in shared dialog style

Direct hex values make it harder to adapt to dark-mode, dynamic-color (Material You), or institute-level theming. Prefer referencing palette resources:

-    <style name="TestpressAppCompatAlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
-        <item name="colorAccent">#08AE9E</item>
-        <item name="android:textColorPrimary">#333333</item>
-        <item name="android:background">#FFFFFF</item>
+    <style name="TestpressAppCompatAlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
+        <item name="colorAccent">@color/testpress_color_primary</item>
+        <item name="android:textColorPrimary">@color/testpress_text_primary</item>
+        <item name="android:background">@color/testpress_surface</item>
     </style>

This keeps the style in sync with brand/color-system updates and reduces duplication.

course/src/main/res/layout/testpress_fragment_carousel_with_empty_view.xml (2)

2-5: Prefer ConstraintLayout over RelativeLayout for flatter, more performant hierarchies

ConstraintLayout eliminates the need for nested RelativeLayouts, reduces measure / layout passes and is now the de-facto container recommended by Google. Consider migrating while the file is new – dependencies are already present in the project for other layouts.


13-18: Hard-coded dimensions & missing accessibility hint on the loading spinner

  1. Size 45dp is hard-coded; reference a dimension resource (@dimen/testpress_loader_size) for consistency across densities.
  2. Add android:contentDescription="@string/testpress_loading" (or android:importantForAccessibility="no") so screen-readers don’t treat the indeterminate bar as an unlabeled element.
-    <ProgressBar
+    <ProgressBar
         android:id="@+id/pb_loading"
-        android:layout_width="45dp"
-        android:layout_height="45dp"
+        android:layout_width="@dimen/testpress_loader_size"
+        android:layout_height="@dimen/testpress_loader_size"
         android:indeterminate="true"
+        android:contentDescription="@string/testpress_loading"
         android:layout_centerInParent="true" />
exam/src/main/res/values/color.xml (1)

10-17: Duplicate primary colour declarations create maintenance overhead

@color/testpress_color_primary and @color/testpress_color_primary_blue have identical values (#2196F3). Pick one canonical name and reference it elsewhere to avoid divergence later.

exam/src/main/res/layout/testpress_loading_layout.xml (1)

8-15: Deprecated layout_marginRight hampers RTL support

layout_marginRight is ignored in RTL locales; you already specify layout_marginEnd. Drop the deprecated attribute to prevent double spacing.

-        android:layout_marginRight="10dp"
         android:layout_marginEnd="10dp" />
course/src/main/res/layout/testpress_loading_layout.xml (2)

8-15: Prefer RTL-aware margins over hard-coded layout_marginRight

android:layout_marginRight is ignored in RTL layouts from API 17 onward.
Rely solely on layout_marginStart/layout_marginEnd (or marginEnd alone since you already include it) to keep the spacing correct in both LTR and RTL.

-        android:layout_marginRight="10dp"
-        android:layout_marginEnd="10dp"
+        android:layout_marginStart="10dp"
+        android:layout_marginEnd="10dp"

8-13: Add an explicit contentDescription for accessibility

Indeterminate progress bars are announced as “in progress” by screen readers only if they have a non-empty contentDescription; otherwise they may be ignored.
If you don’t want it announced, set it to @null explicitly to suppress warnings from accessibility lint.

-    <ProgressBar
+    <ProgressBar
+        android:contentDescription="@null"
course/src/main/res/layout/testpress_actionbar_spinner.xml (1)

7-12: Missing contentDescription on interactive control

Because ClosableSpinner is an interactive widget, it should have a meaningful android:contentDescription (or android:prompt if appropriate) so that assistive technologies can announce its purpose.

-        android:id="@+id/actionbar_spinner"
+        android:id="@+id/actionbar_spinner"
+        android:contentDescription="@string/testpress_spinner_actionbar"

Add a matching entry in strings.xml.

course/src/main/res/layout/testpress_loading_layout_small.xml (2)

9-16: Use RTL-aware margins

Same concern as the large loading layout: replace layout_marginRight with layout_marginStart/layout_marginEnd.

-        android:layout_marginRight="10dp"
-        android:layout_marginEnd="10dp"
+        android:layout_marginStart="10dp"
+        android:layout_marginEnd="10dp"

9-14: Specify contentDescription

Add android:contentDescription="@null" (or a descriptive string) to avoid accessibility-lint warnings.

course/src/main/res/layout/testpress_empty_view.xml (1)

43-48: Add contentDescription to the retry button

Buttons without a label announced by TalkBack rely entirely on android:text. If the text changes programmatically, set an explicit contentDescription or android:labelFor to guarantee accessibility.

samples/src/main/java/in/testpress/samples/course/CourseSampleActivity.java (1)

202-219: Duplicate flag configuration & missing downloads branch

The two branches repeat identical setBookmarksEnabled, setCommentsVotingEnabled, and setCoursesFrontend calls, differing only in setCoursesGamificationEnabled(). Extract common setters and keep the delta to one line.

downloads isn’t handled, which means its gamification flag inherits the last stored value and may be inconsistent between sessions.

                session.getInstituteSettings()
-                        .setBookmarksEnabled(true)
-                        .setCommentsVotingEnabled(false)
-                        .setCoursesFrontend(true)
-                        .setCoursesGamificationEnabled(false);
+                        .setBookmarksEnabled(true)
+                        .setCommentsVotingEnabled(false)
+                        .setCoursesFrontend(true)
+                        .setCoursesGamificationEnabled(false);  // only delta

Consider a small helper method or builder-style copy to avoid this repetition and add an explicit branch for R.id.downloads.

course/src/main/res/layout/testpress_edit_text_dialog_box.xml (1)

15-21: Minor: Consider maxLength to guard against excessively long input

If this dialog targets free-text user input that ends up in a backend call or database, capping length prevents abuse and layout issues.

-            android:maxLines="6"
+            android:maxLines="6"
+            android:maxLength="500"
course/src/main/res/layout/testpress_container_layout.xml (2)

5-7: orientation attribute is ignored on RelativeLayout

RelativeLayout doesn’t use android:orientation; leaving it confuses future readers.

-    android:orientation="vertical"

19-24: Put indeterminate drawable via style to avoid repeated attributes

Embedding fixed size/ drawable here duplicates similar progress bars across layouts. Extract into a style (TestpressLargeProgressBar) for easier theming.

course/src/main/res/layout/testpress_fragment_carousel.xml (2)

23-26: Hard-coded color #ccc – use a resource

Inline colors hinder theming. Declare in colors.xml (maybe testpress_divider_color) and reference it.

-        android:background="#ccc" />
+        android:background="@color/testpress_divider_color" />

28-32: Consider migrating to ViewPager2

androidx.viewpager.widget.ViewPager is deprecated; ViewPager2 brings RTL, vertical paging, and DiffUtil support. Plan to migrate when possible.

store/src/main/java/in/testpress/store/ui/OrderConfirmActivity.java (2)

421-435: Pass a complete PaymentSheet.Configuration

PaymentSheet.Configuration also lets you specify merchantDisplayName, default billing address, etc. You already pass the app name—good—but you should also set allowsDelayedPaymentMethods according to business rules to avoid declined payments.

paymentSheet.presentWithPaymentIntent(
    clientSecret,
    new PaymentSheet.Configuration(
        getAppName(this),
        new PaymentSheet.CustomerConfiguration(order.getCustomerId(), order.getEphemeralKey()) // example
    )
);

425-429: Move PaymentConfiguration.init to Application class

Stripe recommends one-time initialization in Application#onCreate; repeated initialization per payment attempt is unnecessary and slightly expensive.

course/src/main/res/layout/testpress_chapters_list_item.xml (3)

11-16: Remove the meaningless android:orientation from RelativeLayout.

RelativeLayout ignores the orientation attribute – its presence is a no-op and adds noise to the XML.
Delete the attribute to keep the layout clean.


30-32: Avoid magic colours; reference a colour resource.

#aaffffff should live in colors.xml (e.g., @color/testpress_white_translucent) to enable theming.


65-74: Replace hard-coded placeholder text with a string resource.

-android:text="Title goes here"
+android:text="@string/testpress_chapter_title_placeholder"

This enables localisation and centralises copy changes.

course/src/main/res/layout/testpress_attempt_list_item.xml (3)

7-10: Hard-coded divider colour #eee – move to a resource.

Makes theme overrides easier and avoids duplicate literals.


21-29: Placeholder dates should be removed or pulled from strings.xml.

Real data will be bound at runtime; keep the layout neutral:

-android:text="Jan 25, 2017"
+tools:text="Jan 25, 2017"

Using tools:text keeps sample data in preview only.

Also applies to: 82-90


63-67: Use marginEnd and theme colour resources instead of literals.

Replace:

-android:layout_marginRight="5dp"
-android:tint="#777"
+android:layout_marginEnd="5dp"
+android:tint="@color/testpress_text_gray_medium"

Also applies to: 115-118

exam/src/main/res/layout/testpress_container_layout.xml (1)

2-6: android:orientation is ignored on RelativeLayout.

Remove the attribute; it can confuse future readers.

exam/src/main/res/layout/testpress_empty_view.xml (1)

22-26: Move “Network Error” string to strings.xml.

Hard-coding breaks localisation.

-android:text="Network Error"
+android:text="@string/testpress_network_error"
course/src/main/res/layout/testpress_empty_view_with_image.xml (1)

42-44: Avoid hard-coded colour literals

android:textColor="#666666" bypasses theme / dark-mode support.
Create a colour resource (e.g., @color/testpress_text_gray) and reference it here.

course/src/main/res/values/color.xml (1)

13-14: Duplicate primary colour definitions

testpress_color_primary and testpress_color_primary_blue are identical (#2196F3).
Keeping both adds cognitive overhead and risks divergence later. Consolidate to a single resource and update references.

store/src/main/res/layout/testpress_container_layout.xml (1)

2-6: android:orientation is ignored on RelativeLayout

RelativeLayout does not honor android:orientation; remove it to avoid confusion.

exam/src/main/res/layout/testpress_list.xml (1)

56-56: Redundant namespace declaration

xmlns:android is re-declared on SwipeRefreshLayout. It is harmless but noisy—recommend dropping it.

store/src/main/res/layout/testpress_empty_view.xml (1)

11-17: No placeholder image set

ImageView lacks a tools:src sample or a default android:src, so design-time preview is blank.
Add tools:src="@drawable/ic_cloud_off" (or similar) for better tooling support.

course/src/main/res/layout/testpress_content_list_item.xml (1)

102-111: Replace hard-coded text with tools:text

These literal strings will ship if the view is accidentally inflated before being overridden. Use tools:text to keep APK lean and localisable.

Example:

-        android:text="Title goes here"
+        tools:text="Title goes here"

Repeat for duration, question count, comment count, etc.

Also applies to: 127-135, 145-149, 171-179, 193-199, 218-226

course/src/main/res/layout/quiz_question_layout.xml (2)

6-8: orientation attribute has no effect on RelativeLayout

Drop it to avoid misleading future readers.

-    android:orientation="vertical">
+    >

60-97: Mixed use of drawable and solid colour backgrounds

Middle difficulty bars use a plain colour while ends use shape drawables. If rounded shapes are intended across all five bars, provide corresponding *_middle_off/on.xml drawables for consistency and themability.

course/src/main/res/layout/base_list_layout.xml (2)

20-46: Typo in included layout name & repetitive placeholders

testpress_list_placholder is misspelled (“placeholder”), yet the same typo is repeated nine times.
Besides harming readability, the repetition bloats the initial view hierarchy and adds unnecessary inflation cost. Inflate the placeholder once (or generate them programmatically) and fix the spelling to keep resource names consistent.

-            <include
-                layout="@layout/testpress_list_placholder">
-            </include>
+            <include
+                layout="@layout/testpress_list_placeholder" />

Do the same for the remaining eight includes; or switch to a <merge>-based placeholder and add it once.


2-5: Consider migrating RelativeLayout to ConstraintLayout

ConstraintLayout removes two nested levels (RelativeLayout + LinearLayout) without functional loss, improving measure/layout performance.

course/src/main/res/layout/testpress_list.xml (1)

55-60: Redundant namespace declaration

xmlns:android is re-declared inside SwipeRefreshLayout. It is legal but noisy; remove to keep markup minimal.

course/src/main/res/values/strings.xml (3)

49-50: Likely typo in string value

Targets / Threats probably meant Targets / Threads.

-    <string name="testpress_targets_or_threads">Targets / Threats</string>
+    <string name="testpress_targets_or_threads">Targets / Threads</string>

63-63: Spelling error

Download DescritionDownload Description

-    <string name="download_description">Download Descrition</string>
+    <string name="download_description">Download Description</string>

137-138: Grammar: “some thing” → “something”

-    <string name="testpress_some_thing_went_wrong_try_again">Some thing went wrong, please try again later.</string>
+    <string name="testpress_something_went_wrong_try_again">Something went wrong, please try again later.</string>

Remember to update call-sites.

course/src/main/res/layout/testpress_exam_details_layout.xml (1)

122-123: Inline color literal hinders theme / dark-mode support

android:tint="#9900cc" should reference a color resource.

-                android:tint="#9900cc"
+                android:tint="@color/testpress_purple"
store/src/main/res/values/strings.xml (1)

75-77: Typo: “some thing”

Same grammar issue as in course strings; unify spelling for consistency.

-    <string name="testpress_some_thing_went_wrong_try_again">Some thing went wrong, please try again later.</string>
+    <string name="testpress_something_went_wrong_try_again">Something went wrong, please try again later.</string>
course/src/main/res/layout/course_preview_layout.xml (1)

55-60: Redundant namespace declaration

androidx.swiperefreshlayout.widget.SwipeRefreshLayout re-declares xmlns:android, which is already defined in the root tag. AAPT keeps the first and drops the rest, but this is noise and can confuse merge tools.

-    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
+    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
course/src/main/res/layout/content_list_item.xml (2)

30-47: Hard-coded colour & dimensions

android:background="#CAC8C8" and fixed 155dp/87dp make the thumbnail non-theming and non-scalable.
Turn the grey into a color resource (e.g., @color/testpress_placeholder_bg) and move sizes to dimens.xml.


90-97: Ineffective layout_gravity inside ConstraintLayout

android:gravity="end|bottom" on a LinearLayout that is constrained with app:layout_constraintEnd_toEndOf="parent" does nothing.
Delete the gravity attribute to avoid confusion.

course/src/main/res/layout/video_content_list_item.xml (2)

56-78: Progress container: missing style attributes

The horizontal ProgressBar uses default colour which may clash with the app theme. Set android:progressTint / android:indeterminateTint via theme attr to respect dark/light mode.


120-140: Duplicate lock-icon container implementation

The same 36dp grey-round lock container appears in three list-item layouts. Extract into a reusable layout (e.g., lock_badge.xml) and <include> it to reduce duplication.

course/src/main/res/layout/exam_content_list_item.xml (1)

160-170: Clock & tick icons missing contentDescription

These icons convey information (duration, attempted flag). Add android:contentDescription="@null" to mark decorative or a proper string for meaningful icons to satisfy accessibility scanners.

exam/src/main/res/values/strings.xml (2)

290-292: Leading space in value

" This Video is locked!" begins with a space and will render mis-aligned. Remove the leading whitespace.

-    <string name="video_id_locked"> This Video is locked!</string>
+    <string name="video_id_locked">This video is locked!</string>

308-310: Spelling & casing

Goto should be Go to for proper English.

-    <string name="testpress_go_to_settings">Goto Settings</string>
+    <string name="testpress_go_to_settings">Go to Settings</string>
core/src/main/res/values/strings.xml (10)

41-42: Spelling: “Go to”, not “Goto”

Both occurrences of “Goto” (l.41 & l.42) should be “Go to” to stay grammatically correct.

-    <string name="testpress_go_to_settings">Goto Settings</string>
+    <string name="testpress_go_to_settings">Go to Settings</string>

73-76: Plural template is fragile

time_duration (l.73-76) relies on passing two format arguments (%d %s). In ICU-style plurals you normally need only the quantity and derive the unit (“minute/minutes”). Consider two separate plural resources or use %d %s with a comment explaining the second placeholder for translators.


78-88: Branding / style consistency

  1. Testpress Exam Sdk (l.79) → “SDK” is an acronym; capitalise: Testpress Exam SDK.
  2. testpress_course vs testpress_exams (plural) – keep either both singular or both plural for menu symmetry.
-    <string name="testpress_app_name">Testpress Exam Sdk</string>
+    <string name="testpress_app_name">Testpress Exam SDK</string>

90-93: Redundant / conflicting pause strings

You now have three very similar “exam paused” strings (l.90-92 & l.115). Consolidate into one message with optional placeholder parts to prevent translators doing the same work several times.


115-117: Sentence casing inconsistency

testpress_exam_paused (l.115) starts with capital “Exam”, whereas neighbouring UI verbs are uppercase (PAUSE, RESUME). Decide on sentence case vs all-caps for action labels and stick to it; mixed styles look unpolished.


136-151: Mixed-case action labels

testpress_pause (PAUSE) vs testpress_start_exam (Start Exam). Unless UX explicitly calls for caps-only buttons, normalise to one style (recommended: Title Case for buttons, sentence case for messages).


322-323: Unintended quotation marks

exam_resume_disable_warning_title (l.322) encloses the title in quotes: "IMPORTANT NOTICE!". Those literal quotes will appear on screen. Remove them unless expressly desired.

-    <string name="exam_resume_disable_warning_title">"IMPORTANT NOTICE!"</string>
+    <string name="exam_resume_disable_warning_title">IMPORTANT NOTICE!</string>

330-335: Retake option string array lacks translation context

testpress_retake_options (l.331-334) items are shown without a surrounding sentence; add a comment so translators know the UI context (e.g. “Retake with: {option}”).


345-346: Missing placeholder annotation

rank_will_be_published (l.345) uses %s but there is no accompanying comment describing the expected format (e.g., date). Always add <xliff:g> or translator comment for clarity.


312-319: Inconsistent apostrophe escape

testpress_switch_section_message (l.316) uses won\'t, others use straight '. Android handles both but consistency helps translators’ memory tools.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9bf8ad3 and 16f8a96.

⛔ Files ignored due to path filters (17)
  • course/src/main/res/drawable/crown.png is excluded by !**/*.png
  • course/src/main/res/drawable/ic_bookmark.png is excluded by !**/*.png
  • course/src/main/res/drawable/ic_error_outline_black_18dp.png is excluded by !**/*.png
  • course/src/main/res/drawable/ic_file_download_18dp.png is excluded by !**/*.png
  • course/src/main/res/drawable/ic_remove_bookmark.png is excluded by !**/*.png
  • course/src/main/res/drawable/testpress_alert_warning.png is excluded by !**/*.png
  • course/src/main/res/drawable/testpress_attachment_content_icon.png is excluded by !**/*.png
  • course/src/main/res/drawable/testpress_bookmark_flat_icon.png is excluded by !**/*.png
  • course/src/main/res/drawable/testpress_ebook_content_icon.png is excluded by !**/*.png
  • course/src/main/res/drawable/testpress_exam_icon.png is excluded by !**/*.png
  • course/src/main/res/drawable/testpress_no_wifi.png is excluded by !**/*.png
  • course/src/main/res/drawable/testpress_profile_image_place_holder.png is excluded by !**/*.png
  • course/src/main/res/drawable/testpress_question_content_icon.png is excluded by !**/*.png
  • course/src/main/res/drawable/testpress_video_content_icon.png is excluded by !**/*.png
  • exam/src/main/res/drawable/testpress_alert_warning.png is excluded by !**/*.png
  • exam/src/main/res/drawable/testpress_no_wifi.png is excluded by !**/*.png
  • store/src/main/res/drawable/ic_error_outline_black_18dp.png is excluded by !**/*.png
📒 Files selected for processing (66)
  • build.gradle (1 hunks)
  • core/build.gradle (2 hunks)
  • core/src/main/res/values/strings.xml (1 hunks)
  • course/build.gradle (2 hunks)
  • course/src/main/java/in/testpress/course/fragments/LiveStreamFragment.kt (1 hunks)
  • course/src/main/java/in/testpress/course/ui/VideoDownloadQualityChooserDialog.kt (1 hunks)
  • course/src/main/java/in/testpress/course/util/TrackSelectionDialog.kt (3 hunks)
  • course/src/main/res/drawable/testpress_difficulty_left_off.xml (1 hunks)
  • course/src/main/res/drawable/testpress_difficulty_left_on.xml (1 hunks)
  • course/src/main/res/drawable/testpress_difficulty_right_off.xml (1 hunks)
  • course/src/main/res/drawable/testpress_difficulty_right_on.xml (1 hunks)
  • course/src/main/res/layout/base_list_layout.xml (1 hunks)
  • course/src/main/res/layout/content_list_item.xml (1 hunks)
  • course/src/main/res/layout/course_preview_layout.xml (1 hunks)
  • course/src/main/res/layout/exam_content_list_item.xml (1 hunks)
  • course/src/main/res/layout/quiz_question_layout.xml (1 hunks)
  • course/src/main/res/layout/testpress_actionbar_spinner.xml (1 hunks)
  • course/src/main/res/layout/testpress_attempt_list_header.xml (1 hunks)
  • course/src/main/res/layout/testpress_attempt_list_item.xml (1 hunks)
  • course/src/main/res/layout/testpress_chapters_list_item.xml (1 hunks)
  • course/src/main/res/layout/testpress_container_layout.xml (1 hunks)
  • course/src/main/res/layout/testpress_content_list_item.xml (1 hunks)
  • course/src/main/res/layout/testpress_edit_text_dialog_box.xml (1 hunks)
  • course/src/main/res/layout/testpress_empty_view.xml (1 hunks)
  • course/src/main/res/layout/testpress_empty_view_with_image.xml (1 hunks)
  • course/src/main/res/layout/testpress_exam_details_layout.xml (1 hunks)
  • course/src/main/res/layout/testpress_fragment_carousel.xml (1 hunks)
  • course/src/main/res/layout/testpress_fragment_carousel_with_empty_view.xml (1 hunks)
  • course/src/main/res/layout/testpress_list.xml (1 hunks)
  • course/src/main/res/layout/testpress_loading_layout.xml (1 hunks)
  • course/src/main/res/layout/testpress_loading_layout_small.xml (1 hunks)
  • course/src/main/res/layout/testpress_lockable_spinner_item_dropdown.xml (1 hunks)
  • course/src/main/res/layout/testpress_plain_spinner_item.xml (1 hunks)
  • course/src/main/res/layout/video_content_list_item.xml (1 hunks)
  • course/src/main/res/values/color.xml (1 hunks)
  • course/src/main/res/values/strings.xml (1 hunks)
  • course/src/main/res/values/style.xml (1 hunks)
  • exam/build.gradle (2 hunks)
  • exam/src/main/res/layout/testpress_container_layout.xml (1 hunks)
  • exam/src/main/res/layout/testpress_empty_view.xml (1 hunks)
  • exam/src/main/res/layout/testpress_empty_view_with_image.xml (1 hunks)
  • exam/src/main/res/layout/testpress_filter_menu_view.xml (1 hunks)
  • exam/src/main/res/layout/testpress_list.xml (1 hunks)
  • exam/src/main/res/layout/testpress_loading_layout.xml (1 hunks)
  • exam/src/main/res/menu/testpress_filter.xml (1 hunks)
  • exam/src/main/res/menu/testpress_time_analytics_filter.xml (1 hunks)
  • exam/src/main/res/values/color.xml (1 hunks)
  • exam/src/main/res/values/strings.xml (1 hunks)
  • exam/src/main/res/values/styles.xml (1 hunks)
  • gradle/wrapper/gradle-wrapper.properties (1 hunks)
  • samples/build.gradle (2 hunks)
  • samples/src/main/java/in/testpress/samples/BaseNavigationDrawerActivity.java (1 hunks)
  • samples/src/main/java/in/testpress/samples/core/TestpressCoreSampleActivity.java (1 hunks)
  • samples/src/main/java/in/testpress/samples/course/CourseSampleActivity.java (2 hunks)
  • samples/src/main/java/in/testpress/samples/course/NavigationDrawerActivity.java (1 hunks)
  • samples/src/main/java/in/testpress/samples/exam/ExamSampleActivity.java (1 hunks)
  • samples/src/main/java/in/testpress/samples/exam/NavigationDrawerActivity.java (1 hunks)
  • samples/src/main/java/in/testpress/samples/store/NavigationDrawerActivity.java (1 hunks)
  • samples/src/main/java/in/testpress/samples/store/StoreSampleActivity.java (1 hunks)
  • store/build.gradle (2 hunks)
  • store/src/main/java/in/testpress/store/ui/OrderConfirmActivity.java (2 hunks)
  • store/src/main/res/layout/testpress_container_layout.xml (1 hunks)
  • store/src/main/res/layout/testpress_empty_view.xml (1 hunks)
  • store/src/main/res/values/color.xml (1 hunks)
  • store/src/main/res/values/strings.xml (1 hunks)
  • store/src/main/res/values/styles.xml (1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: rupesh-ps
PR: testpress/android-sdk#863
File: build.gradle:110-110
Timestamp: 2025-05-19T13:41:49.742Z
Learning: The project uses Kotlin 1.8.0 which has compatibility constraints with Stripe Android SDK, limiting it to version 20.38.0 maximum. Suggestions to upgrade to newer Stripe SDK versions should consider this limitation.
build.gradle (1)
Learnt from: rupesh-ps
PR: testpress/android-sdk#863
File: build.gradle:110-110
Timestamp: 2025-05-19T13:41:49.742Z
Learning: The project uses Kotlin 1.8.0 which has compatibility constraints with Stripe Android SDK, limiting it to version 20.38.0 maximum. Suggestions to upgrade to newer Stripe SDK versions should consider this limitation.
core/build.gradle (1)
Learnt from: rupesh-ps
PR: testpress/android-sdk#863
File: build.gradle:110-110
Timestamp: 2025-05-19T13:41:49.742Z
Learning: The project uses Kotlin 1.8.0 which has compatibility constraints with Stripe Android SDK, limiting it to version 20.38.0 maximum. Suggestions to upgrade to newer Stripe SDK versions should consider this limitation.
exam/build.gradle (2)
Learnt from: PruthiviRaj27
PR: testpress/android-sdk#904
File: exam/src/main/java/in/testpress/exam/api/ExamService.java:110-113
Timestamp: 2025-07-03T12:51:50.551Z
Learning: QuizExam in the course module does not have window monitoring features, so exam window violation related changes should not be applied to the course module.
Learnt from: rupesh-ps
PR: testpress/android-sdk#863
File: build.gradle:110-110
Timestamp: 2025-05-19T13:41:49.742Z
Learning: The project uses Kotlin 1.8.0 which has compatibility constraints with Stripe Android SDK, limiting it to version 20.38.0 maximum. Suggestions to upgrade to newer Stripe SDK versions should consider this limitation.
store/build.gradle (1)
Learnt from: rupesh-ps
PR: testpress/android-sdk#863
File: build.gradle:110-110
Timestamp: 2025-05-19T13:41:49.742Z
Learning: The project uses Kotlin 1.8.0 which has compatibility constraints with Stripe Android SDK, limiting it to version 20.38.0 maximum. Suggestions to upgrade to newer Stripe SDK versions should consider this limitation.
samples/build.gradle (1)
Learnt from: rupesh-ps
PR: testpress/android-sdk#863
File: build.gradle:110-110
Timestamp: 2025-05-19T13:41:49.742Z
Learning: The project uses Kotlin 1.8.0 which has compatibility constraints with Stripe Android SDK, limiting it to version 20.38.0 maximum. Suggestions to upgrade to newer Stripe SDK versions should consider this limitation.
course/build.gradle (1)
Learnt from: rupesh-ps
PR: testpress/android-sdk#863
File: build.gradle:110-110
Timestamp: 2025-05-19T13:41:49.742Z
Learning: The project uses Kotlin 1.8.0 which has compatibility constraints with Stripe Android SDK, limiting it to version 20.38.0 maximum. Suggestions to upgrade to newer Stripe SDK versions should consider this limitation.
course/src/main/res/values/strings.xml (1)
Learnt from: PruthiviRaj27
PR: testpress/android-sdk#904
File: exam/src/main/java/in/testpress/exam/api/ExamService.java:110-113
Timestamp: 2025-07-03T12:51:50.551Z
Learning: QuizExam in the course module does not have window monitoring features, so exam window violation related changes should not be applied to the course module.
🧬 Code Graph Analysis (2)
samples/src/main/java/in/testpress/samples/core/TestpressCoreSampleActivity.java (1)
core/src/main/java/in/testpress/core/TestpressSdk.java (1)
  • TestpressSdk (23-344)
samples/src/main/java/in/testpress/samples/store/StoreSampleActivity.java (1)
store/src/main/java/in/testpress/store/TestpressStore.java (1)
  • TestpressStore (18-114)
🔇 Additional comments (23)
course/build.gradle (1)

7-7: Namespace addition looks good

Explicit namespace is required from AGP 8+, and the value follows the module package convention.

build.gradle (1)

11-11: Bump Kotlin & Google-Services plugins to stay in-sync with AGP 8

AGP 8 requires JDK 17 and works best with Kotlin 1.9+. While only the AGP coordinate was updated, the rest of the tool-chain (Kotlin 1.8.0, com.google.gms:google-services:3.2.0) dates back years and will surface compatibility warnings.

Please verify CI’s JDK version and plan a coordinated tool-chain upgrade.

course/src/main/java/in/testpress/course/ui/VideoDownloadQualityChooserDialog.kt (1)

63-66: Correct resource-ID fix looks good

Switching to com.google.android.exoplayer2.ui.R.id.exo_track_selection_view aligns with the ExoPlayer library package and avoids duplicate IDs. No further action required.

samples/src/main/java/in/testpress/samples/exam/NavigationDrawerActivity.java (1)

27-36: LGTM – behavioural parity preserved

The new if-else chain mirrors the previous switch without side-effects.

course/src/main/res/drawable/testpress_difficulty_left_off.xml (1)

1-13: LGTM – drawable is minimal and correct.

Shape definition, color reference and corner radii are valid; no issues spotted.

core/build.gradle (1)

9-9: All modules now target Java 17—please verify CI/toolchain and transitive library compatibility

  • Verified: no occurrences of JavaVersion.VERSION_1_8; all modules (store, samples, core, course) set jvmTarget = JavaVersion.VERSION_17.toString().
  • Next steps:
    1. Ensure your CI environment and Gradle toolchain (Gradle wrapper/JDK) are updated to Java 17.
    2. Confirm that transitive libraries—especially Stripe SDK—remain bytecode-compatible. (Kotlin 1.8.0 limits Stripe to ≤20.38.0.)
    3. Run the full test suite to catch any other incompatibilities.
exam/build.gradle (1)

28-31: Ensure all transitive libraries are Java 17-compatible

Targeting JavaVersion.VERSION_17 can surface byte-code incompatibilities in older libs (e.g., annotation processors or byte-code weavers compiled for 1.6/1.8).

  1. Verify the full Gradle build on CI with --warning-mode all.
  2. Pay special attention to libraries that still publish only Java 8 class-files.
  3. The module still pulls kotlinStdlibJdk7; consider bumping to kotlin-stdlib (or kotlinStdlibJdk8) which better matches the new byte-code level.
course/src/main/java/in/testpress/course/util/TrackSelectionDialog.kt (2)

72-72: Good alignment with ExoPlayer's resource structure.

The change to use ExoPlayer's resource ID (com.google.android.exoplayer2.ui.R.id.exo_track_selection_view) instead of a local resource ID ensures consistency with ExoPlayer's UI components and prevents potential resource conflicts.


18-18: Local R import is still required

The in.testpress.course.R import is used on line 67 for R.string.quality_selector, so it should remain. No changes needed.

course/src/main/res/drawable/testpress_difficulty_right_on.xml (2)

1-13: Well-structured drawable resource.

The drawable definition is correct and follows Android standards. The right-side rounded corners (100dp radius) create a clean visual design suitable for difficulty level indicators.


5-5: Color resource verification complete

The @color/testpress_difficulty_level_5 resource is defined in course/src/main/res/values/color.xml (line 7). No further action required.

course/src/main/res/drawable/testpress_difficulty_right_off.xml (2)

1-13: Consistent drawable structure for off state.

The drawable definition correctly mirrors the "on" state version with appropriate color for the inactive/off state. The right-side rounded corners maintain visual consistency.


5-5: Color resource verified in core module

The color @color/testpress_text_gray_light is defined in core/src/main/res/values/color.xml (line 37), and also duplicated in exam/src/main/res/values/color.xml. The reference in course/src/main/res/drawable/testpress_difficulty_right_off.xml is valid. No further action required.

samples/src/main/java/in/testpress/samples/core/TestpressCoreSampleActivity.java (1)

122-123: Environment change from sandbox to lmsdemo.

The base URL and white-labeled host URL have been changed from the sandbox environment to the lmsdemo environment. Ensure this change is intentional and that the lmsdemo environment is appropriate for the sample application.

course/src/main/res/drawable/testpress_difficulty_left_on.xml (2)

1-13: Well-structured drawable resource for left-side rounding.

The drawable definition is correct and complements the right-side rounded drawables, creating a consistent set of UI elements for difficulty level indicators.


5-5: Color resource testpress_difficulty_level_1 exists

The color is defined in course/src/main/res/values/color.xml (line 3):

  • <color name="testpress_difficulty_level_1">#e65c6c</color>

No further action needed.

exam/src/main/res/menu/testpress_filter.xml (1)

5-11: No functional issues – looks good

The menu item correctly uses a string resource, a custom action layout, and is initially hidden.

course/src/main/res/layout/testpress_content_list_item.xml (1)

60-72: Child larger than its container

PieChart is 40 dp but its container is 26 dp, so it will be clipped. Either shrink the chart or enlarge the container.

-            android:layout_width="26dp"
-            android:layout_height="26dp"
+            android:layout_width="40dp"
+            android:layout_height="40dp"
course/src/main/res/layout/video_content_list_item.xml (1)

146-151: Placeholder ImageView left visible attribute

android:visibility="gone" combined with constraints can still take up space at run-time if toggled visible. Consider 0dp width/height with matchConstraint so it expands only when needed.

course/src/main/res/layout/exam_content_list_item.xml (1)

60-72: Lock container visibility="visible" defeats toggle

Other list-items default the lock badge to gone. Here it’s visible, causing locked badge on every exam row. Verify the intention and maybe default to gone.

exam/src/main/res/values/strings.xml (1)

321-322: HTML in string not marked with tools:ignore

<font size="14"> inside hint may be stripped by the HTML sanitizer on older APIs. Consider using CDATA or styling spans programmatically. If you keep it, add tools:ignore="TypographyQuotes" to silence lint.

core/src/main/res/values/strings.xml (2)

48-49: Placeholder missing for unlock time

account_unlock_info (l.48) ends with a space and no placeholder. If the text is meant to be dynamic add %s / %d (and possibly convert to a plurals) – otherwise translators will miss important context.


151-155: Misaligned messaging

testpress_pause_message (l.152) mentions “before the end date” – but the preceding button label reads “Yes, Pause!”. The warning might confuse users when no end date exists. Double-check business logic.

Comment on lines +30 to 35
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
jvmTarget = JavaVersion.VERSION_17.toString()
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Kotlin 1.8.0 + JVM 17 is an invalid combination

jvmTarget = 17 (and JavaVersion.VERSION_17) is only supported from Kotlin 1.9.0 (¹).
With the project still pinned to ext.kotlin_version = "1.8.0" the build will fail at compile time.

Quick fixes:

-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_17
-        targetCompatibility JavaVersion.VERSION_17
-    }
-    kotlinOptions {
-        jvmTarget = JavaVersion.VERSION_17.toString()
-    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_11
+        targetCompatibility JavaVersion.VERSION_11
+    }
+    kotlinOptions {
+        jvmTarget = "11"
+    }

or upgrade every module to Kotlin 1.9.x (and its matching Compose compiler).

(¹) see Kotlin release notes: https://kotlinlang.org/docs/whatsnew19.html#kotlin-jvm-target-17

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
jvmTarget = JavaVersion.VERSION_17.toString()
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
🤖 Prompt for AI Agents
In course/build.gradle around lines 30 to 35, the kotlinOptions.jvmTarget is set
to JavaVersion.VERSION_17, which requires Kotlin 1.9.0 or higher, but the
project is using Kotlin 1.8.0. To fix this, either downgrade jvmTarget to 1.8 to
match Kotlin 1.8.0 or upgrade the Kotlin version in the project to 1.9.x and
update all related modules and Compose compiler accordingly.

Comment on lines +113 to +114
authenticate("111",
"111", TestpressSdk.Provider.TESTPRESS);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace hardcoded credentials with more obvious placeholder values.

Using hardcoded credentials like "111" can be misleading and potentially dangerous if this sample code is copied to production. Consider using more obvious placeholder values like "SAMPLE_USER_ID" or "DEMO_ACCESS_TOKEN" to make it clear these are not real credentials.

-                    authenticate("111",
-                            "111", TestpressSdk.Provider.TESTPRESS);
+                    authenticate("SAMPLE_USER_ID",
+                            "SAMPLE_ACCESS_TOKEN", TestpressSdk.Provider.TESTPRESS);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
authenticate("111",
"111", TestpressSdk.Provider.TESTPRESS);
authenticate("SAMPLE_USER_ID",
"SAMPLE_ACCESS_TOKEN", TestpressSdk.Provider.TESTPRESS);
🤖 Prompt for AI Agents
In
samples/src/main/java/in/testpress/samples/core/TestpressCoreSampleActivity.java
around lines 113 to 114, replace the hardcoded credential strings "111" with
clear placeholder values such as "SAMPLE_USER_ID" and "DEMO_ACCESS_TOKEN" to
indicate these are example values and not real credentials, improving code
clarity and safety.

Comment on lines +6 to +10
<item android:id="@+id/search"
android:title="Search"
android:icon="@drawable/ic_baseline_search_24"
app:actionViewClass="android.widget.SearchView"
app:showAsAction="always" />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Hard-coded “Search” string breaks localisation

Use an existing string resource (e.g. @string/testpress_search) instead of the literal "Search". This avoids missed translations in non-English builds.

-    android:title="Search"
+    android:title="@string/testpress_search"
🤖 Prompt for AI Agents
In exam/src/main/res/menu/testpress_time_analytics_filter.xml around lines 6 to
10, the android:title attribute uses a hard-coded string "Search" which breaks
localization. Replace the literal "Search" with a reference to an existing
string resource such as @string/testpress_search to ensure proper translation
support in different languages.

android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:id="@+id/empty_title"
android:text="Network Error"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Hard-coded text breaks localisation

android:text="Network Error" should reference a string resource so the message can be translated.

-        android:text="Network Error"
+        android:text="@string/testpress_network_error"

Don’t forget to add the new key inside values/strings.xml.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
android:text="Network Error"
android:text="@string/testpress_network_error"
🤖 Prompt for AI Agents
In course/src/main/res/layout/testpress_empty_view.xml at line 23, replace the
hard-coded text attribute android:text="Network Error" with a reference to a
string resource, such as android:text="@string/network_error". Then, add the
corresponding string key "network_error" with the value "Network Error" inside
the values/strings.xml file to enable localization.

Comment on lines +241 to +244
TestpressCourse.showChapters(this, "Course Detail",
Integer.parseInt(text), session);
} else if (clickedButtonId == R.id.chapter_contents) {
String url = session.getInstituteSettings().getBaseUrl() +
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential crash on non-numeric Course ID

Integer.parseInt(text) will throw NumberFormatException if the user enters non-numeric input. Validate or catch and show an error toast before proceeding.

🤖 Prompt for AI Agents
In samples/src/main/java/in/testpress/samples/course/CourseSampleActivity.java
around lines 241 to 244, the code uses Integer.parseInt(text) without
validation, which can throw NumberFormatException if the input is non-numeric.
To fix this, add a try-catch block around Integer.parseInt(text) to catch
NumberFormatException and show an error toast to the user instead of proceeding,
or validate the input beforehand to ensure it is numeric before parsing.

Comment on lines +48 to +55
android:id="@+id/content_type_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:paddingBottom="10dp"
android:visibility="visible"
android:src="@drawable/test"/>

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Stub drawable reference will crash

android:src="@drawable/test" is clearly a placeholder. Building without an actual test.png/xml will fail with aapt error. Replace with the final icon or remove until asset is ready.

🤖 Prompt for AI Agents
In course/src/main/res/layout/exam_content_list_item.xml around lines 48 to 55,
the ImageView uses a placeholder drawable reference android:src="@drawable/test"
which will cause build errors if the drawable resource does not exist. Replace
this placeholder with the actual final drawable resource name or remove the
android:src attribute entirely until the correct asset is available to prevent
build failures.

Comment on lines +276 to +288
<string name="testpress_ok">OK</string>
<string name="testpress_cancel">Cancel</string>
<string name="testpress_no_internet_try_again">Please check your internet connection &amp; try again.</string>
<string name="testpress_tap_to_retry">Tap to retry</string>
<string name="testpress_authentication_failed">Authentication failed</string>
<string name="testpress_network_error">Network Error</string>
<string name="testpress_loading_failed">Loading Failed</string>
<string name="permission_denied">Permission Denied</string>
<string name="content_scheduled">This content is scheduled!</string>
<string name="testpress_no_permission">You do not have permission to view this.</string>
<string name="testpress_some_thing_went_wrong_try_again">Some thing went wrong, please try again later.</string>
<string name="testpress_error_loading_contents">Loading contents failed</string>
<string name="testpress_content_not_available">Content not available</string>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Duplicate / conflicting string keys

testpress_no_internet_connection (line 17) and new testpress_no_internet_try_again represent the same concept. Similarly permission_denied vs testpress_permission_denied. Consolidate to avoid translator confusion and dead keys.

🤖 Prompt for AI Agents
In exam/src/main/res/values/strings.xml around lines 276 to 288, there are
duplicate or conflicting string keys representing the same concepts, such as
'testpress_no_internet_connection' and 'testpress_no_internet_try_again', and
'permission_denied' versus 'testpress_permission_denied'. To fix this,
consolidate these duplicates by choosing a single consistent key for each
concept, remove the redundant keys, and update any references in the codebase to
use the consolidated keys to avoid confusion and dead entries.

Comment on lines +226 to +262
<string name="testpress_time_analytics">Time Analytics</string>

<string name="testpress_web_only_exam">Web Only Exam</string>
<string name="testpress_web_only_exam_description">This exam can only be attempted on the website.</string>
<string name="testpress_can_start_exam_only_after">You can attempt this exam only after \n%1$s</string>
<string name="testpress_score_good_in_previous_exam">You need to get good scores in the previous tests to attempt this test.</string>

<string name="testpress_strength">Strength</string>
<string name="testpress_weakness">Weakness</string>

<string name="testpress_strength_label">Strength / Correct</string>
<string name="testpress_weakness_label">Weakness / Incorrect</string>

<string name="testpress_individual_reports">Individual Reports</string>
<string name="testpress_overall_reports">Overall Reports</string>
<string name="testpress_subject_name">Subject</string>

<string name="testpress_no_questions_message">No questions added to this exam till now, Please check back later or contact administrator</string>

<string name="comments_title">Comments</string>
<string name="write_a_comment">Write a comment&#8230;</string>
<string name="load_previous_comments">Load previous comments</string>
<string name="load_new_comments">Load new comments</string>
<string name="load_comments">Load comments</string>
<string name="comment_posted">Comment posted successfully</string>
<string name="no_comments">Be the first to post a comment</string>
<plurals name="new_comments_available">
<item quantity="one">Tap to view a new comment</item>
<item quantity="other">Tap to view %d new comments</item>
</plurals>

<string name="testpress_test_completed_you_earned">Test completed!\nYou’ve earned</string>
<string name="testpress_okay">Okay</string>

<string name="testpress_continue">Continue</string>
<string name="testpress_time_analytics_label">Time Analytics</string>
<string name="testpress_incorrect_filter_text">Incorrect</string>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Duplicate key with conflicting wording

testpress_time_analytics (l.226) and testpress_time_analytics_label (l.261) refer to the same concept. Remove one or rename to clarify their different contexts before translators start producing diverging texts.

🤖 Prompt for AI Agents
In core/src/main/res/values/strings.xml between lines 226 and 262, the keys
testpress_time_analytics and testpress_time_analytics_label both refer to "Time
Analytics" but have different keys, which can confuse translators. To fix this,
either remove one of the keys if redundant or rename one to clearly
differentiate their contexts, ensuring the naming reflects their distinct usage
to avoid translation divergence.

Comment on lines +324 to +330
<string name="window_monitoring_warning_description">Before you proceed, please be aware:\n\n<b>WINDOW MONITORING IS ENABLED:</b> This exam monitors if you leave the app.\n\n<b>DO NOT SWITCH APPS:</b> If you minimize this app or switch to another app more than 2 times, your exam will be automatically ended.\n\nStay focused in the exam screen to avoid violations and complete your attempt without interruption. </string>

<string name="exam_combined_warning_description">Before you proceed, please be aware:\n\n<b>RESUME IS DISABLED:</b> The admin has disabled the resume feature for this exam. Once you begin, if you close or navigate away from this app, you will NOT be able to resume your attempt. Your attempt will be permanently ended.\n\n<b>WINDOW MONITORING IS ENABLED:</b> This exam monitors if you leave the app. Minimizing this app or switching to another app more than 2 times will automatically end your exam.\n\nEnsure you are ready to take the exam without any interruptions. Double-check your internet connection, silence notifications, and make sure your device has sufficient power. </string>
<string name="window_switch_detected_title">Window Switch Detected</string>
<string name="window_violation_warning">You switched apps %1$d time(s). Switching apps more than %2$d times will end the exam.</string>
<string name="exam_final_violation_message"><b>Violation Detected:</b> You have exceeded the maximum allowed interruptions during the assessment.\n\nThe system has recorded multiple interruptions, which may be caused by one or more of the following:\n1) Minimizing the app or switching to another app.\n2) Pressing restricted keys or attempting to access system features.\n3) Trying to leave the assessment screen.\n\n<b>Your exam will now be ended permanently.</b>\n\nYou will not be able to resume this attempt. Please contact your administrator if you believe this was a mistake.</string>
<string name="testpress_retake_with">Retake with?</string>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Very long HTML-rich strings – consider <xliff:g> placeholders or raw strings

The warning/violation messages (l.324-329) mix <b> tags, line breaks and numbered lists. This is error-prone for translators and hard to maintain. Break into smaller strings or use HTML templates assembled at runtime.

🤖 Prompt for AI Agents
In core/src/main/res/values/strings.xml around lines 324 to 330, the strings
contain complex HTML tags, line breaks, and numbered lists within single string
entries, making translation and maintenance difficult. Refactor by splitting
these long HTML-rich strings into smaller, simpler strings or use <xliff:g>
placeholders for dynamic parts, and assemble the full message with HTML
formatting at runtime in the code. This approach improves clarity for
translators and reduces errors.

Comment on lines +216 to +217
<string name="testpress_speech_recognition_not_supported">Opps! Your device doesn\'t support Speech to Text</string>

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Typo: “Opps!”

testpress_speech_recognition_not_supported (l.216) – should be “Oops!”

-    <string name="testpress_speech_recognition_not_supported">Opps! Your device doesn\'t support Speech to Text</string>
+    <string name="testpress_speech_recognition_not_supported">Oops! Your device doesn’t support Speech to Text</string>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<string name="testpress_speech_recognition_not_supported">Opps! Your device doesn\'t support Speech to Text</string>
<string name="testpress_speech_recognition_not_supported">Oops! Your device doesnt support Speech to Text</string>
🤖 Prompt for AI Agents
In core/src/main/res/values/strings.xml at line 216, correct the typo in the
string value for testpress_speech_recognition_not_supported by changing "Opps!"
to "Oops!" to fix the spelling error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants