Skip to content

Commit d8a27a2

Browse files
committed
refactor: Migrate navigation to nav3
1 parent 1f00462 commit d8a27a2

File tree

78 files changed

+3926
-3471
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+3926
-3471
lines changed

app/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ dependencies {
234234
implementation(libs.navigation.compose)
235235
androidTestImplementation(libs.navigation.testing)
236236
implementation(libs.hilt.navigation.compose)
237+
// Navigation 3
238+
implementation(libs.navigation3.runtime)
239+
implementation(libs.navigation3.ui)
237240
// Hilt - DI
238241
implementation(libs.hilt.android)
239242
ksp(libs.hilt.android.compiler)

app/detekt-baseline.xml

Lines changed: 6 additions & 16 deletions
Large diffs are not rendered by default.

app/src/main/java/to/bitkit/ui/ContentView.kt

Lines changed: 110 additions & 1739 deletions
Large diffs are not rendered by default.

app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import androidx.compose.ui.text.style.TextOverflow
2929
import androidx.compose.ui.tooling.preview.Preview
3030
import androidx.compose.ui.unit.dp
3131
import androidx.lifecycle.compose.collectAsStateWithLifecycle
32-
import androidx.navigation.NavController
3332
import org.lightningdevkit.ldknode.BalanceDetails
3433
import org.lightningdevkit.ldknode.BalanceSource
3534
import org.lightningdevkit.ldknode.BestBlock
@@ -58,6 +57,7 @@ import to.bitkit.ui.components.VerticalSpacer
5857
import to.bitkit.ui.components.rememberMoneyText
5958
import to.bitkit.ui.components.settings.SectionHeader
6059
import to.bitkit.ui.components.settings.SettingsTextButtonRow
60+
import to.bitkit.ui.nav.Navigator
6161
import to.bitkit.ui.scaffold.AppTopBar
6262
import to.bitkit.ui.scaffold.DrawerNavIcon
6363
import to.bitkit.ui.scaffold.ScreenColumn
@@ -72,7 +72,7 @@ import kotlin.time.ExperimentalTime
7272

7373
@Composable
7474
fun NodeInfoScreen(
75-
navController: NavController,
75+
navigator: Navigator,
7676
) {
7777
val wallet = walletViewModel ?: return
7878
val app = appViewModel ?: return
@@ -87,7 +87,7 @@ fun NodeInfoScreen(
8787
uiState = uiState,
8888
isDevModeEnabled = isDevModeEnabled,
8989
balanceDetails = lightningState.balances,
90-
onBack = { navController.popBackStack() },
90+
onBack = { navigator.goBack() },
9191
onRefresh = { wallet.onPullToRefresh() },
9292
onDisconnectPeer = { wallet.disconnectPeer(it) },
9393
onCopy = { text ->

app/src/main/java/to/bitkit/ui/components/AuthCheckScreen.kt

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,62 @@ package to.bitkit.ui.components
33
import androidx.compose.runtime.Composable
44
import androidx.compose.runtime.getValue
55
import androidx.lifecycle.compose.collectAsStateWithLifecycle
6-
import androidx.navigation.NavController
7-
import androidx.navigation.navOptions
8-
import to.bitkit.ui.Routes
9-
import to.bitkit.ui.appViewModel
10-
import to.bitkit.ui.settingsViewModel
6+
import to.bitkit.ui.nav.Navigator
7+
import to.bitkit.ui.nav.Routes
8+
import to.bitkit.viewmodels.AppViewModel
9+
import to.bitkit.viewmodels.SettingsViewModel
1110

1211
@Composable
1312
fun AuthCheckScreen(
14-
navController: NavController,
13+
navigator: Navigator,
1514
route: Routes.AuthCheck,
15+
appViewModel: AppViewModel,
16+
settingsViewModel: SettingsViewModel,
1617
) {
17-
val app = appViewModel ?: return
18-
val settings = settingsViewModel ?: return
19-
20-
val isPinOnLaunchEnabled by settings.isPinOnLaunchEnabled.collectAsStateWithLifecycle()
21-
val isBiometricEnabled by settings.isBiometricEnabled.collectAsStateWithLifecycle()
22-
val isPinOnIdleEnabled by settings.isPinOnIdleEnabled.collectAsStateWithLifecycle()
23-
val isPinForPaymentsEnabled by settings.isPinForPaymentsEnabled.collectAsStateWithLifecycle()
18+
val isPinOnLaunchEnabled by settingsViewModel.isPinOnLaunchEnabled.collectAsStateWithLifecycle()
19+
val isBiometricEnabled by settingsViewModel.isBiometricEnabled.collectAsStateWithLifecycle()
20+
val isPinOnIdleEnabled by settingsViewModel.isPinOnIdleEnabled.collectAsStateWithLifecycle()
21+
val isPinForPaymentsEnabled by settingsViewModel.isPinForPaymentsEnabled.collectAsStateWithLifecycle()
2422

2523
AuthCheckView(
2624
showLogoOnPin = route.showLogoOnPin,
27-
appViewModel = app,
28-
settingsViewModel = settings,
25+
appViewModel = appViewModel,
26+
settingsViewModel = settingsViewModel,
2927
requireBiometrics = route.requireBiometrics,
3028
requirePin = route.requirePin,
3129
onSuccess = {
3230
when (route.onSuccessActionId) {
3331
AuthCheckAction.TOGGLE_BIOMETRICS -> {
34-
settings.setIsBiometricEnabled(!isBiometricEnabled)
35-
navController.popBackStack()
32+
settingsViewModel.setIsBiometricEnabled(!isBiometricEnabled)
33+
navigator.goBack()
3634
}
3735

3836
AuthCheckAction.TOGGLE_PIN_ON_LAUNCH -> {
39-
settings.setIsPinOnLaunchEnabled(!isPinOnLaunchEnabled)
40-
navController.popBackStack()
37+
settingsViewModel.setIsPinOnLaunchEnabled(!isPinOnLaunchEnabled)
38+
navigator.goBack()
4139
}
4240

4341
AuthCheckAction.TOGGLE_PIN_ON_IDLE -> {
44-
settings.setIsPinOnIdleEnabled(!isPinOnIdleEnabled)
45-
navController.popBackStack()
42+
settingsViewModel.setIsPinOnIdleEnabled(!isPinOnIdleEnabled)
43+
navigator.goBack()
4644
}
4745

4846
AuthCheckAction.TOGGLE_PIN_FOR_PAYMENTS -> {
49-
settings.setIsPinForPaymentsEnabled(!isPinForPaymentsEnabled)
50-
navController.popBackStack()
47+
settingsViewModel.setIsPinForPaymentsEnabled(!isPinForPaymentsEnabled)
48+
navigator.goBack()
5149
}
5250

5351
AuthCheckAction.DISABLE_PIN -> {
54-
app.removePin()
55-
navController.popBackStack()
52+
appViewModel.removePin()
53+
navigator.goBack()
5654
}
5755

5856
AuthCheckAction.NAV_TO_RESET -> {
59-
navController.navigate(
60-
route = Routes.ResetAndRestoreSettings,
61-
navOptions = navOptions { popUpTo(Routes.BackupSettings) }
62-
)
57+
navigator.navigateToResetAndRestoreSettings()
6358
}
6459
}
6560
},
66-
onBack = { navController.popBackStack() },
61+
onBack = { navigator.goBack() },
6762
)
6863
}
6964

app/src/main/java/to/bitkit/ui/components/DrawerMenu.kt

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import androidx.compose.material3.DrawerValue
2323
import androidx.compose.material3.HorizontalDivider
2424
import androidx.compose.material3.Icon
2525
import androidx.compose.material3.Text
26-
import androidx.compose.material3.rememberDrawerState
2726
import androidx.compose.runtime.Composable
2827
import androidx.compose.runtime.remember
2928
import androidx.compose.runtime.rememberCoroutineScope
@@ -38,14 +37,9 @@ import androidx.compose.ui.tooling.preview.Preview
3837
import androidx.compose.ui.unit.dp
3938
import androidx.compose.ui.unit.sp
4039
import androidx.compose.ui.zIndex
41-
import androidx.navigation.NavController
42-
import androidx.navigation.NavDestination.Companion.hasRoute
43-
import androidx.navigation.compose.rememberNavController
4440
import kotlinx.coroutines.launch
4541
import to.bitkit.R
46-
import to.bitkit.ui.Routes
47-
import to.bitkit.ui.navigateIfNotCurrent
48-
import to.bitkit.ui.navigateToHome
42+
import to.bitkit.ui.nav.Navigator
4943
import to.bitkit.ui.shared.modifiers.clickableAlpha
5044
import to.bitkit.ui.shared.util.blockPointerInputPassthrough
5145
import to.bitkit.ui.theme.AppThemeSurface
@@ -61,7 +55,7 @@ private val drawerWidth = 200.dp
6155
@Composable
6256
fun DrawerMenu(
6357
drawerState: DrawerState,
64-
rootNavController: NavController,
58+
navigator: Navigator,
6559
hasSeenWidgetsIntro: Boolean,
6660
hasSeenShopIntro: Boolean,
6761
modifier: Modifier = Modifier,
@@ -95,36 +89,57 @@ fun DrawerMenu(
9589
.blockPointerInputPassthrough()
9690
)
9791
) {
98-
Menu(
99-
rootNavController = rootNavController,
100-
drawerState = drawerState,
101-
onClickAddWidget = {
92+
MenuContent(
93+
onWalletClick = {
94+
if (!navigator.isAtHome()) navigator.navigateToHome()
95+
scope.launch { drawerState.close() }
96+
},
97+
onActivityClick = {
98+
navigator.navigateToAllActivity()
99+
scope.launch { drawerState.close() }
100+
},
101+
onContactsClick = null, // TODO IMPLEMENT CONTACTS
102+
onProfileClick = null, // TODO IMPLEMENT PROFILE
103+
onWidgetsClick = {
102104
if (!hasSeenWidgetsIntro) {
103-
rootNavController.navigateIfNotCurrent(Routes.WidgetsIntro)
105+
navigator.navigateToWidgetsIntro()
104106
} else {
105-
rootNavController.navigateIfNotCurrent(Routes.AddWidget)
107+
navigator.navigateToAddWidget()
106108
}
109+
scope.launch { drawerState.close() }
107110
},
108-
onClickShop = {
111+
onShopClick = {
109112
if (!hasSeenShopIntro) {
110-
rootNavController.navigateIfNotCurrent(Routes.ShopIntro)
113+
navigator.navigateToShopIntro()
111114
} else {
112-
rootNavController.navigateIfNotCurrent(Routes.ShopDiscover)
115+
navigator.navigateToShopDiscover()
113116
}
117+
scope.launch { drawerState.close() }
118+
},
119+
onSettingsClick = {
120+
navigator.navigateToSettings()
121+
scope.launch { drawerState.close() }
122+
},
123+
onAppStatusClick = {
124+
navigator.navigateToAppStatus()
125+
scope.launch { drawerState.close() }
114126
},
115127
)
116128
}
117129
}
118130

131+
@Suppress("LongParameterList")
119132
@Composable
120-
private fun Menu(
121-
rootNavController: NavController,
122-
drawerState: DrawerState,
123-
onClickAddWidget: () -> Unit,
124-
onClickShop: () -> Unit,
133+
private fun MenuContent(
134+
onWalletClick: () -> Unit,
135+
onActivityClick: () -> Unit,
136+
onContactsClick: (() -> Unit)?,
137+
onProfileClick: (() -> Unit)?,
138+
onWidgetsClick: () -> Unit,
139+
onShopClick: () -> Unit,
140+
onSettingsClick: () -> Unit,
141+
onAppStatusClick: () -> Unit,
125142
) {
126-
val scope = rememberCoroutineScope()
127-
128143
Column(
129144
modifier = Modifier
130145
.width(drawerWidth)
@@ -137,65 +152,49 @@ private fun Menu(
137152
DrawerItem(
138153
label = stringResource(R.string.wallet__drawer__wallet),
139154
iconRes = R.drawable.ic_coins,
140-
onClick = {
141-
val isInHome = rootNavController.currentBackStackEntry?.destination?.hasRoute<Routes.Home>() ?: false
142-
if (!isInHome) rootNavController.navigateToHome()
143-
scope.launch { drawerState.close() }
144-
},
155+
onClick = onWalletClick,
145156
modifier = Modifier.testTag("DrawerWallet")
146157
)
147158

148159
DrawerItem(
149160
label = stringResource(R.string.wallet__drawer__activity),
150161
iconRes = R.drawable.ic_heartbeat,
151-
onClick = {
152-
rootNavController.navigateIfNotCurrent(Routes.AllActivity)
153-
scope.launch { drawerState.close() }
154-
},
162+
onClick = onActivityClick,
155163
modifier = Modifier.testTag("DrawerActivity")
156164
)
157165

158166
DrawerItem(
159167
label = stringResource(R.string.wallet__drawer__contacts),
160168
iconRes = R.drawable.ic_users,
161-
onClick = null, // TODO IMPLEMENT CONTACTS
169+
onClick = onContactsClick,
162170
modifier = Modifier.testTag("DrawerContacts")
163171
)
164172

165173
DrawerItem(
166174
label = stringResource(R.string.wallet__drawer__profile),
167175
iconRes = R.drawable.ic_user_square,
168-
onClick = null, // TODO IMPLEMENT PROFILE
176+
onClick = onProfileClick,
169177
modifier = Modifier.testTag("DrawerProfile")
170178
)
171179

172180
DrawerItem(
173181
label = stringResource(R.string.wallet__drawer__widgets),
174182
iconRes = R.drawable.ic_stack,
175-
onClick = {
176-
onClickAddWidget()
177-
scope.launch { drawerState.close() }
178-
},
183+
onClick = onWidgetsClick,
179184
modifier = Modifier.testTag("DrawerWidgets")
180185
)
181186

182187
DrawerItem(
183188
label = stringResource(R.string.wallet__drawer__shop),
184189
iconRes = R.drawable.ic_store_front,
185-
onClick = {
186-
onClickShop()
187-
scope.launch { drawerState.close() }
188-
},
190+
onClick = onShopClick,
189191
modifier = Modifier.testTag("DrawerShop")
190192
)
191193

192194
DrawerItem(
193195
label = stringResource(R.string.wallet__drawer__settings),
194196
iconRes = R.drawable.ic_settings,
195-
onClick = {
196-
rootNavController.navigateIfNotCurrent(Routes.Settings)
197-
scope.launch { drawerState.close() }
198-
},
197+
onClick = onSettingsClick,
199198
modifier = Modifier.testTag("DrawerSettings")
200199
)
201200

@@ -205,10 +204,7 @@ private fun Menu(
205204
contentAlignment = Alignment.Center,
206205
modifier = Modifier
207206
.fillMaxWidth()
208-
.clickableAlpha {
209-
rootNavController.navigateIfNotCurrent(Routes.AppStatus)
210-
scope.launch { drawerState.close() }
211-
}
207+
.clickableAlpha(onClick = onAppStatusClick)
212208
) {
213209
AppStatus(
214210
showText = true,
@@ -297,14 +293,16 @@ private fun DrawerItem(
297293
@Composable
298294
private fun Preview() {
299295
AppThemeSurface {
300-
val navController = rememberNavController()
301296
Box {
302-
DrawerMenu(
303-
rootNavController = navController,
304-
drawerState = rememberDrawerState(initialValue = DrawerValue.Open),
305-
hasSeenWidgetsIntro = false,
306-
hasSeenShopIntro = false,
307-
modifier = Modifier.align(Alignment.TopEnd),
297+
MenuContent(
298+
onWalletClick = {},
299+
onActivityClick = {},
300+
onContactsClick = null,
301+
onProfileClick = null,
302+
onWidgetsClick = {},
303+
onShopClick = {},
304+
onSettingsClick = {},
305+
onAppStatusClick = {},
308306
)
309307
}
310308
}

0 commit comments

Comments
 (0)