-
Couldn't load subscription status.
- Fork 1
Upgrade to Java/Kotlin 17, add UI resources, and refactor code structure #913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
WalkthroughThis 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
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
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this 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, andsamplesmodules have been updated to Java 17. This ensures compatibility with the latest Android development environment and leverages newer language features. - Android Namespace Migration: Explicit
namespacedeclarations have been added to thebuild.gradlefiles for thecore,course,exam, andsamplesmodules. 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, andexammodules. 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
switchstatements intoif-else ifblocks in several navigation and SDK demonstration activities. This is a minor code style improvement for consistency and readability. - Stripe Payment Integration Enhancement: In the
storemodule, 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
-
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. ↩
There was a problem hiding this 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
contentDescriptionin 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.
| authenticate("111", | ||
| "111", TestpressSdk.Provider.TESTPRESS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this 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 commentLine 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
- You have both
permission_denied(l.14) andtestpress_permission_denied(l.40) conveying the same idea → pick one key name and remove the other to avoid translation drift.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+. Useandroid:textSizein the view or<string name="hint"><![CDATA[<b>…]]></string>with a span instead.
22-23: Leading space in keyvideo_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 incourse/.../testpress_empty_view_with_image.xml(missingcontentDescription, 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 duplicatesSee 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 valuesHard-coding colors here makes global theming harder (e.g. dark-mode, brand re-skin).
Consider moving these to@color/...entries (as was done forcb_dark_greyearlier) 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 checksumIt’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
distributionSha256Sumentry for supply-chain integrity.store/src/main/res/values/color.xml (1)
1-4: Expand 3-digit hex for readability & consistency
#777is 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: PreferrequireView()and delete commented-out code
- The non-null assertion
view!!can crash at runtime;requireView()is the safe equivalent afteronViewCreated.- Leaving the
exo_durationline 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.GONEstore/build.gradle (1)
8-35: Verify Java 17 migration across tool-chain & dependenciesUpgrading 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_HOME17; 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 scanGiven six mutually-exclusive constants, the original
switch/case(or a modernif-elsewith 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#FFFFFFtovalues/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 defensiveelse/ default branch.The previous
switchhandled any unknown item via its default clause; the newif-elsechain silently ignores unexpected IDs.
Consider adding anelselogging branch (or delegating tosuper) 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.
showSDKonly enters the first branch whenclickedButtonId == R.id.store, yet no caller passes that ID (they usenew_activity_button).
Either:
- Change the first comparison to
R.id.new_activity_button, or- Pass
R.id.storefrom 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 & concisenessThe new
if-elsechain 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
elsebranches, automatically handlesbreak, 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 referenceskotlinStdlibJdk7. 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) orkotlin-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 boilerplateYou 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 styleDirect 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: PreferConstraintLayoutoverRelativeLayoutfor flatter, more performant hierarchies
ConstraintLayouteliminates the need for nestedRelativeLayouts, 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
- Size
45dpis hard-coded; reference a dimension resource (@dimen/testpress_loader_size) for consistency across densities.- Add
android:contentDescription="@string/testpress_loading"(orandroid: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_primaryand@color/testpress_color_primary_bluehave 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: Deprecatedlayout_marginRighthampers RTL support
layout_marginRightis ignored in RTL locales; you already specifylayout_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-codedlayout_marginRight
android:layout_marginRightis ignored in RTL layouts from API 17 onward.
Rely solely onlayout_marginStart/layout_marginEnd(ormarginEndalone 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 explicitcontentDescriptionfor accessibilityIndeterminate 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@nullexplicitly to suppress warnings from accessibility lint.- <ProgressBar + <ProgressBar + android:contentDescription="@null"course/src/main/res/layout/testpress_actionbar_spinner.xml (1)
7-12: MissingcontentDescriptionon interactive controlBecause
ClosableSpinneris an interactive widget, it should have a meaningfulandroid:contentDescription(orandroid:promptif 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 marginsSame concern as the large loading layout: replace
layout_marginRightwithlayout_marginStart/layout_marginEnd.- android:layout_marginRight="10dp" - android:layout_marginEnd="10dp" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp"
9-14: SpecifycontentDescriptionAdd
android:contentDescription="@null"(or a descriptive string) to avoid accessibility-lint warnings.course/src/main/res/layout/testpress_empty_view.xml (1)
43-48: AddcontentDescriptionto the retry buttonButtons without a label announced by TalkBack rely entirely on
android:text. If the text changes programmatically, set an explicitcontentDescriptionorandroid:labelForto guarantee accessibility.samples/src/main/java/in/testpress/samples/course/CourseSampleActivity.java (1)
202-219: Duplicate flag configuration & missingdownloadsbranchThe two branches repeat identical
setBookmarksEnabled,setCommentsVotingEnabled, andsetCoursesFrontendcalls, differing only insetCoursesGamificationEnabled(). Extract common setters and keep the delta to one line.
downloadsisn’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 deltaConsider 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: ConsidermaxLengthto guard against excessively long inputIf 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:orientationattribute is ignored on RelativeLayout
RelativeLayoutdoesn’t useandroid:orientation; leaving it confuses future readers.- android:orientation="vertical"
19-24: Put indeterminate drawable via style to avoid repeated attributesEmbedding 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 resourceInline colors hinder theming. Declare in
colors.xml(maybetestpress_divider_color) and reference it.- android:background="#ccc" /> + android:background="@color/testpress_divider_color" />
28-32: Consider migrating to ViewPager2
androidx.viewpager.widget.ViewPageris 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 completePaymentSheet.Configuration
PaymentSheet.Configurationalso lets you specifymerchantDisplayName, default billing address, etc. You already pass the app name—good—but you should also setallowsDelayedPaymentMethodsaccording 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: MovePaymentConfiguration.initto Application classStripe 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 meaninglessandroid:orientationfromRelativeLayout.
RelativeLayoutignores theorientationattribute – 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.
#aaffffffshould live incolors.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 fromstrings.xml.Real data will be bound at runtime; keep the layout neutral:
-android:text="Jan 25, 2017" +tools:text="Jan 25, 2017"Using
tools:textkeeps sample data in preview only.Also applies to: 82-90
63-67: UsemarginEndand 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:orientationis ignored onRelativeLayout.Remove the attribute; it can confuse future readers.
exam/src/main/res/layout/testpress_empty_view.xml (1)
22-26: Move “Network Error” string tostrings.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_primaryandtestpress_color_primary_blueare 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:orientationis ignored on RelativeLayout
RelativeLayoutdoes not honorandroid:orientation; remove it to avoid confusion.exam/src/main/res/layout/testpress_list.xml (1)
56-56: Redundant namespace declaration
xmlns:androidis re-declared onSwipeRefreshLayout. It is harmless but noisy—recommend dropping it.store/src/main/res/layout/testpress_empty_view.xml (1)
11-17: No placeholder image set
ImageViewlacks atools:srcsample or a defaultandroid:src, so design-time preview is blank.
Addtools: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 withtools:textThese literal strings will ship if the view is accidentally inflated before being overridden. Use
tools:textto 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:orientationattribute has no effect onRelativeLayoutDrop it to avoid misleading future readers.
- android:orientation="vertical"> + >
60-97: Mixed use of drawable and solid colour backgroundsMiddle 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.xmldrawables 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_placholderis 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 migratingRelativeLayouttoConstraintLayout
ConstraintLayoutremoves 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:androidis re-declared insideSwipeRefreshLayout. 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 / Threatsprobably meantTargets / Threads.- <string name="testpress_targets_or_threads">Targets / Threats</string> + <string name="testpress_targets_or_threads">Targets / Threads</string>
63-63: Spelling error
Download Descrition→Download 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.SwipeRefreshLayoutre-declaresxmlns: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.SwipeRefreshLayoutcourse/src/main/res/layout/content_list_item.xml (2)
30-47: Hard-coded colour & dimensions
android:background="#CAC8C8"and fixed155dp/87dpmake the thumbnail non-theming and non-scalable.
Turn the grey into a color resource (e.g.,@color/testpress_placeholder_bg) and move sizes todimens.xml.
90-97: Ineffective layout_gravity inside ConstraintLayout
android:gravity="end|bottom"on aLinearLayoutthat is constrained withapp: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 attributesThe horizontal
ProgressBaruses default colour which may clash with the app theme. Setandroid:progressTint/android:indeterminateTintvia theme attr to respect dark/light mode.
120-140: Duplicate lock-icon container implementationThe 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 missingcontentDescriptionThese 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
Gotoshould beGo tofor 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 %swith a comment explaining the second placeholder for translators.
78-88: Branding / style consistency
Testpress Exam Sdk(l.79) → “SDK” is an acronym; capitalise:Testpress Exam SDK.testpress_coursevstestpress_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 stringsYou 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) vstestpress_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%sbut 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) useswon\'t, others use straight'. Android handles both but consistency helps translators’ memory tools.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (17)
course/src/main/res/drawable/crown.pngis excluded by!**/*.pngcourse/src/main/res/drawable/ic_bookmark.pngis excluded by!**/*.pngcourse/src/main/res/drawable/ic_error_outline_black_18dp.pngis excluded by!**/*.pngcourse/src/main/res/drawable/ic_file_download_18dp.pngis excluded by!**/*.pngcourse/src/main/res/drawable/ic_remove_bookmark.pngis excluded by!**/*.pngcourse/src/main/res/drawable/testpress_alert_warning.pngis excluded by!**/*.pngcourse/src/main/res/drawable/testpress_attachment_content_icon.pngis excluded by!**/*.pngcourse/src/main/res/drawable/testpress_bookmark_flat_icon.pngis excluded by!**/*.pngcourse/src/main/res/drawable/testpress_ebook_content_icon.pngis excluded by!**/*.pngcourse/src/main/res/drawable/testpress_exam_icon.pngis excluded by!**/*.pngcourse/src/main/res/drawable/testpress_no_wifi.pngis excluded by!**/*.pngcourse/src/main/res/drawable/testpress_profile_image_place_holder.pngis excluded by!**/*.pngcourse/src/main/res/drawable/testpress_question_content_icon.pngis excluded by!**/*.pngcourse/src/main/res/drawable/testpress_video_content_icon.pngis excluded by!**/*.pngexam/src/main/res/drawable/testpress_alert_warning.pngis excluded by!**/*.pngexam/src/main/res/drawable/testpress_no_wifi.pngis excluded by!**/*.pngstore/src/main/res/drawable/ic_error_outline_black_18dp.pngis 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 goodExplicit
namespaceis 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 8AGP 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 goodSwitching to
com.google.android.exoplayer2.ui.R.id.exo_track_selection_viewaligns 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 preservedThe 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) setjvmTarget = JavaVersion.VERSION_17.toString().- Next steps:
- Ensure your CI environment and Gradle toolchain (Gradle wrapper/JDK) are updated to Java 17.
- Confirm that transitive libraries—especially Stripe SDK—remain bytecode-compatible. (Kotlin 1.8.0 limits Stripe to ≤20.38.0.)
- Run the full test suite to catch any other incompatibilities.
exam/build.gradle (1)
28-31: Ensure all transitive libraries are Java 17-compatibleTargeting
JavaVersion.VERSION_17can surface byte-code incompatibilities in older libs (e.g., annotation processors or byte-code weavers compiled for 1.6/1.8).
- Verify the full Gradle build on CI with
--warning-mode all.- Pay special attention to libraries that still publish only Java 8 class-files.
- The module still pulls
kotlinStdlibJdk7; consider bumping tokotlin-stdlib(orkotlinStdlibJdk8) 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 requiredThe
in.testpress.course.Rimport is used on line 67 forR.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 completeThe
@color/testpress_difficulty_level_5resource is defined incourse/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 moduleThe color
@color/testpress_text_gray_lightis defined incore/src/main/res/values/color.xml(line 37), and also duplicated inexam/src/main/res/values/color.xml. The reference incourse/src/main/res/drawable/testpress_difficulty_right_off.xmlis 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 resourcetestpress_difficulty_level_1existsThe 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 goodThe 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
PieChartis 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. Consider0dpwidth/height withmatchConstraintso it expands only when needed.course/src/main/res/layout/exam_content_list_item.xml (1)
60-72: Lock containervisibility="visible"defeats toggleOther list-items default the lock badge to
gone. Here it’svisible, causing locked badge on every exam row. Verify the intention and maybe default togone.exam/src/main/res/values/strings.xml (1)
321-322: HTML in string not marked with tools:ignore
<font size="14">insidehintmay be stripped by the HTML sanitizer on older APIs. Consider usingCDATAor styling spans programmatically. If you keep it, addtools: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 aplurals) – 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.
| sourceCompatibility JavaVersion.VERSION_17 | ||
| targetCompatibility JavaVersion.VERSION_17 | ||
| } | ||
| kotlinOptions { | ||
| jvmTarget = JavaVersion.VERSION_1_8.toString() | ||
| jvmTarget = JavaVersion.VERSION_17.toString() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| authenticate("111", | ||
| "111", TestpressSdk.Provider.TESTPRESS); |
There was a problem hiding this comment.
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.
| 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.
| <item android:id="@+id/search" | ||
| android:title="Search" | ||
| android:icon="@drawable/ic_baseline_search_24" | ||
| app:actionViewClass="android.widget.SearchView" | ||
| app:showAsAction="always" /> |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| TestpressCourse.showChapters(this, "Course Detail", | ||
| Integer.parseInt(text), session); | ||
| } else if (clickedButtonId == R.id.chapter_contents) { | ||
| String url = session.getInstituteSettings().getBaseUrl() + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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"/> | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| <string name="testpress_ok">OK</string> | ||
| <string name="testpress_cancel">Cancel</string> | ||
| <string name="testpress_no_internet_try_again">Please check your internet connection & 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> |
There was a problem hiding this comment.
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.
| <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…</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> |
There was a problem hiding this comment.
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.
| <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> |
There was a problem hiding this comment.
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.
| <string name="testpress_speech_recognition_not_supported">Opps! Your device doesn\'t support Speech to Text</string> | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| <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> |
🤖 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.
Changes done
Reason for the changes
Fixes # .
Summary by CodeRabbit
New Features
Refactor
Bug Fixes
Chores