@momo-kits/native-kits 0.162.3-fontscale.3-debug → 0.162.3-fontscale.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/build.gradle.kts +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +4 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
- package/gradle.properties +1 -1
- package/ios/Typography/FontScaleStore.swift +8 -9
- package/ios/Typography/Text.swift +0 -1
- package/package.json +1 -1
package/compose/build.gradle.kts
CHANGED
|
@@ -7,6 +7,7 @@ import androidx.compose.ui.Modifier
|
|
|
7
7
|
import androidx.compose.ui.unit.Dp
|
|
8
8
|
import vn.momo.kits.const.*
|
|
9
9
|
import vn.momo.kits.modifier.DeprecatedModifier
|
|
10
|
+
import vn.momo.kits.platform.ProvideOsFontScale
|
|
10
11
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
11
12
|
|
|
12
13
|
@Deprecated("Use IMaxApi instead", ReplaceWith("IMaxApi"))
|
|
@@ -93,6 +94,7 @@ fun ApplicationContainer(
|
|
|
93
94
|
|
|
94
95
|
val appStatusBarHeight = statusBarHeight ?: getStatusBarHeight()
|
|
95
96
|
|
|
97
|
+
ProvideOsFontScale {
|
|
96
98
|
CompositionLocalProvider(
|
|
97
99
|
AppTheme provides appTheme,
|
|
98
100
|
PlatformApi provides composeApi,
|
|
@@ -103,5 +105,6 @@ fun ApplicationContainer(
|
|
|
103
105
|
content()
|
|
104
106
|
}
|
|
105
107
|
}
|
|
108
|
+
}
|
|
106
109
|
|
|
107
110
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package vn.momo.kits.const
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.getValue
|
|
4
|
+
import androidx.compose.runtime.mutableStateOf
|
|
5
|
+
import androidx.compose.runtime.setValue
|
|
6
|
+
|
|
7
|
+
// App-wide font-scale holder. The kit is sandboxed and can't read the host cache directly, so the
|
|
8
|
+
// host (which sees both core and this kit) seeds this once at startup and pushes runtime updates into
|
|
9
|
+
// it. scaleSize() reads it as the fallback, so every screen — including direct NavigationContainer
|
|
10
|
+
// screens with no host-pushed MiniAppContext — scales with no per-render prop and no async flicker.
|
|
11
|
+
// Backed by snapshot state: writes recompose text automatically.
|
|
12
|
+
object KitFontScale {
|
|
13
|
+
var userScaleRate by mutableStateOf(1f)
|
|
14
|
+
private set
|
|
15
|
+
var useOSScaleRate by mutableStateOf(true)
|
|
16
|
+
private set
|
|
17
|
+
|
|
18
|
+
fun update(userScaleRate: Float, useOSScaleRate: Boolean) {
|
|
19
|
+
this.userScaleRate = userScaleRate
|
|
20
|
+
this.useOSScaleRate = useOSScaleRate
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -24,8 +24,10 @@ const val MAX_DEVICE_SCALE = 5
|
|
|
24
24
|
@Composable
|
|
25
25
|
fun scaleSize(size: Float): Float {
|
|
26
26
|
val context = LocalContext.current
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
// Host-pushed context wins; otherwise fall back to the app-wide KitFontScale holder.
|
|
28
|
+
val useOsScale = context?.useOSScaleRate ?: KitFontScale.useOSScaleRate
|
|
29
|
+
if (!useOsScale) {
|
|
30
|
+
return size * (context?.userScaleRate ?: KitFontScale.userScaleRate)
|
|
29
31
|
}
|
|
30
32
|
val scaleSizeMaxRate: Float = MAX_FONT_SCALE
|
|
31
33
|
val deviceWidth = getScreenDimensions().width
|
|
@@ -12,6 +12,7 @@ import androidx.navigation.toRoute
|
|
|
12
12
|
import vn.momo.kits.application.*
|
|
13
13
|
import vn.momo.kits.const.*
|
|
14
14
|
import vn.momo.kits.platform.ProvideNavigationEventDispatcherOwner
|
|
15
|
+
import vn.momo.kits.platform.ProvideOsFontScale
|
|
15
16
|
import vn.momo.kits.utils.getAppStatusBarHeight
|
|
16
17
|
import vn.momo.kits.utils.getNavigationBarHeight
|
|
17
18
|
import vn.momo.maxapi.IMaxApi
|
|
@@ -57,6 +58,7 @@ fun NavigationContainer(
|
|
|
57
58
|
registry.bind(screenId, initialScreenName, initialScreen, options)
|
|
58
59
|
val startDestination = remember(screenId) { DynamicScreenRoute(screenId) }
|
|
59
60
|
|
|
61
|
+
ProvideOsFontScale {
|
|
60
62
|
ProvideNavigationEventDispatcherOwner {
|
|
61
63
|
CompositionLocalProvider(
|
|
62
64
|
LocalNavigator provides navigator,
|
|
@@ -133,6 +135,7 @@ fun NavigationContainer(
|
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
}
|
|
138
|
+
}
|
|
136
139
|
|
|
137
140
|
DisposableEffect(Unit) {
|
|
138
141
|
onDispose {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
package vn.momo.kits.platform
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.Composable
|
|
4
|
+
|
|
5
|
+
// Overrides LocalDensity.fontScale with the live OS Dynamic Type scale so text re-scales while a
|
|
6
|
+
// screen is visible. Wrapped inside the containers so every screen is covered, not just callers of
|
|
7
|
+
// the app-level wrappers.
|
|
8
|
+
@Composable
|
|
9
|
+
expect fun ProvideOsFontScale(content: @Composable () -> Unit)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
package vn.momo.kits.platform
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.Composable
|
|
4
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
5
|
+
import androidx.compose.runtime.DisposableEffect
|
|
6
|
+
import androidx.compose.runtime.mutableStateOf
|
|
7
|
+
import androidx.compose.runtime.remember
|
|
8
|
+
import androidx.compose.ui.platform.LocalDensity
|
|
9
|
+
import androidx.compose.ui.unit.Density
|
|
10
|
+
import kotlinx.cinterop.ExperimentalForeignApi
|
|
11
|
+
import kotlinx.cinterop.ObjCAction
|
|
12
|
+
import platform.Foundation.NSNotification
|
|
13
|
+
import platform.Foundation.NSNotificationCenter
|
|
14
|
+
import platform.Foundation.NSSelectorFromString
|
|
15
|
+
import platform.UIKit.UIContentSizeCategoryDidChangeNotification
|
|
16
|
+
import platform.UIKit.UIFont
|
|
17
|
+
import platform.UIKit.UIFontTextStyleBody
|
|
18
|
+
import platform.darwin.NSObject
|
|
19
|
+
|
|
20
|
+
// Compose MP iOS reads LocalDensity.fontScale once at ComposeUIViewController creation and does not
|
|
21
|
+
// recompose it when UIContentSizeCategory changes (Android tracks Configuration.fontScale live). We
|
|
22
|
+
// observe the notification and override LocalDensity.fontScale so scaleSize() recomposes live. The
|
|
23
|
+
// formula matches the SwiftUI kit (UIFont body point size / 17) so both iOS surfaces scale alike.
|
|
24
|
+
private const val DEFAULT_BODY_POINT_SIZE = 17.0
|
|
25
|
+
|
|
26
|
+
private fun currentOsFontScale(): Float =
|
|
27
|
+
(UIFont.preferredFontForTextStyle(UIFontTextStyleBody).pointSize / DEFAULT_BODY_POINT_SIZE).toFloat()
|
|
28
|
+
|
|
29
|
+
@OptIn(ExperimentalForeignApi::class)
|
|
30
|
+
@Composable
|
|
31
|
+
actual fun ProvideOsFontScale(content: @Composable () -> Unit) {
|
|
32
|
+
val osFontScale = remember { mutableStateOf(currentOsFontScale()) }
|
|
33
|
+
|
|
34
|
+
val listener = remember {
|
|
35
|
+
object : NSObject() {
|
|
36
|
+
@Suppress("unused")
|
|
37
|
+
@ObjCAction
|
|
38
|
+
fun contentSizeChanged(arg: NSNotification) {
|
|
39
|
+
osFontScale.value = currentOsFontScale()
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
DisposableEffect(Unit) {
|
|
45
|
+
NSNotificationCenter.defaultCenter.addObserver(
|
|
46
|
+
observer = listener,
|
|
47
|
+
selector = NSSelectorFromString(listener::contentSizeChanged.name + ":"),
|
|
48
|
+
name = UIContentSizeCategoryDidChangeNotification,
|
|
49
|
+
`object` = null,
|
|
50
|
+
)
|
|
51
|
+
onDispose {
|
|
52
|
+
NSNotificationCenter.defaultCenter.removeObserver(
|
|
53
|
+
observer = listener,
|
|
54
|
+
name = UIContentSizeCategoryDidChangeNotification,
|
|
55
|
+
`object` = null,
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
val density = LocalDensity.current
|
|
61
|
+
CompositionLocalProvider(
|
|
62
|
+
LocalDensity provides Density(density.density, osFontScale.value),
|
|
63
|
+
) {
|
|
64
|
+
content()
|
|
65
|
+
}
|
|
66
|
+
}
|
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.3-fontscale.
|
|
21
|
+
version=0.162.3-fontscale.4
|
|
22
22
|
|
|
23
23
|
repo=GitLab
|
|
24
24
|
url=https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import Combine
|
|
2
1
|
import CoreGraphics
|
|
3
2
|
|
|
4
|
-
/// App-wide font-scale preference for the SwiftUI kit.
|
|
5
|
-
/// (
|
|
6
|
-
///
|
|
7
|
-
/// When `useOSScaleRate` is false the kit applies `userScaleRate` instead of the
|
|
8
|
-
///
|
|
9
|
-
public final class FontScaleStore
|
|
3
|
+
/// App-wide font-scale preference for the SwiftUI kit. An exported holder the host writes once at
|
|
4
|
+
/// app startup (from the cache-backed `FontScaleProvider`); `scaleSize`/`appFont` read the snapshot.
|
|
5
|
+
/// No realtime: the SwiftUI kit has no navigation container to scope reactive updates, so a startup
|
|
6
|
+
/// snapshot is enough. When `useOSScaleRate` is false the kit applies `userScaleRate` instead of the
|
|
7
|
+
/// OS Dynamic Type factor.
|
|
8
|
+
public final class FontScaleStore {
|
|
10
9
|
public static let shared = FontScaleStore()
|
|
11
10
|
private init() {}
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
public private(set) var userScaleRate: CGFloat = 1
|
|
13
|
+
public private(set) var useOSScaleRate: Bool = true
|
|
15
14
|
|
|
16
15
|
public func update(userScaleRate: CGFloat, useOSScaleRate: Bool) {
|
|
17
16
|
self.userScaleRate = userScaleRate
|