@momo-kits/native-kits 0.162.2-test.2-debug → 0.162.2-test.3-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.
@@ -9,8 +9,10 @@ import kotlinx.coroutines.SupervisorJob
9
9
  import kotlinx.coroutines.launch
10
10
  import vn.momo.maxapi.IMaxApi
11
11
 
12
- const val KEY_USE_DEVICE_FONT_SCALE = "use_device_font_scale"
13
- const val KEY_APP_FONT_SCALE = "app_font_scale"
12
+ private const val KEY_USE_DEVICE_FONT_SCALE = "use_device_font_scale"
13
+ private const val KEY_APP_FONT_SCALE = "app_font_scale"
14
+ private const val MIN_APP_FONT_SCALE = 1f
15
+ private const val MAX_APP_FONT_SCALE = 1.5f
14
16
 
15
17
  /**
16
18
  * Single in-memory mirror of the Observer Storage font-scale source of truth
@@ -19,9 +21,11 @@ const val KEY_APP_FONT_SCALE = "app_font_scale"
19
21
  * scaleSize() reads this holder directly, so every Compose subtree across all
20
22
  * NavigationContainer roots reacts to a change at once — no per-root wiring.
21
23
  *
22
- * The subscription is started once (the first NavigationContainer that receives
23
- * a non-null [IMaxApi]) and lives on its own scope, independent of any screen
24
- * lifecycle, so it survives navigation between roots.
24
+ * [start] subscribes once to storage through the given [IMaxApi]: it seeds the
25
+ * current value (the observer Flow only replays emissions made after subscribe),
26
+ * then collects live changes. The subscription lives on its own scope, so it
27
+ * survives navigation between screens. The caller must pass a real (adapter-backed)
28
+ * IMaxApi — a NoopMaxApi emits a single error frame, which is ignored here.
25
29
  */
26
30
  object FontScaleStore {
27
31
 
@@ -37,41 +41,51 @@ object FontScaleStore {
37
41
  if (started) return
38
42
  started = true
39
43
 
40
- // Seed the current persisted value first: the observer signal flow has no
41
- // replay, so a fresh subscriber would otherwise stay at defaults until the
42
- // next change (wrong scale on first paint).
44
+ // Seed current persisted value.
43
45
  maxApi.getDataObserver(KEY_USE_DEVICE_FONT_SCALE) { map ->
44
- parseBool(map)?.let { useDeviceFontScale = it }
46
+ parseUseDevice(map)?.let { useDeviceFontScale = it }
45
47
  }
46
48
  maxApi.getDataObserver(KEY_APP_FONT_SCALE) { map ->
47
- parseFloat(map)?.let { appFontScale = it }
49
+ parseScale(map)?.let { appFontScale = it }
48
50
  }
49
51
 
50
52
  // Live updates.
51
53
  scope.launch {
52
54
  maxApi.observer(KEY_USE_DEVICE_FONT_SCALE).collect { map ->
53
- parseBool(map)?.let { useDeviceFontScale = it }
55
+ parseUseDevice(map)?.let { useDeviceFontScale = it }
54
56
  }
55
57
  }
56
58
  scope.launch {
57
59
  maxApi.observer(KEY_APP_FONT_SCALE).collect { map ->
58
- parseFloat(map)?.let { appFontScale = it }
60
+ parseScale(map)?.let { appFontScale = it }
59
61
  }
60
62
  }
61
63
  }
62
64
 
63
- private fun response(map: Map<String, Any?>?): Any? = map?.get("response")
65
+ /**
66
+ * Callback map = serialized MaxApiResponse flattened: { status, response, errorCode, ... }.
67
+ * A stored string scalar arrives under "response" as a String ("1.5" / "false").
68
+ * Returns null for error frames (e.g. adapter-not-bound) and unset keys.
69
+ */
70
+ private fun response(map: Map<String, Any?>?): Any? {
71
+ if (map == null) return null
72
+ val errorCode = (map["errorCode"] as? Number)?.toInt() ?: 0
73
+ if (errorCode != 0) return null
74
+ return map["response"]
75
+ }
64
76
 
65
- private fun parseBool(map: Map<String, Any?>?): Boolean? = when (val v = response(map)) {
66
- is Boolean -> v
67
- is String -> v.toBooleanStrictOrNull() ?: v.equals("true", ignoreCase = true)
68
- is Number -> v.toInt() != 0
69
- else -> null
77
+ private fun parseScale(map: Map<String, Any?>?): Float? {
78
+ val value = when (val r = response(map)) {
79
+ is Number -> r.toFloat()
80
+ is String -> r.toFloatOrNull()
81
+ else -> null
82
+ } ?: return null
83
+ return value.coerceIn(MIN_APP_FONT_SCALE, MAX_APP_FONT_SCALE)
70
84
  }
71
85
 
72
- private fun parseFloat(map: Map<String, Any?>?): Float? = when (val v = response(map)) {
73
- is Number -> v.toFloat()
74
- is String -> v.toFloatOrNull()
86
+ private fun parseUseDevice(map: Map<String, Any?>?): Boolean? = when (val r = response(map)) {
87
+ is Boolean -> r
88
+ is String -> r.toBooleanStrictOrNull()
75
89
  else -> null
76
90
  }
77
91
  }
@@ -37,10 +37,6 @@ fun NavigationContainer(
37
37
  val parentContext = ApplicationContext.current
38
38
  val mergedContext = MiniAppContext.merge(parentContext, applicationContext)
39
39
 
40
- LaunchedEffect(maxApi) {
41
- maxApi?.let { FontScaleStore.start(it) }
42
- }
43
-
44
40
  val theme = remember { mutableStateOf(initialTheme) }
45
41
 
46
42
  LaunchedEffect(Unit) {
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.162.2-test.2
21
+ version=0.162.2-test.3
22
22
 
23
23
  repo=GitLab
24
24
  url=https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.162.2-test.2-debug",
3
+ "version": "0.162.2-test.3-debug",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},