Skip to content

Conversation

@gino-m
Copy link
Collaborator

@gino-m gino-m commented Jan 28, 2026

Migrates SyncStatusFragment to Compose. Part 2 of 3.

Towards #1795

This PR migrates the Sync Status screen to Jetpack Compose, removing legacy XML layouts.
@auto-assign auto-assign bot requested a review from anandwana001 January 28, 2026 22:23
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gino-m, 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 represents the second phase of migrating the SyncStatus feature to Jetpack Compose. It significantly modernizes the UI implementation by replacing the traditional Android View system with a fully declarative Compose UI. The changes streamline the fragment's code, introduce a dedicated Composable screen for better separation of concerns, and update the testing approach to align with Compose best practices.

Highlights

  • UI Migration to Compose: The SyncStatusFragment has been refactored to fully utilize Jetpack Compose for its UI, replacing the previous XML-based layout.
  • New Compose Screen: A dedicated SyncStatusScreen.kt file has been introduced to encapsulate the Compose UI for displaying synchronization statuses, promoting better modularity.
  • XML Layout Removal: The sync_status_frag.xml layout file has been removed, signifying a complete transition of this UI component to Compose.
  • Updated UI Testing: The corresponding UI tests in SyncStatusFragmentTest have been updated to use Jetpack Compose testing APIs, moving away from Espresso for toolbar assertions.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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 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. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

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

Footnotes

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

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request successfully migrates SyncStatusFragment to Jetpack Compose by replacing the XML layout with a ComposeView and introducing a new SyncStatusScreen composable. The implementation is clean and follows modern Android practices. However, I've identified a critical issue in gradle.properties where a hardcoded local path has been added, which will break the build for other developers. Additionally, I've provided a few suggestions to improve the new Compose code for better performance, testability, and readability.

# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
org.gradle.java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

This hardcoded, absolute path for org.gradle.java.home is specific to a single developer's machine and should not be committed to version control. It will cause build failures for other team members on different operating systems or with different Android Studio installation paths. This setting should be configured locally by each developer, for example in the local.properties file (which is typically ignored by Git) or as an environment variable.

Comment on lines 48 to 58
return androidx.compose.ui.platform.ComposeView(requireContext()).apply {
setViewCompositionStrategy(
androidx.compose.ui.platform.ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
)
setContent {
org.groundplatform.android.ui.theme.AppTheme {
val list by viewModel.uploadStatus.observeAsState(emptyList())
SyncStatusScreen(uploadStatuses = list, onBack = { findNavController().navigateUp() })
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

To improve code readability, it's better to import the classes used here instead of using their fully qualified names. Please add imports for androidx.compose.ui.platform.ComposeView, androidx.compose.ui.platform.ViewCompositionStrategy, and org.groundplatform.android.ui.theme.AppTheme.

Suggested change
return androidx.compose.ui.platform.ComposeView(requireContext()).apply {
setViewCompositionStrategy(
androidx.compose.ui.platform.ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
)
setContent {
org.groundplatform.android.ui.theme.AppTheme {
val list by viewModel.uploadStatus.observeAsState(emptyList())
SyncStatusScreen(uploadStatuses = list, onBack = { findNavController().navigateUp() })
}
}
}
return ComposeView(requireContext()).apply {
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
)
setContent {
AppTheme {
val list by viewModel.uploadStatus.observeAsState(emptyList())
SyncStatusScreen(uploadStatuses = list, onBack = { findNavController().navigateUp() })
}
}
}

Comment on lines +57 to +59
items(uploadStatuses) {
SyncListItem(modifier = Modifier.semantics { testTag = "item ${it.user}" }, detail = it)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Here are a couple of suggestions to improve this LazyColumn implementation:

  1. Provide a unique key: For better performance and to prevent potential issues with state when the list is modified, it's a best practice to provide a unique key for each item. Since SyncStatusDetail doesn't have a unique ID field, you can compose a key from its existing properties.

  2. Ensure unique testTag: The testTag is generated using only the user's name, which is not guaranteed to be unique if a user has multiple items. This could lead to flaky UI tests. A more robust testTag can be created from a combination of fields like label and subtitle.

      items(
        items = uploadStatuses,
        key = { "${it.timestamp.time}-${it.label}-${it.subtitle}" }
      ) {
        SyncListItem(
          modifier = Modifier.semantics { testTag = "item ${it.label} ${it.subtitle}" },
          detail = it
        )
      }

@gino-m gino-m removed the request for review from anandwana001 January 28, 2026 22:28
@gino-m gino-m marked this pull request as draft January 28, 2026 22:28
@codecov
Copy link

codecov bot commented Jan 29, 2026

Codecov Report

❌ Patch coverage is 96.66667% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 69.87%. Comparing base (6597d13) to head (7512b2d).

Files with missing lines Patch % Lines
...platform/android/ui/syncstatus/SyncStatusScreen.kt 95.23% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3488      +/-   ##
============================================
+ Coverage     69.82%   69.87%   +0.05%     
+ Complexity     1599     1597       -2     
============================================
  Files           322      323       +1     
  Lines          8678     8693      +15     
  Branches        949      949              
============================================
+ Hits           6059     6074      +15     
  Misses         2049     2049              
  Partials        570      570              
Files with missing lines Coverage Δ
...atform/android/ui/syncstatus/SyncStatusFragment.kt 100.00% <100.00%> (+4.54%) ⬆️
...tform/android/ui/syncstatus/SyncStatusViewModel.kt 78.04% <100.00%> (ø)
...java/org/groundplatform/android/util/ComposeExt.kt 75.00% <ø> (ø)
...platform/android/ui/syncstatus/SyncStatusScreen.kt 95.23% <95.23%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

1 participant