@momo-kits/native-kits 0.160.1-scrolltotop.12-debug → 0.160.1-scrolltotop.13-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/build.gradle.kts +1 -1
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +55 -11
- package/example/ios/Example.xcodeproj/xcuserdata/thanhle.xcuserdatad/xcschemes/xcschememanagement.plist +5 -0
- package/example/ios/Example.xcworkspace/xcuserdata/thanhle.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Example.xcworkspace/xcuserdata/thanhle.xcuserdatad/xcschemes/xcschememanagement.plist +5 -0
- package/gradle.properties +1 -1
- package/local.properties +8 -0
- package/package.json +1 -1
- package/publish.sh +0 -0
package/compose/build.gradle.kts
CHANGED
|
@@ -3,12 +3,33 @@ package vn.momo.kits.navigation
|
|
|
3
3
|
import androidx.compose.runtime.Composable
|
|
4
4
|
import androidx.compose.runtime.DisposableEffect
|
|
5
5
|
import androidx.compose.runtime.remember
|
|
6
|
+
import kotlin.time.Clock
|
|
7
|
+
import kotlin.time.ExperimentalTime
|
|
8
|
+
|
|
9
|
+
private const val TAG = "[ScrollToTop]"
|
|
10
|
+
|
|
11
|
+
private fun Any.tag(): String = "${this::class.simpleName ?: "Any"}@${hashCode().toString(16)}"
|
|
12
|
+
|
|
13
|
+
@OptIn(ExperimentalTime::class)
|
|
14
|
+
private fun ts(): String {
|
|
15
|
+
val ms = Clock.System.now().toEpochMilliseconds()
|
|
16
|
+
val s = ms / 1000
|
|
17
|
+
val hh = ((s / 3600) % 24).toString().padStart(2, '0')
|
|
18
|
+
val mm = ((s / 60) % 60).toString().padStart(2, '0')
|
|
19
|
+
val ss = (s % 60).toString().padStart(2, '0')
|
|
20
|
+
val mmm = (ms % 1000).toString().padStart(3, '0')
|
|
21
|
+
return "$hh:$mm:$ss.$mmm"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private fun log(msg: String) = println("${ts()} $TAG $msg")
|
|
6
25
|
|
|
7
26
|
actual fun onNavigatorEntered(navigator: Navigator) {
|
|
27
|
+
log("onNavigatorEntered owner=${navigator.tag()}")
|
|
8
28
|
ScrollToTopRegistry.pushOwner(navigator)
|
|
9
29
|
}
|
|
10
30
|
|
|
11
31
|
actual fun onNavigatorExited(navigator: Navigator) {
|
|
32
|
+
log("onNavigatorExited owner=${navigator.tag()}")
|
|
12
33
|
ScrollToTopRegistry.removeOwner(navigator)
|
|
13
34
|
}
|
|
14
35
|
|
|
@@ -17,11 +38,16 @@ internal actual fun RegisterScrollToTop(navigator: Navigator, callback: (() -> U
|
|
|
17
38
|
val token = remember { Any() }
|
|
18
39
|
DisposableEffect(navigator, callback) {
|
|
19
40
|
if (callback != null) {
|
|
41
|
+
log("RegisterScrollToTop push owner=${navigator.tag()} token=${token.tag()}")
|
|
20
42
|
ScrollToTopRegistry.push(navigator, token, callback)
|
|
21
43
|
} else {
|
|
44
|
+
log("RegisterScrollToTop remove(callback=null) owner=${navigator.tag()} token=${token.tag()}")
|
|
45
|
+
ScrollToTopRegistry.remove(navigator, token)
|
|
46
|
+
}
|
|
47
|
+
onDispose {
|
|
48
|
+
log("RegisterScrollToTop dispose owner=${navigator.tag()} token=${token.tag()}")
|
|
22
49
|
ScrollToTopRegistry.remove(navigator, token)
|
|
23
50
|
}
|
|
24
|
-
onDispose { ScrollToTopRegistry.remove(navigator, token) }
|
|
25
51
|
}
|
|
26
52
|
}
|
|
27
53
|
|
|
@@ -42,39 +68,57 @@ object ScrollToTopRegistry {
|
|
|
42
68
|
private val ownerStack = mutableListOf<Any>()
|
|
43
69
|
|
|
44
70
|
fun pushOwner(owner: Any) {
|
|
45
|
-
ownerStack.remove(owner)
|
|
71
|
+
val existed = ownerStack.remove(owner)
|
|
46
72
|
ownerStack.add(owner)
|
|
73
|
+
log("pushOwner owner=${owner.tag()} reorder=$existed ownerStack=${ownerStack.size} state=${dump()}")
|
|
47
74
|
}
|
|
48
75
|
|
|
49
76
|
fun removeOwner(owner: Any) {
|
|
50
|
-
ownerStack.remove(owner)
|
|
51
|
-
stacksByOwner.remove(owner)
|
|
77
|
+
val removedFromStack = ownerStack.remove(owner)
|
|
78
|
+
val removedScreens = stacksByOwner.remove(owner)?.size ?: 0
|
|
79
|
+
log("removeOwner owner=${owner.tag()} removedFromStack=$removedFromStack droppedScreens=$removedScreens state=${dump()}")
|
|
52
80
|
}
|
|
53
81
|
|
|
54
82
|
internal fun push(owner: Any, token: Any, callback: () -> Unit) {
|
|
55
83
|
val stack = stacksByOwner.getOrPut(owner) { mutableListOf() }
|
|
56
84
|
val idx = stack.indexOfFirst { it.token === token }
|
|
57
85
|
if (idx >= 0) {
|
|
58
|
-
// Same screen, callback changed (e.g. via setOptions) — replace in place
|
|
59
|
-
// so we don't reorder the per-owner stack.
|
|
60
86
|
stack[idx] = Entry(token, callback)
|
|
87
|
+
log("push(update) owner=${owner.tag()} token=${token.tag()} idx=$idx size=${stack.size} state=${dump()}")
|
|
61
88
|
} else {
|
|
62
89
|
stack.add(Entry(token, callback))
|
|
90
|
+
log("push(new) owner=${owner.tag()} token=${token.tag()} size=${stack.size} state=${dump()}")
|
|
63
91
|
}
|
|
64
92
|
}
|
|
65
93
|
|
|
66
94
|
internal fun remove(owner: Any, token: Any) {
|
|
67
|
-
stacksByOwner[owner]
|
|
95
|
+
val stack = stacksByOwner[owner]
|
|
96
|
+
val before = stack?.size ?: 0
|
|
97
|
+
val removed = stack?.removeAll { it.token === token } ?: false
|
|
98
|
+
log("remove owner=${owner.tag()} token=${token.tag()} removed=$removed size=${before}->${stack?.size ?: 0} state=${dump()}")
|
|
68
99
|
}
|
|
69
100
|
|
|
70
101
|
fun trigger() {
|
|
71
|
-
val owner = ownerStack.lastOrNull()
|
|
72
|
-
|
|
102
|
+
val owner = ownerStack.lastOrNull()
|
|
103
|
+
if (owner == null) {
|
|
73
104
|
if (stacksByOwner.size == 1) {
|
|
74
|
-
stacksByOwner.
|
|
105
|
+
val only = stacksByOwner.entries.first()
|
|
106
|
+
val cb = only.value.lastOrNull()?.callback
|
|
107
|
+
log("trigger(fallback singleOwner) owner=${only.key.tag()} hasCallback=${cb != null}")
|
|
108
|
+
cb?.invoke()
|
|
109
|
+
} else {
|
|
110
|
+
log("trigger NO-OP (no owner, owners=${stacksByOwner.size}) state=${dump()}")
|
|
75
111
|
}
|
|
76
112
|
return
|
|
77
113
|
}
|
|
78
|
-
stacksByOwner[owner]?.lastOrNull()?.callback
|
|
114
|
+
val cb = stacksByOwner[owner]?.lastOrNull()?.callback
|
|
115
|
+
log("trigger owner=${owner.tag()} hasCallback=${cb != null} state=${dump()}")
|
|
116
|
+
cb?.invoke()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private fun dump(): String {
|
|
120
|
+
val owners = ownerStack.joinToString(",") { it.tag() }
|
|
121
|
+
val stacks = stacksByOwner.entries.joinToString(",") { (o, s) -> "${o.tag()}:${s.size}" }
|
|
122
|
+
return "ownerStack=[$owners] stacks={$stacks}"
|
|
79
123
|
}
|
|
80
124
|
}
|
|
Binary file
|
package/gradle.properties
CHANGED
|
@@ -18,7 +18,7 @@ kotlin.apple.xcodeCompatibility.nowarn=true
|
|
|
18
18
|
name="ComposeKits"
|
|
19
19
|
group=vn.momo.kits
|
|
20
20
|
artifact.id=kits
|
|
21
|
-
version=0.
|
|
21
|
+
version=0.160.1-scrolltotop.13
|
|
22
22
|
|
|
23
23
|
repo=GitLab
|
|
24
24
|
url=https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven
|
package/local.properties
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## This file must *NOT* be checked into Version Control Systems,
|
|
2
|
+
# as it contains information specific to your local configuration.
|
|
3
|
+
#
|
|
4
|
+
# Location of the SDK. This is only used by Gradle.
|
|
5
|
+
# For customization when using a Version Control System, please read the
|
|
6
|
+
# header note.
|
|
7
|
+
#Tue Jun 17 09:25:26 ICT 2025
|
|
8
|
+
sdk.dir=/Users/thanhle/Library/Android/sdk
|
package/package.json
CHANGED
package/publish.sh
CHANGED
|
File without changes
|