@momo-kits/native-kits 0.162.1-beta.3-debug → 0.162.1-beta.4-debug
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +3 -19
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +5 -40
- package/gradle.properties +1 -1
- package/package.json +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationEvent.kt +0 -53
|
@@ -5,7 +5,6 @@ import androidx.compose.animation.core.tween
|
|
|
5
5
|
import androidx.compose.runtime.*
|
|
6
6
|
import androidx.compose.runtime.saveable.rememberSaveable
|
|
7
7
|
import androidx.compose.ui.unit.Dp
|
|
8
|
-
import androidx.navigation.NavController
|
|
9
8
|
import androidx.navigation.compose.NavHost
|
|
10
9
|
import androidx.navigation.compose.composable
|
|
11
10
|
import androidx.navigation.compose.rememberNavController
|
|
@@ -28,18 +27,11 @@ fun NavigationContainer(
|
|
|
28
27
|
setNavigator: ((Navigator) -> Unit)? = null,
|
|
29
28
|
statusBarHeight: Dp? = null,
|
|
30
29
|
config: KitConfig? = null,
|
|
31
|
-
language: String? = null
|
|
32
|
-
onNavigationEvent: ((NavigationEvent) -> Unit)? = null
|
|
30
|
+
language: String? = null
|
|
33
31
|
){
|
|
34
32
|
val navController = rememberNavController()
|
|
35
33
|
val registry = remember { DynamicScreenRegistry() }
|
|
36
|
-
val navigator = remember { Navigator(navController = navController, maxApi = maxApi, registry = registry
|
|
37
|
-
|
|
38
|
-
val recomposeCount = remember { mutableStateOf(0) }
|
|
39
|
-
SideEffect {
|
|
40
|
-
recomposeCount.value += 1
|
|
41
|
-
onNavigationEvent?.invoke(NavigationEvent.ContainerRecompose(recomposeCount.value))
|
|
42
|
-
}
|
|
34
|
+
val navigator = remember { Navigator(navController = navController, maxApi = maxApi, registry = registry) }
|
|
43
35
|
val statusBarHeight = statusBarHeight ?: getAppStatusBarHeight()
|
|
44
36
|
val navigationBarHeight = getNavigationBarHeight()
|
|
45
37
|
|
|
@@ -142,16 +134,8 @@ fun NavigationContainer(
|
|
|
142
134
|
}
|
|
143
135
|
}
|
|
144
136
|
|
|
145
|
-
DisposableEffect(
|
|
146
|
-
val listener = NavController.OnDestinationChangedListener { _, destination, _ ->
|
|
147
|
-
val current = registry.getLatestScreen()
|
|
148
|
-
onNavigationEvent?.invoke(
|
|
149
|
-
NavigationEvent.DestinationChanged(destination.route, current?.id, current?.name)
|
|
150
|
-
)
|
|
151
|
-
}
|
|
152
|
-
navController.addOnDestinationChangedListener(listener)
|
|
137
|
+
DisposableEffect(Unit) {
|
|
153
138
|
onDispose {
|
|
154
|
-
navController.removeOnDestinationChangedListener(listener)
|
|
155
139
|
navigator.dispose()
|
|
156
140
|
registry.unregisterScreen(screenId)
|
|
157
141
|
}
|
|
@@ -27,24 +27,10 @@ import kotlin.time.Duration.Companion.milliseconds
|
|
|
27
27
|
class Navigator(
|
|
28
28
|
private val navController: NavController,
|
|
29
29
|
private val maxApi: IMaxApi?,
|
|
30
|
-
private val registry: DynamicScreenRegistry
|
|
31
|
-
private val onNavigationEvent: ((NavigationEvent) -> Unit)? = null
|
|
30
|
+
private val registry: DynamicScreenRegistry
|
|
32
31
|
) {
|
|
33
32
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
|
34
33
|
|
|
35
|
-
private fun emit(event: NavigationEvent) {
|
|
36
|
-
onNavigationEvent?.invoke(event)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* The screen currently on top of THIS container's [navController] back stack.
|
|
41
|
-
*
|
|
42
|
-
* Use this instead of [DynamicScreenRegistry.getLatestScreen], which returns the globally
|
|
43
|
-
* last-registered screen across every NavigationContainer. With multiple containers sharing
|
|
44
|
-
* the single [DynamicScreenRegistry], the global "latest" is not guaranteed to belong to this
|
|
45
|
-
* navController, so back/dismiss/overlay logic could read the wrong options or unregister the
|
|
46
|
-
* wrong screen.
|
|
47
|
-
*/
|
|
48
34
|
private fun currentScreen(): DynamicScreen? {
|
|
49
35
|
val entry = navController.currentBackStackEntry ?: return null
|
|
50
36
|
val id = runCatching { entry.toRoute<DynamicScreenRoute>().id }.getOrNull()
|
|
@@ -55,18 +41,14 @@ class Navigator(
|
|
|
55
41
|
|
|
56
42
|
fun push(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
|
|
57
43
|
val route = registry.register(screenName, content, options)
|
|
58
|
-
emit(NavigationEvent.Push(screenName, route.id))
|
|
59
44
|
navController.navigate(DynamicScreenRoute(route.id))
|
|
60
45
|
}
|
|
61
46
|
|
|
62
47
|
fun replace(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
navController.popBackStack()
|
|
68
|
-
push(screenName, content, options)
|
|
69
|
-
}
|
|
48
|
+
val replacedScreen = currentScreen()
|
|
49
|
+
replacedScreen?.let { registry.unregisterScreen(it.id) }
|
|
50
|
+
navController.popBackStack()
|
|
51
|
+
push(screenName, content, options)
|
|
70
52
|
}
|
|
71
53
|
|
|
72
54
|
fun onBackSafe(callBack: (() -> Unit)? = null) {
|
|
@@ -97,7 +79,6 @@ class Navigator(
|
|
|
97
79
|
}
|
|
98
80
|
|
|
99
81
|
fun pop(count: Int = 1, callBack: (() -> Unit)? = null) {
|
|
100
|
-
emit(NavigationEvent.Pop(count, OverplayComponentRegistry.getOverplayType()))
|
|
101
82
|
scope.launch {
|
|
102
83
|
repeat(count) {
|
|
103
84
|
if (OverplayComponentRegistry.getOverplayType() == OverplayComponentType.SNACK_BAR){
|
|
@@ -121,8 +102,6 @@ class Navigator(
|
|
|
121
102
|
|
|
122
103
|
private suspend fun dismissScreen() {
|
|
123
104
|
if (navController.previousBackStackEntry != null){
|
|
124
|
-
// Capture the screen being dismissed BEFORE popping; after popBackStack the current
|
|
125
|
-
// entry is the revealed screen, so reading it post-pop would unregister the wrong one.
|
|
126
105
|
val dismissing = currentScreen()
|
|
127
106
|
navController.popBackStack()
|
|
128
107
|
delay(300L.milliseconds)
|
|
@@ -134,7 +113,6 @@ class Navigator(
|
|
|
134
113
|
|
|
135
114
|
fun present(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
|
|
136
115
|
val route = registry.register(screenName, content, options)
|
|
137
|
-
emit(NavigationEvent.Present(screenName, route.id))
|
|
138
116
|
navController.navigate(DynamicDialogRoute(route.id))
|
|
139
117
|
}
|
|
140
118
|
|
|
@@ -142,7 +120,6 @@ class Navigator(
|
|
|
142
120
|
registry.unregisterAll()
|
|
143
121
|
|
|
144
122
|
val route = registry.register(screenName, content, options)
|
|
145
|
-
emit(NavigationEvent.Reset(screenName, route.id))
|
|
146
123
|
navController.navigate(DynamicScreenRoute(route.id)) {
|
|
147
124
|
popUpTo(0) { inclusive = true }
|
|
148
125
|
}
|
|
@@ -154,7 +131,6 @@ class Navigator(
|
|
|
154
131
|
onDismiss: (() -> Unit)? = null
|
|
155
132
|
){
|
|
156
133
|
val id = currentScreen()?.id ?: -1
|
|
157
|
-
emit(NavigationEvent.ShowModal(id, barrierDismissible))
|
|
158
134
|
OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.MODAL, false, barrierDismissible, onDismiss)
|
|
159
135
|
}
|
|
160
136
|
|
|
@@ -166,13 +142,11 @@ class Navigator(
|
|
|
166
142
|
bottomSheetHeader: BottomHeader? = null
|
|
167
143
|
){
|
|
168
144
|
val id = currentScreen()?.id ?: -1
|
|
169
|
-
emit(NavigationEvent.ShowBottomSheet(id, barrierDismissible))
|
|
170
145
|
OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.BOTTOM_SHEET, isSurface, barrierDismissible, onDismiss, bottomSheetHeader)
|
|
171
146
|
}
|
|
172
147
|
|
|
173
148
|
fun showSnackBar(snackBar: SnackBar, onDismiss: (() -> Unit)? = null) {
|
|
174
149
|
val id = currentScreen()?.id ?: -1
|
|
175
|
-
emit(NavigationEvent.ShowSnackBar(id))
|
|
176
150
|
scope.launch {
|
|
177
151
|
OverplayComponentRegistry.registerOverplay(
|
|
178
152
|
id = id,
|
|
@@ -194,7 +168,6 @@ class Navigator(
|
|
|
194
168
|
}
|
|
195
169
|
|
|
196
170
|
fun dispose(){
|
|
197
|
-
emit(NavigationEvent.Dispose)
|
|
198
171
|
scope.cancel()
|
|
199
172
|
}
|
|
200
173
|
}
|
|
@@ -216,14 +189,6 @@ data class DynamicScreen(
|
|
|
216
189
|
var options: NavigationOptions? = null
|
|
217
190
|
)
|
|
218
191
|
|
|
219
|
-
/**
|
|
220
|
-
* Per-container store of dynamic screens. Each [NavigationContainer] owns its own instance, so the
|
|
221
|
-
* number of live containers no longer matters: `getLatestScreen`/`unregisterAll` only ever see the
|
|
222
|
-
* screens of their own container.
|
|
223
|
-
*
|
|
224
|
-
* Ids are still drawn from a process-wide counter so they stay globally unique — this keeps the
|
|
225
|
-
* still-global [OverplayComponentRegistry] (which keys overlays by screen id) collision-free.
|
|
226
|
-
*/
|
|
227
192
|
class DynamicScreenRegistry {
|
|
228
193
|
private val screens = mutableMapOf<Int, DynamicScreen>()
|
|
229
194
|
|
package/gradle.properties
CHANGED
package/package.json
CHANGED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.navigation
|
|
2
|
-
|
|
3
|
-
sealed class NavigationEvent {
|
|
4
|
-
abstract val label: String
|
|
5
|
-
|
|
6
|
-
data class Push(val screenName: String, val id: Int) : NavigationEvent() {
|
|
7
|
-
override val label get() = "Push(screen=$screenName, id=$id)"
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
data class Replace(val screenName: String, val id: Int) : NavigationEvent() {
|
|
11
|
-
override val label get() = "Replace(screen=$screenName, id=$id)"
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
data class Pop(val count: Int, val overlayType: OverplayComponentType?) : NavigationEvent() {
|
|
15
|
-
override val label get() = "Pop(count=$count, overlay=$overlayType)"
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
data class Present(val screenName: String, val id: Int) : NavigationEvent() {
|
|
19
|
-
override val label get() = "Present(screen=$screenName, id=$id)"
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
data class Reset(val screenName: String, val id: Int) : NavigationEvent() {
|
|
23
|
-
override val label get() = "Reset(screen=$screenName, id=$id)"
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
data class ShowModal(val parentId: Int, val barrierDismissible: Boolean) : NavigationEvent() {
|
|
27
|
-
override val label get() = "ShowModal(parentId=$parentId, barrierDismissible=$barrierDismissible)"
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
data class ShowBottomSheet(val parentId: Int, val barrierDismissible: Boolean) : NavigationEvent() {
|
|
31
|
-
override val label get() = "ShowBottomSheet(parentId=$parentId, barrierDismissible=$barrierDismissible)"
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
data class ShowSnackBar(val parentId: Int) : NavigationEvent() {
|
|
35
|
-
override val label get() = "ShowSnackBar(parentId=$parentId)"
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
data class DestinationChanged(
|
|
39
|
-
val route: String?,
|
|
40
|
-
val id: Int?,
|
|
41
|
-
val screenName: String?
|
|
42
|
-
) : NavigationEvent() {
|
|
43
|
-
override val label get() = "DestinationChanged(route=$route, id=$id, screen=$screenName)"
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
data class ContainerRecompose(val recomposeCount: Int) : NavigationEvent() {
|
|
47
|
-
override val label get() = "ContainerRecompose(count=$recomposeCount)"
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
object Dispose : NavigationEvent() {
|
|
51
|
-
override val label get() = "Dispose"
|
|
52
|
-
}
|
|
53
|
-
}
|