Skip to content

Conversation

tuancoltech
Copy link
Member

@tuancoltech tuancoltech commented May 14, 2025

Issue Number

  • Resolves #

Purpose

Use Jetpack Compose in MainActivity instead of XML layout

Technical Details

Screenshots

Testing Instructions

Regression Tests

  • I tested my changes on Android 16 (API 36)
  • I tested my changes on Android 15 (API 35)
  • I tested my changes on Android 14 (API 34)
  • I tested my changes on Android 13 (API 33)
  • I tested my changes on Android 12L (API 32)
  • I tested my changes on Android 12 (API 31)
  • I tested my changes on Android 11 (API 30)
  • I tested my changes on Android 10 (API 29)
  • I tested my changes on Android 9 (API 28)
  • I tested my changes on Android 8.1 (API 27)
  • I tested my changes on Android 8.0 (API 26)

UI Tests

  • I tested my changes on a 6-7" screen (▯ portrait orientation)
  • I tested my changes on a 6-7" screen (▭ landscape orientation)
  • I tested my changes on a 7-8" screen (▯ portrait orientation)
  • I tested my changes on a 7-8" screen (▭ landscape orientation)
  • I tested my changes on a 9-10" screen (▯ portrait orientation)
  • I tested my changes on a 9-10" screen (▭ landscape orientation)

Content Tests

  • I tested my changes with English content (eng.elimu.ai)
  • I tested my changes with Hindi content (hin.elimu.ai)
  • I tested my changes with Tagalog content (tgl.elimu.ai)
  • I tested my changes with Thai content (tha.elimu.ai)
  • I tested my changes with Vietnamese content (vie.elimu.ai)

Summary by CodeRabbit

  • New Features
    • Introduced Jetpack Compose for building the app’s user interface, replacing the previous XML-based layout in the main screen.
    • The main screen now uses a modern Material3 design and improved theming.
  • Refactor
    • Updated the main activity to use a Compose-based implementation for UI and logic flow.
  • Chores
    • Updated build configuration and dependencies to support Jetpack Compose.

@tuancoltech tuancoltech requested a review from a team as a code owner May 14, 2025 06:57
@tuancoltech tuancoltech self-assigned this May 14, 2025
Copy link

coderabbitai bot commented May 14, 2025

Walkthrough

This update migrates the Android app’s main UI from XML layouts and view binding to Jetpack Compose, updating build configurations and dependencies to support Compose. The MainActivity now uses a declarative Compose-based UI and handles package checks via Compose side effects. Compose dependencies are added to the build and version catalog.

Changes

File(s) Change Summary
app/build.gradle Enabled Jetpack Compose support in build features, specified Compose compiler extension version, and added Compose-related dependencies for UI, Material3, tooling, activity, and ViewModel integration.
gradle/libs.versions.toml Added version and library entries for Jetpack Compose components, including UI, Material3, activity, lifecycle, and compiler, to the version catalog for dependency management.
app/src/main/java/ai/elimu/vitabu/MainActivity.kt Refactored MainActivity from AppCompatActivity with XML view binding to ComponentActivity using a Compose-based UI. Introduced VitabuTheme and MainScreen composables, moved package check logic into a Compose side effect, and removed imperative UI and lifecycle code.
build.gradle Added Compose compiler plugin alias in the top-level plugins block; no other functional changes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MainActivity
    participant MainScreen (Composable)
    participant ensurePackageInstalledOrPrompt
    participant StoryBooksActivity

    User->>MainActivity: Launch app
    MainActivity->>MainScreen: Set Compose content
    MainScreen->>ensurePackageInstalledOrPrompt: On first composition (LaunchedEffect)
    ensurePackageInstalledOrPrompt-->>MainScreen: Return package check result
    MainScreen->>MainActivity: Invoke onPackageCheck callback
    alt Package present
        MainActivity->>StoryBooksActivity: Start activity
        MainActivity->>MainActivity: Finish self
    else Package missing
        MainScreen->>User: Prompt for installation (handled in ensurePackageInstalledOrPrompt)
    end
Loading

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • jo-elimu

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1064e63 and a9af28b.

