-
Notifications
You must be signed in to change notification settings - Fork 103
Split app to 2 screens with Navigation3 and NavigationStack #73
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
Conversation
This commit introduces the following changes: **Android App:** - Implemented basic navigation between `ListScreen` and a new `CartScreen` using Navigation 3. - `ListScreen` now displays a "View Cart" button showing the item count. - `CartScreen` is a new Composable that displays the items in the cart. **iOS App:** - Updated `ContentView` to include a navigation link to `CartView`. - The "View Cart" link on `ContentView` now displays the cart item count. - `CartView` now directly observes `cartViewModel.cartUiState`. - Removed the expand/collapse functionality from `CartView` and made `CartDetailsView` always visible within a `ScrollView`. **Shared Code:** - Introduced a new `CartViewModel` to manage the state of the shopping cart, separating concerns from `MainViewModel`. - `MainViewModel`'s `HomeUiState` now includes `cartItemCount`. The previous `cartUiState` and its direct cart details have been removed from `MainViewModel`. - Renamed `IOSViewModelOwner` to `IOSViewModelStoreOwner` and updated its methods to provide `MainViewModel` and `CartViewModel`. - Updated Android compile SDK to 36. - Added Kotlinx Serialization plugin. **Dependency Updates:** - Added `androidx.navigation3` and `kotlinx-serialization-core` dependencies.
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 @cartland, 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 significantly enhances the application's architecture by introducing multi-screen navigation on both Android and iOS platforms. It achieves this by separating the cart's business logic into a dedicated ViewModel in the shared module, leading to cleaner code and improved maintainability. The UI has been adapted on both platforms to support these new navigation flows and display relevant cart information.
Highlights
- Multi-Screen Navigation Implementation: Introduced multi-screen navigation for both Android and iOS applications. Android now uses Navigation3 to navigate between a
ListScreen
and a newCartScreen
, while iOS utilizesNavigationStack
to linkContentView
to a newCartView
. - Cart Logic Separation and ViewModel Refactoring: Extracted cart-specific state management and logic into a new
CartViewModel
within the shared Kotlin Multiplatform module. This refactorsMainViewModel
to focus solely on the main list functionality, withHomeUiState
now including only thecartItemCount
. - Platform-Specific UI Adjustments: Updated Android's
ListScreen
to remove direct cart display and integrate with the new navigation flow, simplifyingFruittieItem
UI. On iOS,CartView
was refactored to directly observe the newCartViewModel
and its cart details are now always visible within aScrollView
, removing previous expand/collapse functionality. - Dependency and SDK Updates: Upgraded the Android compile SDK to 36 across both the Android app and shared modules. Added necessary
androidx.navigation3
andkotlinx-serialization-core
dependencies, and updated iOS deployment target to 16.6.
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 splits the UI into two screens, ListScreen
/ContentView
and CartScreen
/CartView
, for Android and iOS respectively, and introduces CartViewModel
to separate concerns. The use of Navigation3 and NavigationStack
is a welcome improvement.
Suggestions include refining the navigation logic, improving UI performance by reducing redundant observers, and enhancing maintainability by centralizing state calculations in the ViewModel.
entry<CartScreenKey> { | ||
CartScreen( | ||
onNavBarBack = { | ||
backStack.removeIf { it is CartScreenKey } |
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.
@@ -110,34 +97,33 @@ fun ListScreen() { | |||
) { paddingValues -> | |||
Column( | |||
modifier = Modifier | |||
.padding(horizontal = 16.dp) |
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.
The padding(horizontal = 16.dp)
is redundant because start = 16.dp
and end = 16.dp
are set in the subsequent padding
modifier. Remove the first padding
call.
modifier = Modifier
// Support edge-to-edge (required on Android 15)
// https://developer.android.com/develop/ui/compose/layouts/insets#inset-size
.padding(
// Draw to bottom edge. LazyColumn adds a Spacer for WindowInsets.systemBars.
// No bottom padding.
top = paddingValues.calculateTopPadding(),
start = 16.dp,
end = 16.dp,
)
Observing(mainViewModel.homeUiState) { homeUIState in | ||
ScrollView { | ||
LazyVStack { | ||
ForEach(homeUIState.fruitties, id: \.self) { value in | ||
FruittieView(fruittie: value, addToCart: { fruittie in | ||
Task { | ||
mainViewModel.addItemToCart(fruittie: fruittie) | ||
} | ||
}) | ||
} | ||
}) | ||
} | ||
} | ||
} |
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 are two Observing
calls on the same mainViewModel.homeUiState
. This creates two subscriptions to the same flow. Use a single Observing
block that wraps the views that depend on the state.
NavigationStack {
VStack {
Text("Fruitties").font(.largeTitle).fontWeight(.bold)
Observing(mainViewModel.homeUiState) { homeUIState in
NavigationLink {
CartView(cartViewModel: cartViewModel)
} label: {
let total = homeUIState.cartItemCount
Text("View Cart (\(total))")
}
ScrollView {
LazyVStack {
ForEach(homeUIState.fruitties, id: \.self) { value in
FruittieView(fruittie: value, addToCart: { fruittie in
Task {
mainViewModel.addItemToCart(fruittie: fruittie)
}
})
}
}
}
}
}
}
val cartUiState: StateFlow<CartUiState> = | ||
repository.cartDetails | ||
.map { CartUiState(it) } | ||
.stateIn( | ||
scope = viewModelScope, | ||
started = SharingStarted.WhileSubscribed(TIMEOUT_MILLIS), | ||
initialValue = CartUiState(), | ||
) |
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.
Calculate the total item count here and store it in the CartUiState
to avoid duplicate calculations in both Android and iOS UI code.
You'll also need to update CartUiState
(at lines 67-69) to include the totalItemCount
property:
data class CartUiState(
val cartDetails: List<CartItemDetails> = listOf(),
val totalItemCount: Int = 0,
)
val cartUiState: StateFlow<CartUiState> =
repository.cartDetails
.map { details ->
CartUiState(
cartDetails = details,
totalItemCount = details.sumOf { it.count }
)
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(TIMEOUT_MILLIS),
initialValue = CartUiState(),
)
This commit refactors the calculation of the total number of items in the cart. Previously, the total item count was calculated independently in both the Android `CartScreen.kt` and iOS `CartView.swift`. This change moves the calculation into the shared `CartViewModel.kt`. A new `totalItemCount` property is added to `CartUiState`, which is now populated within the `map` function that transforms the `repository.cartDetails` flow. This centralization simplifies the UI components and ensures consistency in how the total item count is determined across platforms.
This commit introduces the following changes:
Android App:
ListScreen
and a newCartScreen
using Navigation 3.ListScreen
now displays a "View Cart" button showing the item count.CartScreen
is a new Composable that displays the items in the cart.iOS App:
ContentView
to include a navigation link toCartView
.ContentView
now displays the cart item count.CartView
now directly observescartViewModel.cartUiState
.CartView
and madeCartDetailsView
always visible within aScrollView
.Shared Code:
CartViewModel
to manage the state of the shopping cart, separating concerns fromMainViewModel
.MainViewModel
'sHomeUiState
now includescartItemCount
. The previouscartUiState
and its direct cart details have been removed fromMainViewModel
.IOSViewModelOwner
toIOSViewModelStoreOwner
and updated its methods to provideMainViewModel
andCartViewModel
.Dependency Updates:
androidx.navigation3
andkotlinx-serialization-core
dependencies.