@momo-kits/native-kits 0.167.1-sizescale.2-debug → 0.300.1-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/CLAUDE.md +4 -4
- package/README.md +10 -2
- package/build.gradle.kts +3 -1
- package/compose/build.gradle.kts +19 -20
- package/compose/build.gradle.kts.backup +18 -19
- package/compose/compose.podspec +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +1 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +3 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +25 -16
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +23 -13
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +3 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +11 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +10 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +6 -23
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +13 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +22 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +11 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +28 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +6 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +6 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +26 -17
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +4 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +47 -30
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +4 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +33 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +40 -32
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +47 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +6 -2
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +1 -3
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +6 -11
- package/gradle/libs.versions.toml +9 -3
- package/gradle/wrapper/gradle-wrapper.properties +3 -1
- package/gradle.properties +1 -1
- package/ios/native-kits.podspec +1 -1
- package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
- package/package.json +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitSizeScale.kt +0 -56
- package/example/ios/Example.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/Example.xcscheme +0 -32
- package/example/ios/Example.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/WorkspaceSettings.xcsettings +0 -16
- package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
- package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/xcschemes/xcschememanagement.plist +0 -5
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/SDWebImage.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/SDWebImageSwiftUI.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/SkeletonUI.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/lottie-ios-LottiePrivacyInfo.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/lottie-ios.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/xcschememanagement.plist +0 -60
- package/local.properties +0 -8
package/CLAUDE.md
CHANGED
|
@@ -7,7 +7,7 @@ Guidance for working in this repo. Keep it accurate — update it when structure
|
|
|
7
7
|
`momo-native-kits` — MoMo's design-system / UI-kit as a **Kotlin Multiplatform + Compose Multiplatform** library, published for Android (AAR/Maven) and iOS (static framework + CocoaPods). It is the Compose port of the React Native `momo-kits`. Consumed by mini-apps embedded in the host MoMo app.
|
|
8
8
|
|
|
9
9
|
- Artifact: `vn.momo.kits:kits` (version in `gradle.properties`). NPM mirror: `@momo-kits/native-kits`.
|
|
10
|
-
- Targets: `
|
|
10
|
+
- Targets: AGP KMP `android` target (JVM 17, compile/min SDK 37/24; AGP 9.2.1, Gradle 9.5.0), `iosArm64`, `iosSimulatorArm64` (framework `baseName = "kits"`, `isStatic = true`).
|
|
11
11
|
- Kotlin 2.3.10, Compose MP 1.10.3.
|
|
12
12
|
|
|
13
13
|
## Modules
|
|
@@ -26,11 +26,11 @@ Guidance for working in this repo. Keep it accurate — update it when structure
|
|
|
26
26
|
|
|
27
27
|
## Build & verify
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Run `./gradlew :compose:testAndroidHostTest` for the request ownership tests in `commonTest`. Compile the relevant Android/iOS targets and use the sample app for visual checks.
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
32
|
./gradlew :compose:compileCommonMainKotlinMetadata # validate commonMain (fast, do this first)
|
|
33
|
-
./gradlew :compose:
|
|
33
|
+
./gradlew :compose:compileAndroidMain # Android target
|
|
34
34
|
./gradlew :compose:linkDebugFrameworkIosSimulatorArm64 # iOS framework (slow)
|
|
35
35
|
./gradlew :sample:androidApp:installDebug # run demo on device/emulator
|
|
36
36
|
```
|
|
@@ -43,7 +43,7 @@ Publishing is automated (`publish.sh` + GitLab CI on `[ci build]` / `main`). Do
|
|
|
43
43
|
- **Configuration flows via CompositionLocals**, not params. Public ones: `AppTheme`, `AppStatusBar`, `AppNavigationBar` (`const/Theme.kt`); `ApplicationContext`, `AppConfig`, `AppLanguage`, `LocalLocalize` (`application/`); `LocalNavigator`, `LocalMaxApi` (`navigation/`). Read with `X.current`.
|
|
44
44
|
- **Design-system config** (`trustBanner`, `headerBar`, `headerGradient`): the host seeds `KitDesignSystemConfig.update(...)` once (same pattern as `KitFontScale`); `NavigationContainer` provides it as `LocalDesignSystemConfig` (param `designSystemConfig` → parent → global) and applies `headerBar` as the header image when the theme has none.
|
|
45
45
|
- **Platform code** goes through `expect`/`actual` in `platform/` — never reference Android/iOS APIs from `commonMain` directly.
|
|
46
|
-
- **Native bridge:** `IMaxApi` (`vn.momo.maxapi`, exposed as `LocalMaxApi`) is the host-app bridge
|
|
46
|
+
- **Native bridge:** typed `IMaxApi` from NativeMaxApi `0.3.1` (`vn.momo.maxapi`, exposed as `LocalMaxApi`) is the host-app bridge. Toolkit uses `ToolkitOptions` to preserve custom groups and system-tool policy; pending callbacks are cancelled when their composition is disposed. Containers borrow the host client and must not close it.
|
|
47
47
|
- Navigation uses a runtime `DynamicScreenRegistry`; overlays (modal/bottom-sheet/snackbar) go through `Navigator` + `OverplayComponentRegistry`.
|
|
48
48
|
- **iOS swipe-back:** the host owns the only edge-pan recogniser and replays it through `HostBackGestureBridge` (`navigation/HostBackGestureBridge.kt`; the kit framework is never exported, so the host reaches it through its own Koin-provided facade): `checkCanPop` / `canPopInner` / `pop` route the back into the kit stack, `started` / `progressed` / `completed` / `cancelled` seek the NavHost transition, `shouldUseFloatingArrowBack` is set by bottom tabs. `NavigationContainer` attaches itself automatically (`AttachHostBackGesture`, iOS only, detached by identity on dispose) — hosts need no wrapper and no `setNavigator`. `maxApi` is a required parameter of `NavigationContainer` — every container, nested or root, is handed its host bridge explicitly.
|
|
49
49
|
|
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ ComposeKit là bộ UI Kit đa nền tảng phục vụ Mini App/SDK của MoMo.
|
|
|
53
53
|
---
|
|
54
54
|
|
|
55
55
|
### Yêu cầu môi trường
|
|
56
|
-
- JDK 17
|
|
56
|
+
- JDK 17+ và Android SDK (compileSdk xem `libs.versions.toml`); wrapper Gradle `9.5.0`, AGP `9.2.1`.
|
|
57
57
|
- Kotlin Multiplatform plugin + Compose Multiplatform (JetBrains 1.6.1+).
|
|
58
58
|
- Xcode 15, CocoaPods 1.12+ để build `iosApp` hoặc publish Pod.
|
|
59
59
|
- Truy cập mạng nội bộ GitLab Packages nếu cần publish/consume Maven repo `https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven`.
|
|
@@ -174,4 +174,12 @@ fun SuccessState() {
|
|
|
174
174
|
```
|
|
175
175
|
|
|
176
176
|
- `shared/build.gradle.kts` đã bật `coreLibraryDesugaringEnabled` để tương thích `compottie-dot`/`compottie-network` với `minSdk = 24`.
|
|
177
|
-
- Nếu animation dùng asset/font nội bộ, kết hợp `compottie-resources` (`rememberResourcesAssetsManager`, `rememberResourcesFontManager`) để trỏ về `composeResources`.
|
|
177
|
+
- Nếu animation dùng asset/font nội bộ, kết hợp `compottie-resources` (`rememberResourcesAssetsManager`, `rememberResourcesFontManager`) để trỏ về `composeResources`.
|
|
178
|
+
### NativeMaxApi 0.3.1
|
|
179
|
+
|
|
180
|
+
Compose dùng typed `vn.momo.maxapi.IMaxApi` do host truyền vào `NavigationContainer`.
|
|
181
|
+
Toolkit dùng overload `showToolkit(ToolkitOptions, callback)` để giữ nhóm tool tùy chỉnh,
|
|
182
|
+
nhãn đa ngôn ngữ, icon, badge và `useSystemTools`. Callback trả `actionKey`; request đang chờ
|
|
183
|
+
được hủy khi composition bị gỡ. Kits không đóng client do host sở hữu.
|
|
184
|
+
|
|
185
|
+
Chạy `./gradlew :compose:testAndroidHostTest` để kiểm tra hủy request và callback đến muộn.
|
package/build.gradle.kts
CHANGED
|
@@ -2,7 +2,9 @@ plugins {
|
|
|
2
2
|
// this is necessary to avoid the plugins to be loaded multiple times
|
|
3
3
|
// in each subproject's classloader
|
|
4
4
|
alias(libs.plugins.android.application) apply false
|
|
5
|
-
|
|
5
|
+
// AI-GENERATED START: use the AGP 9 Kotlin Multiplatform Android library target
|
|
6
|
+
alias(libs.plugins.android.kotlin.multiplatform.library) apply false
|
|
7
|
+
// AI-GENERATED END: use the AGP 9 Kotlin Multiplatform Android library target
|
|
6
8
|
alias(libs.plugins.compose) apply false
|
|
7
9
|
alias(libs.plugins.kotlin.compose.compiler) apply false
|
|
8
10
|
alias(libs.plugins.jetbrains.kotlin.multiplatform) apply false
|
package/compose/build.gradle.kts
CHANGED
|
@@ -4,7 +4,9 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|
|
4
4
|
|
|
5
5
|
plugins {
|
|
6
6
|
alias(libs.plugins.jetbrains.kotlin.multiplatform)
|
|
7
|
-
|
|
7
|
+
// AI-GENERATED START: use the AGP 9 Kotlin Multiplatform Android library target
|
|
8
|
+
alias(libs.plugins.android.kotlin.multiplatform.library)
|
|
9
|
+
// AI-GENERATED END: use the AGP 9 Kotlin Multiplatform Android library target
|
|
8
10
|
alias(libs.plugins.compose)
|
|
9
11
|
alias(libs.plugins.kotlin.compose.compiler)
|
|
10
12
|
// alias(libs.plugins.vanniktech.mavenPublish)
|
|
@@ -22,12 +24,18 @@ val gitlabUser: String = findProperty("gitlab.user") as String? ?: ""
|
|
|
22
24
|
val gitlabKey: String = findProperty("gitlab.password") as String? ?: ""
|
|
23
25
|
|
|
24
26
|
kotlin {
|
|
25
|
-
|
|
27
|
+
// AI-GENERATED START: configure the AGP 9 Android target and host tests
|
|
28
|
+
android {
|
|
29
|
+
namespace = "vn.momo.kits.kits"
|
|
30
|
+
compileSdk = 35
|
|
31
|
+
minSdk = 24
|
|
32
|
+
androidResources.enable = true
|
|
33
|
+
withHostTest {}
|
|
26
34
|
compilerOptions {
|
|
27
35
|
jvmTarget.set(JvmTarget.JVM_17)
|
|
28
36
|
}
|
|
29
|
-
publishLibraryVariants("release")
|
|
30
37
|
}
|
|
38
|
+
// AI-GENERATED END: configure the AGP 9 Android target and host tests
|
|
31
39
|
|
|
32
40
|
val fwName = gitlabArtifactId
|
|
33
41
|
val iosTargets = listOf(iosArm64(), iosSimulatorArm64())
|
|
@@ -40,7 +48,7 @@ kotlin {
|
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
cocoapods {
|
|
43
|
-
version = "0.
|
|
51
|
+
version = "0.300.1-debug"
|
|
44
52
|
summary = "IOS Shared module"
|
|
45
53
|
homepage = "https://momo.vn"
|
|
46
54
|
ios.deploymentTarget = "15.0"
|
|
@@ -86,24 +94,14 @@ kotlin {
|
|
|
86
94
|
iosMain.dependencies {
|
|
87
95
|
implementation(libs.ktor.client.darwin)
|
|
88
96
|
}
|
|
97
|
+
// AI-GENERATED START: verify toolkit request ownership
|
|
98
|
+
commonTest.dependencies {
|
|
99
|
+
implementation(kotlin("test"))
|
|
100
|
+
}
|
|
101
|
+
// AI-GENERATED END: verify toolkit request ownership
|
|
89
102
|
}
|
|
90
103
|
}
|
|
91
104
|
|
|
92
|
-
android {
|
|
93
|
-
namespace = "vn.momo.kits.kits"
|
|
94
|
-
compileSdk = 35
|
|
95
|
-
compileOptions {
|
|
96
|
-
sourceCompatibility = JavaVersion.VERSION_17
|
|
97
|
-
targetCompatibility = JavaVersion.VERSION_17
|
|
98
|
-
}
|
|
99
|
-
defaultConfig {
|
|
100
|
-
minSdk = 24
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
dependencies {
|
|
105
|
-
}
|
|
106
|
-
|
|
107
105
|
repositories {
|
|
108
106
|
google {
|
|
109
107
|
mavenContent {
|
|
@@ -153,8 +151,9 @@ compose {
|
|
|
153
151
|
// configure(
|
|
154
152
|
// KotlinMultiplatform(
|
|
155
153
|
// javadocJar = JavadocJar.Empty(),
|
|
154
|
+
// // AI-GENERATED START: the AGP KMP target publishes a single Android variant
|
|
156
155
|
// sourcesJar = true,
|
|
157
|
-
//
|
|
156
|
+
// // AI-GENERATED END: the AGP KMP target publishes a single Android variant
|
|
158
157
|
// )
|
|
159
158
|
// )
|
|
160
159
|
//
|
|
@@ -4,7 +4,9 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
|
|
4
4
|
|
|
5
5
|
plugins {
|
|
6
6
|
alias(libs.plugins.jetbrains.kotlin.multiplatform)
|
|
7
|
-
|
|
7
|
+
// AI-GENERATED START: use the AGP 9 Kotlin Multiplatform Android library target
|
|
8
|
+
alias(libs.plugins.android.kotlin.multiplatform.library)
|
|
9
|
+
// AI-GENERATED END: use the AGP 9 Kotlin Multiplatform Android library target
|
|
8
10
|
alias(libs.plugins.compose)
|
|
9
11
|
alias(libs.plugins.kotlin.compose.compiler)
|
|
10
12
|
alias(libs.plugins.vanniktech.mavenPublish)
|
|
@@ -22,12 +24,18 @@ val gitlabUser: String = findProperty("gitlab.user") as String? ?: ""
|
|
|
22
24
|
val gitlabKey: String = findProperty("gitlab.password") as String? ?: ""
|
|
23
25
|
|
|
24
26
|
kotlin {
|
|
25
|
-
|
|
27
|
+
// AI-GENERATED START: configure the AGP 9 Android target and host tests
|
|
28
|
+
android {
|
|
29
|
+
namespace = "$gitlabGroup.$gitlabArtifactId"
|
|
30
|
+
compileSdk = libs.versions.android.compileSdk.get().toInt()
|
|
31
|
+
minSdk = libs.versions.android.minSdk.get().toInt()
|
|
32
|
+
androidResources.enable = true
|
|
33
|
+
withHostTest {}
|
|
26
34
|
compilerOptions {
|
|
27
35
|
jvmTarget.set(JvmTarget.JVM_17)
|
|
28
36
|
}
|
|
29
|
-
publishLibraryVariants("release")
|
|
30
37
|
}
|
|
38
|
+
// AI-GENERATED END: configure the AGP 9 Android target and host tests
|
|
31
39
|
|
|
32
40
|
val fwName = gitlabArtifactId
|
|
33
41
|
val iosTargets = listOf(iosArm64(), iosSimulatorArm64())
|
|
@@ -86,24 +94,14 @@ kotlin {
|
|
|
86
94
|
iosMain.dependencies {
|
|
87
95
|
implementation(libs.ktor.client.darwin)
|
|
88
96
|
}
|
|
97
|
+
// AI-GENERATED START: verify toolkit request ownership
|
|
98
|
+
commonTest.dependencies {
|
|
99
|
+
implementation(kotlin("test"))
|
|
100
|
+
}
|
|
101
|
+
// AI-GENERATED END: verify toolkit request ownership
|
|
89
102
|
}
|
|
90
103
|
}
|
|
91
104
|
|
|
92
|
-
android {
|
|
93
|
-
namespace = "$gitlabGroup.$gitlabArtifactId"
|
|
94
|
-
compileSdk = libs.versions.android.compileSdk.get().toInt()
|
|
95
|
-
compileOptions {
|
|
96
|
-
sourceCompatibility = JavaVersion.VERSION_17
|
|
97
|
-
targetCompatibility = JavaVersion.VERSION_17
|
|
98
|
-
}
|
|
99
|
-
defaultConfig {
|
|
100
|
-
minSdk = libs.versions.android.minSdk.get().toInt()
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
dependencies {
|
|
105
|
-
}
|
|
106
|
-
|
|
107
105
|
repositories {
|
|
108
106
|
google {
|
|
109
107
|
mavenContent {
|
|
@@ -153,8 +151,9 @@ mavenPublishing {
|
|
|
153
151
|
configure(
|
|
154
152
|
KotlinMultiplatform(
|
|
155
153
|
javadocJar = JavadocJar.Empty(),
|
|
154
|
+
// AI-GENERATED START: the AGP KMP target publishes a single Android variant
|
|
156
155
|
sourcesJar = true,
|
|
157
|
-
|
|
156
|
+
// AI-GENERATED END: the AGP KMP target publishes a single Android variant
|
|
158
157
|
)
|
|
159
158
|
)
|
|
160
159
|
|
package/compose/compose.podspec
CHANGED
|
@@ -30,7 +30,6 @@ import com.airbnb.lottie.compose.rememberLottieDynamicProperties
|
|
|
30
30
|
import com.airbnb.lottie.compose.rememberLottieDynamicProperty
|
|
31
31
|
import vn.momo.kits.const.AppNavigationBar
|
|
32
32
|
import vn.momo.kits.const.AppStatusBar
|
|
33
|
-
import vn.momo.kits.const.LocalSizeScale
|
|
34
33
|
import vn.momo.kits.navigation.Navigator
|
|
35
34
|
import vn.momo.kits.utils.readJson
|
|
36
35
|
import androidx.activity.compose.BackHandler as AndroidBackHandler
|
|
@@ -40,10 +39,8 @@ actual fun getPlatformName(): String = "Android"
|
|
|
40
39
|
@Composable
|
|
41
40
|
actual fun getScreenDimensions(): ScreenDimension {
|
|
42
41
|
val config = LocalConfiguration.current
|
|
43
|
-
// Logical dp: the container size scale enlarges every dp, so the screen spans fewer of them.
|
|
44
|
-
val sizeScale = LocalSizeScale.current
|
|
45
42
|
return ScreenDimension(
|
|
46
|
-
|
|
43
|
+
config.screenWidthDp, config.screenHeightDp
|
|
47
44
|
)
|
|
48
45
|
}
|
|
49
46
|
|
|
@@ -44,7 +44,7 @@ import vn.momo.kits.const.getFontFamily
|
|
|
44
44
|
import vn.momo.kits.modifier.kitsAutomationId
|
|
45
45
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
46
46
|
import vn.momo.kits.modifier.setAutomationId
|
|
47
|
-
import vn.momo.kits.navigation.component.
|
|
47
|
+
import vn.momo.kits.navigation.component.headerFontFamily
|
|
48
48
|
import vn.momo.kits.navigation.component.HEADER_HEIGHT
|
|
49
49
|
import vn.momo.kits.utils.getAppStatusBarHeight
|
|
50
50
|
import kotlin.math.max
|
|
@@ -362,7 +362,7 @@ private fun LiteScreenLayout(
|
|
|
362
362
|
text = title,
|
|
363
363
|
color = headerColor.tintIconColor,
|
|
364
364
|
style = titleStyle,
|
|
365
|
-
fontFamily =
|
|
365
|
+
fontFamily = headerFontFamily,
|
|
366
366
|
modifier = titleModifier,
|
|
367
367
|
maxLines = 1,
|
|
368
368
|
overflow = TextOverflow.Ellipsis
|
|
@@ -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"))
|
|
@@ -91,10 +92,9 @@ fun ApplicationContainer(
|
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
val appStatusBarHeight = (statusBarHeight ?: getStatusBarHeight()) / pendingSizeScale()
|
|
95
|
+
val appStatusBarHeight = statusBarHeight ?: getStatusBarHeight()
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
ProvideOsFontScale {
|
|
98
98
|
CompositionLocalProvider(
|
|
99
99
|
AppTheme provides appTheme,
|
|
100
100
|
PlatformApi provides composeApi,
|
|
@@ -2,13 +2,18 @@ package vn.momo.kits.application
|
|
|
2
2
|
|
|
3
3
|
import androidx.compose.runtime.Composable
|
|
4
4
|
import androidx.compose.runtime.CompositionLocalProvider
|
|
5
|
-
|
|
5
|
+
// AI-GENERATED START: own the typed language request
|
|
6
|
+
import androidx.compose.runtime.DisposableEffect
|
|
7
|
+
// AI-GENERATED END: own the typed language request
|
|
6
8
|
import androidx.compose.runtime.remember
|
|
7
9
|
import vn.momo.kits.const.AppTheme
|
|
8
10
|
import vn.momo.kits.const.Theme
|
|
9
11
|
import vn.momo.kits.navigation.LocalMaxApi
|
|
10
|
-
import vn.momo.kits.
|
|
12
|
+
import vn.momo.kits.platform.ProvideOsFontScale
|
|
13
|
+
// AI-GENERATED START: consume typed NativeMaxApi results
|
|
11
14
|
import vn.momo.maxapi.IMaxApi
|
|
15
|
+
import vn.momo.maxapi.runtime.ApiResult
|
|
16
|
+
// AI-GENERATED END: consume typed NativeMaxApi results
|
|
12
17
|
|
|
13
18
|
|
|
14
19
|
@Composable
|
|
@@ -27,17 +32,27 @@ fun WidgetContainer(
|
|
|
27
32
|
val resolvedLocalize = localize ?: LocalLocalize.current
|
|
28
33
|
val resolvedMaxApi = maxApi ?: LocalMaxApi.current
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
val
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
// AI-GENERATED START: cancel language delivery when its composition owner changes
|
|
36
|
+
DisposableEffect(resolvedMaxApi, localize) {
|
|
37
|
+
val api = resolvedMaxApi
|
|
38
|
+
val target = localize
|
|
39
|
+
var active = true
|
|
40
|
+
val handle = runCatching {
|
|
41
|
+
api?.getLanguage { result ->
|
|
42
|
+
if (active && target != null && result is ApiResult.Success &&
|
|
43
|
+
result.value.trim().lowercase().startsWith(Localize.EN)) {
|
|
44
|
+
target.changeLanguage(Localize.EN)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}.getOrNull()
|
|
48
|
+
onDispose {
|
|
49
|
+
active = false
|
|
50
|
+
handle?.cancel()
|
|
37
51
|
}
|
|
38
52
|
}
|
|
53
|
+
// AI-GENERATED END: cancel language delivery when its composition owner changes
|
|
39
54
|
|
|
40
|
-
|
|
55
|
+
ProvideOsFontScale {
|
|
41
56
|
CompositionLocalProvider(
|
|
42
57
|
AppTheme provides resolvedTheme,
|
|
43
58
|
LocalContext provides mergedContext,
|
|
@@ -48,9 +63,3 @@ fun WidgetContainer(
|
|
|
48
63
|
}
|
|
49
64
|
}
|
|
50
65
|
}
|
|
51
|
-
|
|
52
|
-
private fun parseLanguage(raw: Map<String, Any?>?): String? {
|
|
53
|
-
val code = (raw?.get("response") as? String)?.trim()?.lowercase()
|
|
54
|
-
if (code.isNullOrEmpty()) return null
|
|
55
|
-
return if (code.startsWith(Localize.EN)) Localize.EN else Localize.VI
|
|
56
|
-
}
|
|
@@ -19,6 +19,7 @@ import coil3.request.ImageRequest
|
|
|
19
19
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
20
20
|
import vn.momo.kits.const.AppTheme
|
|
21
21
|
import vn.momo.kits.const.Colors
|
|
22
|
+
import vn.momo.kits.gifimage.GifImage
|
|
22
23
|
import vn.momo.kits.modifier.conditional
|
|
23
24
|
import vn.momo.kits.utils.Icons
|
|
24
25
|
import vn.momo.kits.utils.noThemeIcons
|
|
@@ -59,18 +60,27 @@ fun Icon(
|
|
|
59
60
|
}
|
|
60
61
|
.semantics { contentDescription = contentDesc }
|
|
61
62
|
) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
63
|
+
if (isGifUrl(iconUrl)) {
|
|
64
|
+
GifImage(
|
|
65
|
+
modifier = Modifier.matchParentSize(),
|
|
66
|
+
url = iconUrl,
|
|
67
|
+
contentDescription = null,
|
|
68
|
+
contentScale = ContentScale.Fit,
|
|
69
|
+
)
|
|
70
|
+
} else {
|
|
71
|
+
AsyncImage(
|
|
72
|
+
modifier = Modifier.matchParentSize(),
|
|
73
|
+
model = ImageRequest.Builder(context)
|
|
74
|
+
.data(iconUrl)
|
|
75
|
+
.size(
|
|
76
|
+
coil3.size.Dimension.Undefined,
|
|
77
|
+
coil3.size.Dimension.Undefined
|
|
78
|
+
)
|
|
79
|
+
.build(),
|
|
80
|
+
contentDescription = null,
|
|
81
|
+
contentScale = ContentScale.Fit,
|
|
82
|
+
colorFilter = colorFilter,
|
|
83
|
+
)
|
|
84
|
+
}
|
|
75
85
|
}
|
|
76
86
|
}
|
|
@@ -77,7 +77,7 @@ private fun getHostFromUrl(url: String): String? {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
internal fun isGifUrl(url: String): Boolean {
|
|
81
81
|
val path = url.substringBefore('#').substringBefore('?')
|
|
82
82
|
return path.endsWith(".gif", ignoreCase = true)
|
|
83
83
|
}
|
|
@@ -26,9 +26,9 @@ import kotlin.math.roundToInt
|
|
|
26
26
|
private val THUMB_SIZE = 20.dp
|
|
27
27
|
private val THUMB_BORDER = 3.dp
|
|
28
28
|
private val TRACK_HEIGHT = 4.dp
|
|
29
|
-
private val LABEL_PAD_H
|
|
30
|
-
private val LABEL_PAD_V
|
|
31
|
-
private val LABEL_GAP
|
|
29
|
+
private val LABEL_PAD_H = Spacing.XS
|
|
30
|
+
private val LABEL_PAD_V = Spacing.XXS
|
|
31
|
+
private val LABEL_GAP = Spacing.XS // space between label and thumb top
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
private fun clamp(value: Float, min: Float, max: Float): Float =
|
|
@@ -67,7 +67,7 @@ class TooltipState {
|
|
|
67
67
|
fun rememberTooltipState(): TooltipState {
|
|
68
68
|
return remember { TooltipState() }
|
|
69
69
|
}
|
|
70
|
-
private val TOOLTIP_OFFSET
|
|
70
|
+
private val TOOLTIP_OFFSET = Spacing.S
|
|
71
71
|
private val ARROW_SIZE = 6.dp
|
|
72
72
|
private class TooltipPositionProvider(
|
|
73
73
|
private val placement: TooltipPlacement,
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
package vn.momo.kits.const
|
|
2
2
|
|
|
3
|
-
import androidx.compose.ui.unit.Dp
|
|
4
3
|
import androidx.compose.ui.unit.dp
|
|
5
4
|
|
|
6
|
-
// Divided by KitSizeScale.rate: containers scale LocalDensity for sizes, spacing must stay unscaled.
|
|
7
|
-
private fun spacing(value: Int): Dp = (value / KitSizeScale.rate).dp
|
|
8
|
-
|
|
9
5
|
object Spacing {
|
|
10
|
-
val XXS
|
|
11
|
-
val XS
|
|
12
|
-
val S
|
|
13
|
-
val M
|
|
14
|
-
val L
|
|
15
|
-
val XL
|
|
16
|
-
val XXL
|
|
17
|
-
val Size3XL
|
|
18
|
-
val Size4XL
|
|
19
|
-
val Size5XL
|
|
20
|
-
}
|
|
6
|
+
val XXS = 2.dp
|
|
7
|
+
val XS = 4.dp
|
|
8
|
+
val S = 8.dp
|
|
9
|
+
val M = 12.dp
|
|
10
|
+
val L = 16.dp
|
|
11
|
+
val XL = 24.dp
|
|
12
|
+
val XXL = 32.dp
|
|
13
|
+
val Size3XL = 48.dp
|
|
14
|
+
val Size4XL = 56.dp
|
|
15
|
+
val Size5XL = 64.dp
|
|
16
|
+
}
|
|
@@ -67,7 +67,7 @@ data class Theme(
|
|
|
67
67
|
return !assets.headerBackground.isNullOrEmpty()
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
val
|
|
70
|
+
private val lightBaseTheme = Theme(
|
|
71
71
|
dark = false,
|
|
72
72
|
colors = ColorScheme(
|
|
73
73
|
primary = Colors.pink_03,
|
|
@@ -117,14 +117,14 @@ val defaultTheme = Theme(
|
|
|
117
117
|
container = Colors.blue_08
|
|
118
118
|
)
|
|
119
119
|
),
|
|
120
|
-
font = "
|
|
120
|
+
font = "SFProText",
|
|
121
121
|
assets = ThemeAssets(
|
|
122
122
|
headerBackground = null
|
|
123
123
|
)
|
|
124
124
|
)
|
|
125
125
|
|
|
126
126
|
|
|
127
|
-
val
|
|
127
|
+
private val darkBaseTheme = Theme(
|
|
128
128
|
dark = true,
|
|
129
129
|
colors = ColorScheme(
|
|
130
130
|
primary = Colors.pink_04,
|
|
@@ -174,13 +174,19 @@ val darkTheme = Theme(
|
|
|
174
174
|
container = Colors.blue_08
|
|
175
175
|
)
|
|
176
176
|
),
|
|
177
|
-
font = "
|
|
177
|
+
font = "SFProText",
|
|
178
178
|
assets = ThemeAssets(
|
|
179
179
|
headerBackground = null
|
|
180
180
|
)
|
|
181
181
|
)
|
|
182
182
|
|
|
183
183
|
|
|
184
|
+
val defaultTheme: Theme
|
|
185
|
+
get() = lightBaseTheme.copy(font = defaultFontFamily)
|
|
186
|
+
|
|
187
|
+
val darkTheme: Theme
|
|
188
|
+
get() = darkBaseTheme.copy(font = defaultFontFamily)
|
|
189
|
+
|
|
184
190
|
val AppTheme = staticCompositionLocalOf { defaultTheme }
|
|
185
191
|
|
|
186
192
|
val AppStatusBar = staticCompositionLocalOf { 0.dp }
|
|
@@ -26,13 +26,11 @@ fun scaleSize(size: Float): Float {
|
|
|
26
26
|
return size * (context?.userScaleRate ?: KitFontScale.userScaleRate)
|
|
27
27
|
}
|
|
28
28
|
val scaleSizeMaxRate: Float = MAX_FONT_SCALE
|
|
29
|
-
|
|
30
|
-
val sizeScale = LocalSizeScale.current
|
|
31
|
-
val deviceWidth = getScreenDimensions().width * sizeScale
|
|
29
|
+
val deviceWidth = getScreenDimensions().width
|
|
32
30
|
val deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
|
|
33
31
|
|
|
34
32
|
val density = LocalDensity.current
|
|
35
|
-
val fontScale = density.fontScale
|
|
33
|
+
val fontScale = density.fontScale
|
|
36
34
|
|
|
37
35
|
var fontSizeScaleDevice = size
|
|
38
36
|
var fontSizeScaleOS = size
|
|
@@ -59,8 +57,7 @@ fun scaleSize(size: TextUnit): TextUnit {
|
|
|
59
57
|
val density = LocalDensity.current
|
|
60
58
|
|
|
61
59
|
val scaled = scaleSize(size.value)
|
|
62
|
-
|
|
63
|
-
val spValue = scaled / (density.fontScale * LocalSizeScale.current)
|
|
60
|
+
val spValue = scaled / density.fontScale
|
|
64
61
|
|
|
65
62
|
return TextUnit(value = spValue, type = TextUnitType.Sp)
|
|
66
63
|
}
|
|
@@ -123,31 +120,17 @@ private val hostFontFiles: Map<String, String> = mapOf(
|
|
|
123
120
|
)
|
|
124
121
|
}
|
|
125
122
|
|
|
126
|
-
/**
|
|
127
|
-
* Font mặc định mới, chỉ áp cho user nằm trong whitelist design system ([KitDesignSystem]).
|
|
128
|
-
* Ngoài whitelist thì quay về [LEGACY_DEFAULT_FONT_FAMILY] như trước.
|
|
129
|
-
*/
|
|
130
123
|
private const val NEW_DEFAULT_FONT_FAMILY = "MomoTrustSans"
|
|
131
124
|
private const val LEGACY_DEFAULT_FONT_FAMILY = "SFProText"
|
|
132
125
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
* (commit header title 5bfde6251); truoc do header lay font theo theme, nen ngoai
|
|
136
|
-
* whitelist ca hai deu ha ve [LEGACY_DEFAULT_FONT_FAMILY].
|
|
137
|
-
*/
|
|
138
|
-
private val newFontFamilies = setOf(NEW_DEFAULT_FONT_FAMILY, "MoMoTrustDisplay")
|
|
126
|
+
internal val defaultFontFamily: String
|
|
127
|
+
get() = if (KitDesignSystem.isWhiteList) NEW_DEFAULT_FONT_FAMILY else LEGACY_DEFAULT_FONT_FAMILY
|
|
139
128
|
|
|
140
129
|
@Composable
|
|
141
130
|
fun getFontFamily(fontFamily: String, fontWeight: FontWeight? = FontWeight.Normal): FontFamily {
|
|
142
131
|
val isWhiteList = KitDesignSystem.isWhiteList
|
|
143
|
-
val resolvedFamily =
|
|
144
|
-
if (fontFamily in newFontFamilies && !isWhiteList) {
|
|
145
|
-
LEGACY_DEFAULT_FONT_FAMILY
|
|
146
|
-
} else {
|
|
147
|
-
fontFamily
|
|
148
|
-
}
|
|
149
132
|
val defaultFile = if (isWhiteList) NEW_DEFAULT_FONT_FILE else LEGACY_DEFAULT_FONT_FILE
|
|
150
|
-
val key = "$
|
|
133
|
+
val key = "$fontFamily-${fontWeight?.weight}"
|
|
151
134
|
val fileName = hostFontFiles[key] ?: defaultFile
|
|
152
135
|
return hostFontFamily(fileName)
|
|
153
136
|
?: hostFontFamily(defaultFile)
|
|
@@ -4,6 +4,7 @@ import androidx.compose.foundation.background
|
|
|
4
4
|
import androidx.compose.foundation.layout.Arrangement
|
|
5
5
|
import androidx.compose.foundation.layout.Box
|
|
6
6
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
|
7
|
+
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|
7
8
|
import androidx.compose.foundation.layout.FlowRow
|
|
8
9
|
import androidx.compose.foundation.layout.PaddingValues
|
|
9
10
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
@@ -14,6 +15,7 @@ import androidx.compose.runtime.CompositionLocalProvider
|
|
|
14
15
|
import androidx.compose.ui.Modifier
|
|
15
16
|
import androidx.compose.ui.draw.clip
|
|
16
17
|
import androidx.compose.ui.draw.shadow
|
|
18
|
+
import androidx.compose.ui.graphics.Color
|
|
17
19
|
import androidx.compose.ui.unit.dp
|
|
18
20
|
import vn.momo.kits.components.Image
|
|
19
21
|
import vn.momo.kits.const.AppTheme
|
|
@@ -21,30 +23,30 @@ import vn.momo.kits.const.Radius
|
|
|
21
23
|
import vn.momo.kits.const.Spacing
|
|
22
24
|
|
|
23
25
|
@Composable
|
|
24
|
-
|
|
26
|
+
@OptIn(ExperimentalLayoutApi::class)
|
|
27
|
+
fun Card(
|
|
25
28
|
useShadow: Boolean = false,
|
|
26
29
|
backgroundImage: String? = null,
|
|
30
|
+
backgroundColor: Color? = null,
|
|
27
31
|
contentPadding: PaddingValues = PaddingValues(Spacing.M),
|
|
28
32
|
modifier: Modifier = Modifier,
|
|
29
33
|
content: @Composable () -> Unit,
|
|
30
34
|
) {
|
|
31
|
-
val columns =
|
|
32
|
-
val
|
|
35
|
+
val columns = gridColumns()
|
|
36
|
+
val gap = Spacing.S
|
|
33
37
|
val shape = RoundedCornerShape(Radius.M)
|
|
34
|
-
var surface = modifier.fillMaxWidth().padding(horizontal =
|
|
35
|
-
if (useShadow) surface = surface.shadow(
|
|
36
|
-
surface = surface.clip(shape)
|
|
37
|
-
if (backgroundImage == null) surface = surface.background(AppTheme.current.colors.background.surface)
|
|
38
|
+
var surface = modifier.fillMaxWidth().padding(horizontal = Spacing.M)
|
|
39
|
+
if (useShadow) surface = surface.shadow(6.dp, shape)
|
|
40
|
+
surface = surface.clip(shape).background(backgroundColor ?: AppTheme.current.colors.background.surface)
|
|
38
41
|
Box(modifier = surface) {
|
|
39
42
|
if (backgroundImage != null) {
|
|
40
43
|
Image(source = backgroundImage, modifier = Modifier.matchParentSize())
|
|
41
44
|
}
|
|
42
45
|
BoxWithConstraints(modifier = Modifier.fillMaxWidth().padding(contentPadding)) {
|
|
43
|
-
|
|
44
|
-
CompositionLocalProvider(LocalGridContext provides GridContext(columns, gutter, sizePerSpan)) {
|
|
46
|
+
CompositionLocalProvider(LocalGridContext provides gridContext(constraints.maxWidth, columns, gap)) {
|
|
45
47
|
FlowRow(
|
|
46
|
-
horizontalArrangement = Arrangement.spacedBy(
|
|
47
|
-
verticalArrangement = Arrangement.spacedBy(
|
|
48
|
+
horizontalArrangement = Arrangement.spacedBy(gap),
|
|
49
|
+
verticalArrangement = Arrangement.spacedBy(gap),
|
|
48
50
|
) { content() }
|
|
49
51
|
}
|
|
50
52
|
}
|