📒 Files selected for processing (4)
  • app/build.gradle (3 hunks)
  • app/src/main/java/ai/elimu/vitabu/MainActivity.kt (1 hunks)
  • build.gradle (1 hunks)
  • gradle/libs.versions.toml (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • build.gradle
  • app/build.gradle
  • app/src/main/java/ai/elimu/vitabu/MainActivity.kt
  • gradle/libs.versions.toml
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: test (28)
  • GitHub Check: build (windows-latest, 21)
  • GitHub Check: build (ubuntu-latest, 21)
  • GitHub Check: build (ubuntu-latest, 17)
  • GitHub Check: build (macos-latest, 21)
  • GitHub Check: build (macos-latest, 17)
  • GitHub Check: build (windows-latest, 17)
  • GitHub Check: test (29)
  • GitHub Check: lint
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.

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: 0

🧹 Nitpick comments (3)
app/src/main/java/ai/elimu/vitabu/MainActivity.kt (3)

43-53: Theme implementation could be enhanced.

The current VitabuTheme implementation uses default Material theming without customization. Consider enhancing it with app-specific colors, typography, and support for dark theme.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.

@Composable
-fun VitabuTheme(content: @Composable () -> Unit) {
-    MaterialTheme {
+fun VitabuTheme(
+    darkTheme: Boolean = isSystemInDarkTheme(),
+    dynamicColor: Boolean = true,
+    content: @Composable () -> Unit
+) {
+    val colorScheme = when {
+        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
+            val context = LocalContext.current
+            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
+        }
+        darkTheme -> VitabuDarkColorScheme
+        else -> VitabuLightColorScheme
+    }
+    
+    MaterialTheme(
+        colorScheme = colorScheme,
+        typography = VitabuTypography,
+    ) {
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colorScheme.background
        ) {
            content()
        }
    }
}

55-73: Consider enhancing MainScreen with loading state.

The MainScreen implementation works but lacks visual feedback during the package check. Consider adding a loading indicator and handling different states.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.

@Composable
fun MainScreen(onPackageCheck: (Boolean) -> Unit) {
    val context = LocalContext.current
+    var isChecking by remember { mutableStateOf(true) }
    
    // Empty Box as container - the UI is minimal since this is just a launcher activity
    Box(modifier = Modifier.fillMaxSize()) {
+        if (isChecking) {
+            CircularProgressIndicator(
+                modifier = Modifier.align(Alignment.Center)
+            )
+        }
+        
        // Check for required package when the composable is first launched
        LaunchedEffect(key1 = Unit) {
            val hasPackage = ensurePackageInstalledOrPrompt(
                packageName = BuildConfig.CONTENT_PROVIDER_APPLICATION_ID,
                launchPackage = BuildConfig.APPSTORE_APPLICATION_ID,
                launchClass = "ai.elimu.appstore.MainActivity",
                dialogMessage = context.resources.getString(R.string.content_provider_needed),
                buttonText = context.getString(R.string.install)
            )
+            isChecking = false
            onPackageCheck(hasPackage)
        }
    }
}

63-69: Avoid hardcoded class name references.

The full path to "ai.elimu.appstore.MainActivity" is hardcoded. Consider using a constant or BuildConfig value to make it easier to maintain.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.

val hasPackage = ensurePackageInstalledOrPrompt(
    packageName = BuildConfig.CONTENT_PROVIDER_APPLICATION_ID,
    launchPackage = BuildConfig.APPSTORE_APPLICATION_ID,
-    launchClass = "ai.elimu.appstore.MainActivity",
+    launchClass = BuildConfig.APPSTORE_MAIN_ACTIVITY_CLASS,
    dialogMessage = context.resources.getString(R.string.content_provider_needed),
    buttonText = context.getString(R.string.install)
)

You would also need to add this constant to your buildConfigField in app/build.gradle:

buildConfigField("String", "APPSTORE_APPLICATION_ID", '"ai.elimu.appstore"')
+buildConfigField("String", "APPSTORE_MAIN_ACTIVITY_CLASS", '"ai.elimu.appstore.MainActivity"')
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 665f92a and bd78cef.

📒 Files selected for processing (3)
  • app/build.gradle (2 hunks)
  • app/src/main/java/ai/elimu/vitabu/MainActivity.kt (1 hunks)
  • gradle/libs.versions.toml (2 hunks)
🔇 Additional comments (8)
gradle/libs.versions.toml (2)

36-43: Good organization of Compose dependencies.

The library declarations properly reference the version declarations, making future updates easier to manage. The organization with comments helps maintain clarity in the version catalog.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.


16-21:

❓ Verification inconclusive

Jetpack Compose versions look appropriate, but verify compatibility with other components.

The added Compose version declarations are reasonable choices for this migration, but it's always good practice to ensure version compatibility across the ecosystem, especially with your Kotlin version (2.1.21).

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.


🌐 Web query:

Are Jetpack Compose versions 1.5.4 (UI), 1.1.2 (Material3), and compiler 1.5.3 compatible with Kotlin 2.1.21?

💡 Result:

Jetpack Compose versions 1.5.4 (UI), 1.1.2 (Material3), and compiler 1.5.3 are compatible with Kotlin 1.9.10. However, Kotlin 2.1.21 is a newer version, and there is no official information confirming compatibility between these specific versions of Jetpack Compose and Kotlin 2.1.21.

Starting with Kotlin 2.0.0, the Compose compiler has been integrated into the Kotlin repository, ensuring that the Compose compiler version matches the Kotlin version. This integration simplifies the setup and ensures compatibility between Compose and Kotlin versions. (android-developers.googleblog.com)

Given that Kotlin 2.1.21 is a newer release, it's advisable to check the official Jetpack Compose and Kotlin documentation or release notes for any updates regarding compatibility. If no information is available, consider testing your project with Kotlin 2.1.21 to identify any potential issues.

Citations:


Verify Compose–Kotlin compatibility

The selected Jetpack Compose versions (1.5.4 UI, 1.1.2 Material3, 1.5.3 compiler) are officially supported on Kotlin 1.9.10, but there’s no published confirmation for Kotlin 2.1.21. Since Kotlin 2.0.0 integrates the Compose compiler into the Kotlin repo—meaning the compiler plugin version should match your Kotlin version—please:

  • Check the official Jetpack Compose and Kotlin release notes for any updates on Kotlin 2.x support.
  • Ensure composeCompiler = "1.5.3" is compatible with Kotlin 2.1.21 or update it to the matching version.
  • Run a full local build and exercise your Compose UI to catch any runtime or compile-time issues.

File to review:

  • gradle/libs.versions.toml (lines 16–21)

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.

app/build.gradle (4)

48-48: Jetpack Compose enabled correctly.

Properly enabling Compose in the build features is essential for the migration. Note that you're keeping viewBinding enabled as well, which is good for a gradual migration approach.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.


51-53: Compose compiler version properly configured.

Using the version reference from the version catalog ensures consistency across the project.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.


75-82: Complete set of Compose dependencies added.

All necessary dependencies for Jetpack Compose are included, with proper separation between implementation and debugImplementation for tooling. This follows best practices to keep release APK size optimized.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.


87-87: Compose UI testing dependency correctly added.

Adding the Compose UI test dependency to androidTestImplementation is appropriate and will enable testing of the Compose UI components.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.

app/src/main/java/ai/elimu/vitabu/MainActivity.kt (2)

19-19: Correctly extending ComponentActivity.

ComponentActivity is the appropriate base class for Compose-based UIs, replacing AppCompatActivity.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.


27-39: Clean transition to Compose content.

The setContent approach is well-structured with proper separation of concerns. The callback pattern for handling the package check result is a good approach.

elimu.ai's mission is to build innovative learning software that empowers out-of-school children to teach themselves basic reading📖, writing✍🏽 and math🔢 within 6 months.

@tuancoltech tuancoltech force-pushed the replace_xml_layout_with_jetpack_compose_main_acativity branch 3 times, most recently from e33083f to 3dc1477 Compare May 14, 2025 10:00
@jo-elimu
Copy link
Member

image

@tuancoltech Since this change adds 71 lines of code, is it an improvement of maintainability? (If we want to make it easy for other engineers to modify the code in the future.)

@jo-elimu jo-elimu marked this pull request as draft May 14, 2025 14:28
@tuancoltech tuancoltech force-pushed the replace_xml_layout_with_jetpack_compose_main_acativity branch from 3dc1477 to 1064e63 Compare May 15, 2025 03:13
@tuancoltech tuancoltech force-pushed the replace_xml_layout_with_jetpack_compose_main_acativity branch from 1064e63 to a9af28b Compare May 15, 2025 03:18
@tuancoltech
Copy link
Member Author

tuancoltech commented May 15, 2025

image

@tuancoltech Since this change adds 71 lines of code, is it an improvement of maintainability? (If we want to make it easy for other engineers to modify the code in the future.)

@jo-elimu I have been trying to switch from XML layout to using Jetpack Compose for MainActivity.
It's been claimed that Jetpack compose reduces boiler plate code and enhances the drawing UI performance in general.
However, for this specific MainActivity, it's introducing many more lines of codes.
Also, it seems that we're having compatibility issue which causes build error at the moment.
So let's ignore it for now.

@jo-elimu
Copy link
Member

@tuancoltech Got it, thanks for clarifying.

If we move away from using XML files for the app layout, will we no longer have access to see the UI preview/visualizations in Android Studio?

@tuancoltech
Copy link
Member Author

@tuancoltech Got it, thanks for clarifying.

If we move away from using XML files for the app layout, will we no longer have access to see the UI preview/visualizations in Android Studio?

@jo-elimu We still can see the UI crafted via @Preview annotation provided by Compose library.

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