Skip to content

Migrate Jetchat from Fragment Navigation to Navigation 3 - #1732

Merged
raystatic merged 9 commits into
mainfrom
nav3migration
Oct 16, 2026
Merged

raystatic merged 9 commits into
mainfrom
nav3migration

Conversation

@raystatic

Copy link
Copy Markdown
Contributor

Migrates Jetchat's navigation from Fragments and XML NavHostFragment to Nav3.

Before

  • NavActivity (AppCompatActivity) hosted an XML NavHostFragment (content_main.xml + mobile_navigation.xml) via AndroidViewBinding.
  • ConversationFragment and ProfileFragment wrapped Compose screens inside ComposeViews and communicated drawer events through MainViewModel.

After

  • NavActivity (ComponentActivity) hosts ConversationContent and ProfileScreen directly in a Navigation 3 NavDisplay backed by rememberNavBackStack(Conversation).
  • Destinations are defined as type-safe @Serializable NavKeys (Conversation and Profile(userId)), with ViewModels scoped per entry via rememberViewModelStoreNavEntryDecorator().
  • Removes ConversationFragment, ProfileFragment, MainViewModel, XML navigation/layout resources, and legacy Fragment/viewBinding dependencies.

@raystatic
raystatic requested a review from a team as a code owner October 14, 2026 00:23
@raystatic
raystatic requested a review from dturner October 14, 2026 00:23
@raystatic
raystatic requested a review from riggaroo October 14, 2026 00:53
@raystatic
raystatic marked this pull request as draft October 14, 2026 08:53
Comment on lines +84 to +87
predictivePopTransitionSpec = {
slideInHorizontally(initialOffsetX = { -it }) togetherWith
slideOutHorizontally(targetOffsetX = { it })
},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Lets keep these as the defaults - or try to emulate our specs for predictive back - ie scale the content down instead of slide

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Screen_recording_20261016_190441.mp4

with defaults, I felt the motions between screens were not consistent, that's why I added custom specs there.

But if keeping defaults is what we recommend in these cases, I will remove them

@compose-devrel-github-bot

Copy link
Copy Markdown
Contributor

⚡ Jetpack Compose Performance Review

No Jetpack Compose performance issues were found in the changed code.

Summary of Diff Analysis

  • JetchatApp.kt: State reads and state mutations adhere to unidirectional data flow and Compose lifecycle guidelines. Side effects and coroutines (scope.launch) are strictly triggered in event callbacks (onNavigate, onNavIconPressed), preventing backwards writes. Transition specifications (slideInHorizontally, slideOutHorizontally) properly use lambda offsets, deferring calculations to the Layout phase. ViewModel lifecycle decorators and state scoping are correctly configured using Navigation 3 decorators (rememberSaveableStateHolderNavEntryDecorator, rememberViewModelStoreNavEntryDecorator).
  • JetchatDrawer.kt & JetchatScaffold.kt: Vector drawables are rendered using Icon with tint rather than unoptimized bitmap loaders. State comparisons (selected = key == selectedKey) are computed directly and cached locally per drawer item.
  • JetchatNavKeys.kt: Navigation key models (Conversation, Profile) are defined as flat Kotlin data classes containing immutable primitive val properties, which the Compose compiler automatically infers as stable under Strong Skipping Mode without needing unnecessary @Stable or @Immutable annotations.
  • NavActivity.kt & ConversationViewModel.kt: Activity setup and ViewModel state declarations follow standard Compose patterns without redundant composition-phase state wrappers or main-thread blocking operations.

@raystatic
raystatic marked this pull request as ready for review October 16, 2026 13:49
@raystatic
raystatic enabled auto-merge October 16, 2026 14:13
@raystatic
raystatic merged commit 5f2f2cf into main Oct 16, 2026
10 of 11 checks passed
@raystatic
raystatic deleted the nav3migration branch October 16, 2026 14:15
@compose-devrel-github-bot

Copy link
Copy Markdown
Contributor

⚡ Jetpack Compose Performance Review

No Jetpack Compose performance issues were found in the changed code.

Summary of Audit

The newly introduced and modified code in .gemini/pr_diff.patch was reviewed against all performance categories (Categories 1–7):

  • State, Snapshots & Stability (Category 1): The navigation data models (Conversation, Profile) are small, flat data classes containing primitive val String properties, which the Compose compiler automatically infers as stable without requiring redundant @Immutable annotations. Navigation state derivation (selectedKey = backStack.last()) is correctly handled, and no backwards writes or redundant state wrappers were introduced.
  • Layouts & Measurements (Category 2): Layout nodes in JetchatApp, JetchatDrawer, and JetchatDrawerContent maintain a clean, shallow tree hierarchy without decorative wrapper boxes, unneeded Canvas elements, or layout measurement feedback loops.
  • Lazy Layouts (Category 3): No lazy layouts (LazyColumn, LazyRow, LazyGrid) were introduced or modified in this change.
  • Animation & Shared Transitions (Category 4): No animated properties or shared transition scopes were modified.
  • Effects, Lifecycle & Threading (Category 5): Composition bodies are idempotent and free of direct side effects. Coroutine operations (drawerState.open(), drawerState.close()) are cleanly confined to user event callbacks (onNavIconPressed, onNavigate). observeAsState() correctly binds LiveData updates to composition.
  • Graphics & Custom Drawing (Category 6): In DrawerHeader, Image was appropriately replaced with Icon for a surface-tinted vector asset (jetchat_logo), adhering to Compose drawing best practices.
  • Custom Modifiers (Category 7): No custom modifiers were added or altered.

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.

3 participants