peachsim 0.1.661 → 0.1.663

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.
Files changed (82) hide show
  1. package/cli/commands/inspect/core.ts +9 -1
  2. package/cli/commands/inspect/settling.ts +44 -1
  3. package/cli/commands/inspect/wait-ready.ts +40 -61
  4. package/dist-lib/agent-daemon-client.cjs +1 -1
  5. package/dist-lib/agent-events.cjs +1 -1
  6. package/dist-lib/agent-identity.cjs +1 -1
  7. package/dist-lib/agent-sessions.cjs +1 -1
  8. package/dist-lib/attached-projects.cjs +1 -1
  9. package/dist-lib/auth/shared-session.cjs +1 -1
  10. package/dist-lib/backend-origin.cjs +1 -1
  11. package/dist-lib/beta.cjs +1 -1
  12. package/dist-lib/beta.mjs +1 -1
  13. package/dist-lib/bridge-constants.cjs +1 -1
  14. package/dist-lib/bridge-contract-input.cjs +6 -2
  15. package/dist-lib/bridge-contract-input.mjs +6 -2
  16. package/dist-lib/bridge-contract.cjs +1 -1
  17. package/dist-lib/bridge-contract.mjs +1 -1
  18. package/dist-lib/capture-contract.cjs +1 -1
  19. package/dist-lib/capture-contract.mjs +1 -1
  20. package/dist-lib/cli-constants.cjs +1 -1
  21. package/dist-lib/cloud-contract.cjs +1 -1
  22. package/dist-lib/cloud-contract.mjs +1 -1
  23. package/dist-lib/cloud-test-args.cjs +1 -1
  24. package/dist-lib/cloud-test-args.mjs +1 -1
  25. package/dist-lib/cloud.cjs +1 -1
  26. package/dist-lib/cloud.mjs +1 -1
  27. package/dist-lib/config.cjs +1 -1
  28. package/dist-lib/detox/index.cjs +1 -1
  29. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  30. package/dist-lib/home-paths.cjs +1 -1
  31. package/dist-lib/host/bridge-host.cjs +1 -1
  32. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  34. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  35. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  36. package/dist-lib/host/websocket-proxy.cjs +1 -1
  37. package/dist-lib/index.cjs +8 -2
  38. package/dist-lib/jump-to-source-babel.cjs +1 -1
  39. package/dist-lib/jump-to-source-native.cjs +1 -1
  40. package/dist-lib/kotlin-host.cjs +197 -60
  41. package/dist-lib/menu.cjs +1 -1
  42. package/dist-lib/menu.mjs +1 -1
  43. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  44. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  45. package/dist-lib/metro-production-bundle.cjs +1 -1
  46. package/dist-lib/metro-production-bundle.mjs +1 -1
  47. package/dist-lib/metro.cjs +1 -1
  48. package/dist-lib/native-app-identity.cjs +1 -1
  49. package/dist-lib/native-app-identity.mjs +1 -1
  50. package/dist-lib/plist.cjs +1 -1
  51. package/dist-lib/plist.mjs +1 -1
  52. package/dist-lib/profiles.cjs +1 -1
  53. package/dist-lib/public-brand.cjs +1 -1
  54. package/dist-lib/react-native-host-modules.cjs +1 -1
  55. package/dist-lib/react-native-host-modules.mjs +1 -1
  56. package/dist-lib/render-mode.cjs +1 -1
  57. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  58. package/dist-lib/sdk.cjs +29 -2
  59. package/dist-lib/sdk.mjs +28 -2
  60. package/dist-lib/skills.cjs +9 -2
  61. package/dist-lib/swift-compile.cjs +1 -1
  62. package/dist-lib/swift-compile.mjs +1 -1
  63. package/dist-lib/swift-package.cjs +1 -1
  64. package/dist-lib/swift-package.mjs +1 -1
  65. package/dist-lib/swift-submit.cjs +1 -1
  66. package/dist-lib/swift-submit.mjs +1 -1
  67. package/dist-lib/swift.cjs +1 -1
  68. package/dist-lib/vite-swift.cjs +1 -1
  69. package/dist-lib/vite.cjs +1 -1
  70. package/kotlin/AppSources/androidx/activity/ActivityViewModelLazy.kt +21 -0
  71. package/kotlin/AppSources/androidx/activity/ComponentActivity.kt +5 -3
  72. package/kotlin/AppSources/androidx/lifecycle/AndroidViewModel.kt +10 -0
  73. package/kotlin/AppSources/dev/peach/app/PeachApp.kt +16 -2
  74. package/kotlin/tools/abi-classes.main.kts +41 -0
  75. package/package.json +1 -1
  76. package/src/bridge-contract-input.ts +5 -1
  77. package/src/bridge-contract.ts +4 -1
  78. package/src/generated/android-framework-themes.json +341 -0
  79. package/src/kotlin-app.ts +47 -26
  80. package/src/kotlin-host.ts +105 -17
  81. package/src/kotlin-view-models.ts +133 -0
  82. package/src/sdk.ts +2 -1
@@ -0,0 +1,21 @@
1
+ package androidx.activity
2
+
3
+ import androidx.lifecycle.ViewModel
4
+ import androidx.lifecycle.ViewModelLazy
5
+ import androidx.lifecycle.ViewModelProvider
6
+ import androidx.lifecycle.viewmodel.CreationExtras
7
+
8
+ // activity-ktx's viewModels(): the activity's store, its default factory and
9
+ // creation extras unless the caller passes its own
10
+ inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
11
+ noinline extrasProducer: (() -> CreationExtras)? = null,
12
+ noinline factoryProducer: (() -> ViewModelProvider.Factory)? = null,
13
+ ): Lazy<VM> {
14
+ val factoryPromise = factoryProducer ?: { defaultViewModelProviderFactory }
15
+ return ViewModelLazy(
16
+ VM::class,
17
+ { viewModelStore },
18
+ factoryPromise,
19
+ { extrasProducer?.invoke() ?: this.defaultViewModelCreationExtras },
20
+ )
21
+ }
@@ -8,7 +8,6 @@ import androidx.lifecycle.LifecycleEventObserver
8
8
  import androidx.lifecycle.LifecycleOwner
9
9
  import androidx.lifecycle.LifecycleRegistry
10
10
  import androidx.lifecycle.SAVED_STATE_REGISTRY_OWNER_KEY
11
- import androidx.lifecycle.SavedStateViewModelFactory
12
11
  import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
13
12
  import androidx.lifecycle.ViewModelStore
14
13
  import androidx.lifecycle.ViewModelStoreOwner
@@ -23,7 +22,8 @@ import androidx.savedstate.SavedStateRegistryOwner
23
22
  // lifecycle, viewmodel and savedstate libraries: the registry attaches in the
24
23
  // constructor and restores in onCreate before super, the lifecycle moves up on
25
24
  // the post callbacks and down on the pre callbacks, as ReportFragment does from
26
- // API 29, and destroy clears the view model store.
25
+ // API 29, and destroy clears the view model store unless the activity is
26
+ // changing configurations.
27
27
  open class ComponentActivity : Activity(), LifecycleOwner, ViewModelStoreOwner,
28
28
  HasDefaultViewModelProviderFactory, SavedStateRegistryOwner, OnBackPressedDispatcherOwner {
29
29
  private val lifecycleRegistry = LifecycleRegistry(this)
@@ -48,7 +48,9 @@ open class ComponentActivity : Activity(), LifecycleOwner, ViewModelStoreOwner,
48
48
  }
49
49
  }
50
50
  override val savedStateRegistry: SavedStateRegistry get() = savedStateRegistryController.savedStateRegistry
51
- override val defaultViewModelProviderFactory = SavedStateViewModelFactory()
51
+ // SavedStateViewModelFactory's constructor choice, made at compile time
52
+ // for the app's view models since Kotlin/Wasm has no reflection
53
+ override val defaultViewModelProviderFactory get() = dev.peach.app.viewModelFactory()
52
54
  override val defaultViewModelCreationExtras: CreationExtras
53
55
  get() = MutableCreationExtras().also {
54
56
  it[SAVED_STATE_REGISTRY_OWNER_KEY] = this
@@ -0,0 +1,10 @@
1
+ package androidx.lifecycle
2
+
3
+ import android.app.Application
4
+
5
+ // androidx.lifecycle's AndroidViewModel: a view model that holds its
6
+ // application, which the default factory passes to its constructor
7
+ open class AndroidViewModel(private val application: Application) : ViewModel() {
8
+ @Suppress("UNCHECKED_CAST")
9
+ open fun <T : Application> getApplication(): T = application as T
10
+ }
@@ -15,6 +15,7 @@ import android.view.ViewGroup
15
15
  import android.view.Window
16
16
  import android.view.WindowTheme
17
17
  import androidx.activity.ComponentActivity
18
+ import androidx.lifecycle.ViewModelProvider
18
19
  import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
19
20
  import androidx.compose.runtime.Composable
20
21
  import androidx.compose.runtime.CompositionLocalProvider
@@ -45,14 +46,24 @@ import org.json.JSONObject
45
46
  internal class PeachAppSpec(
46
47
  val launcher: ComponentName,
47
48
  val component: ComponentName,
48
- val window: WindowTheme,
49
+ // the launcher activity's window theme in a day and a night configuration,
50
+ // values-night over values
51
+ val dayWindow: WindowTheme,
52
+ val nightWindow: WindowTheme,
49
53
  val createApplication: () -> Application,
50
54
  val createActivity: () -> Activity,
51
55
  // the activity's configChanges includes uiMode: it takes a night mode
52
56
  // change in onConfigurationChanged rather than relaunching
53
57
  val handlesUiMode: Boolean,
58
+ // the app's view models, each built with the constructor the device's
59
+ // default factory finds for it
60
+ val viewModels: ViewModelProvider.Factory,
54
61
  )
55
62
 
63
+ internal fun viewModelFactory(): ViewModelProvider.Factory = runningApp().spec.viewModels
64
+
65
+ internal fun peachApplication(): Application = runningApp().application
66
+
56
67
  // the insets the device delivers to the window's content, in pixels: all of
57
68
  // them on an edge-to-edge window, none once the decor fits system windows.
58
69
  // insets lists the status bars, navigation bars, display cutout, system
@@ -192,7 +203,10 @@ private fun launchActivity(app: AppProcess, lastNonConfigurationInstance: Any?):
192
203
  mount.emitAtFrame("window") { window.describe().toString() }
193
204
  }
194
205
  }
195
- window = Window(activity, spec.window, host)
206
+ // the theme the activity is created under: a relaunch after a night
207
+ // change takes the other one
208
+ val theme = if (isNight(processResources.configuration)) spec.nightWindow else spec.dayWindow
209
+ window = Window(activity, theme, host)
196
210
  activity.attach(
197
211
  app.application,
198
212
  spec.component,
@@ -0,0 +1,41 @@
1
+ // prints an app klib's classes as the compiler resolved them, one JSON object
2
+ // per line: qualified name, kind, modality, whether it is inner or generic,
3
+ // its supertypes and its public constructors' parameter types, each marked
4
+ // when every parameter has a default
5
+ @file:OptIn(org.jetbrains.kotlin.library.abi.ExperimentalLibraryAbiReader::class)
6
+
7
+ import org.jetbrains.kotlin.library.abi.*
8
+
9
+ fun name(qualified: AbiQualifiedName): String {
10
+ val pkg = qualified.packageName.value.replace('/', '.')
11
+ val relative = qualified.relativeName.value
12
+ return if (pkg.isEmpty()) relative else "$pkg.$relative"
13
+ }
14
+
15
+ fun type(type: AbiType): String =
16
+ ((type as? AbiType.Simple)?.classifierReference as? AbiClassifierReference.ClassReference)
17
+ ?.let { name(it.className) } ?: "?"
18
+
19
+ fun quote(value: String) = "\"" + value.replace("\\", "\\\\").replace("\"", "\\\"") + "\""
20
+
21
+ fun walk(declaration: AbiDeclaration) {
22
+ if (declaration !is AbiClass) return
23
+ val constructors = declaration.declarations.filterIsInstance<AbiFunction>()
24
+ .filter { it.isConstructor }
25
+ .map { constructor ->
26
+ val parameters = constructor.valueParameters.joinToString(",", "[", "]") { quote(type(it.type)) }
27
+ "{\"parameters\":$parameters,\"defaulted\":${constructor.valueParameters.all { it.hasDefaultArg }}}"
28
+ }
29
+ println(
30
+ "{\"name\":${quote(name(declaration.qualifiedName))}" +
31
+ ",\"kind\":${quote(declaration.kind.name)}" +
32
+ ",\"modality\":${quote(declaration.modality.name)}" +
33
+ ",\"inner\":${declaration.isInner}" +
34
+ ",\"generic\":${declaration.typeParameters.isNotEmpty()}" +
35
+ ",\"supers\":${declaration.superTypes.joinToString(",", "[", "]") { quote(type(it)) }}" +
36
+ ",\"constructors\":${constructors.joinToString(",", "[", "]")}}",
37
+ )
38
+ declaration.declarations.forEach(::walk)
39
+ }
40
+
41
+ LibraryAbiReader.readAbiInfo(java.io.File(args[0])).topLevelDeclarations.declarations.forEach(::walk)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.661",
3
+ "version": "0.1.663",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -415,8 +415,12 @@ export function parseSemanticWaitOptions(value: unknown): SemanticWaitOptions {
415
415
  const type = stringValue(condition.type, 'waitFor.condition.type')
416
416
  const timeoutMs = semanticWaitTimeout(input, 'waitFor')
417
417
  if (type === 'ready') {
418
+ const stableMs = optionalNumber(condition, 'stableMs', 'waitFor.condition')
419
+ if (stableMs !== undefined && stableMs < 0) {
420
+ validationFailure('waitFor.condition.stableMs', 'must be at least 0')
421
+ }
418
422
  return {
419
- condition: { type },
423
+ condition: { type, ...(stableMs === undefined ? {} : { stableMs }) },
420
424
  ...(timeoutMs === undefined ? {} : { timeoutMs }),
421
425
  }
422
426
  }
@@ -332,7 +332,10 @@ export interface PerformResult {
332
332
  // something to look at — those are 1x1 and painted under the whole app, so they
333
333
  // are permanently occluded and `present` can never match one.
334
334
  export type SemanticWaitCondition =
335
- | { type: 'ready' }
335
+ // stableMs: how long the node count must hold before ready matches
336
+ // (SEMANTIC_READY_NODE_STABLE_MS by default). a caller that already waited
337
+ // for the app to settle passes 0 to read the settled tree at once.
338
+ | { type: 'ready'; stableMs?: number }
336
339
  | { type: 'present'; selector: SimSemanticResolveSelector }
337
340
  | { type: 'mounted'; selector: SimSemanticResolveSelector }
338
341
  | { type: 'absent'; selector: SimSemanticResolveSelector }
@@ -6299,5 +6299,346 @@
6299
6299
  "legacy_light_control_normal": "#99000000",
6300
6300
  "legacy_light_button_pressed": "@color/legacy_orange",
6301
6301
  "legacy_light_button_normal": "#f3dbdbdb"
6302
+ },
6303
+ "night": {
6304
+ "styles": {
6305
+ "Theme.DeviceDefault.Settings": {
6306
+ "parent": "Theme.DeviceDefault",
6307
+ "items": {
6308
+ "windowLightStatusBar": "false",
6309
+ "navigationBarColor": "@android:color/black",
6310
+ "windowLightNavigationBar": "false",
6311
+ "colorPrimary": "@color/primary_dark_device_default_settings",
6312
+ "colorPrimaryDark": "@color/primary_dark_device_default_settings",
6313
+ "colorBackground": "@color/primary_dark_device_default_settings",
6314
+ "colorEdgeEffect": "@color/edge_effect_device_default_dark",
6315
+ "colorListDivider": "@color/list_divider_color_dark",
6316
+ "opacityListDivider": "@color/list_divider_opacity_device_default_dark"
6317
+ }
6318
+ },
6319
+ "Theme.DeviceDefault.Settings.DialogBase": {
6320
+ "parent": "Theme.Material.BaseDialog",
6321
+ "items": {
6322
+ "colorPrimary": "@color/primary_dark_device_default_settings",
6323
+ "colorPrimaryDark": "@color/primary_dark_device_default_settings",
6324
+ "colorSecondary": "@color/secondary_device_default_settings",
6325
+ "colorAccent": "@color/accent_device_default_dark",
6326
+ "colorError": "@color/error_color_device_default_dark",
6327
+ "alertDialogTheme": "@style/Theme.DeviceDefault.Dialog.Alert"
6328
+ }
6329
+ },
6330
+ "Theme.DeviceDefault.Dialog.AppError": {
6331
+ "parent": "Theme.DeviceDefault.Dialog.Alert",
6332
+ "items": {}
6333
+ },
6334
+ "Theme.DeviceDefault.Dialog.Alert.DayNight": {
6335
+ "parent": "Theme.DeviceDefault.Dialog.Alert",
6336
+ "items": {}
6337
+ },
6338
+ "Theme.DeviceDefault.DayNight": {
6339
+ "parent": "Theme.DeviceDefault",
6340
+ "items": {}
6341
+ },
6342
+ "ThemeOverlay.DeviceDefault.Accent.DayNight": {
6343
+ "parent": "@style/ThemeOverlay.DeviceDefault.Accent",
6344
+ "items": {}
6345
+ },
6346
+ "Theme.DeviceDefault.Resolver": {
6347
+ "parent": "Theme.DeviceDefault.ResolverCommon",
6348
+ "items": {
6349
+ "windowLightNavigationBar": "false",
6350
+ "colorBackgroundFloating": "@android:color/GM2_grey_800",
6351
+ "textColorSecondary": "@android:color/resolver_text_color_secondary_dark"
6352
+ }
6353
+ },
6354
+ "Theme.DeviceDefault.AutofillHalfScreenDialogButton": {
6355
+ "parent": "Theme.DeviceDefault.Panel",
6356
+ "items": {
6357
+ "selectableItemBackground": "@android:color/transparent",
6358
+ "colorAccentPrimaryVariant": "@color/system_accent1_200",
6359
+ "colorAccentPrimary": "@color/system_accent1_700",
6360
+ "textColorPrimary": "@color/system_neutral1_100",
6361
+ "textColorSecondary": "@color/system_neutral2_100",
6362
+ "colorListDivider": "@color/white"
6363
+ }
6364
+ },
6365
+ "Theme.DeviceDefault.AutofillHalfScreenDialogList": {
6366
+ "parent": "Theme.DeviceDefault.DayNight",
6367
+ "items": {
6368
+ "colorForeground": "@android:color/white"
6369
+ }
6370
+ },
6371
+ "Theme.DeviceDefault.AutofillDialogExpressiveButton": {
6372
+ "parent": "Theme.DeviceDefault.Panel",
6373
+ "items": {
6374
+ "colorPrimary": "@color/system_primary_dark"
6375
+ }
6376
+ }
6377
+ },
6378
+ "colors": {
6379
+ "accent_device_default": "@color/accent_device_default_dark",
6380
+ "notification_primary_text_color_current": "@color/notification_primary_text_color_dark",
6381
+ "notification_secondary_text_color_current": "@color/notification_secondary_text_color_dark",
6382
+ "notification_default_color_current": "@color/notification_default_color_dark",
6383
+ "chooser_row_divider": "@color/list_divider_color_dark",
6384
+ "chooser_gradient_background": "@color/loading_gradient_background_color_dark",
6385
+ "chooser_gradient_highlight": "@color/loading_gradient_highlight_color_dark",
6386
+ "call_notification_decline_color": "#E66A5E",
6387
+ "call_notification_answer_color": "#5DBA80",
6388
+ "personal_apps_suspension_notification_color": "#8AB4F8",
6389
+ "overview_background": "@color/overview_background_dark",
6390
+ "user_icon_4": "#fff439a0",
6391
+ "user_icon_6": "#ff4ecde6",
6392
+ "user_icon_7": "#fffbbc04",
6393
+ "user_icon_8": "#fffa903e",
6394
+ "language_picker_item_text_color": "#F1F3F4",
6395
+ "language_picker_item_text_color_secondary": "#BDC1C6",
6396
+ "language_picker_item_text_color_selected": "#202124",
6397
+ "language_picker_item_text_color_secondary_selected": "#202124",
6398
+ "language_picker_item_selected_indicator": "#202124",
6399
+ "language_picker_item_selected_bg": "#92B3F2",
6400
+ "language_picker_item_selected_stroke": "#185ABC",
6401
+ "shade_panel_fg": "@color/shade_panel_fg_color",
6402
+ "shade_panel_bg": "@color/shade_panel_bg_color",
6403
+ "side_fps_toast_background": "#2E3132",
6404
+ "side_fps_text_color": "#EFF1F2",
6405
+ "side_fps_button_color": "#33B9DB",
6406
+ "security_privacy_notification_tint_normal": "#8AB4F8",
6407
+ "system_on_primary_fixed": "@color/system_on_primary_fixed_dark",
6408
+ "system_on_primary_fixed_variant": "@color/system_on_primary_fixed_variant_dark",
6409
+ "system_on_secondary_fixed": "@color/system_on_secondary_fixed_dark",
6410
+ "system_on_secondary_fixed_variant": "@color/system_on_secondary_fixed_variant_dark",
6411
+ "system_on_tertiary_fixed": "@color/system_on_tertiary_fixed_dark",
6412
+ "system_on_tertiary_fixed_variant": "@color/system_on_tertiary_fixed_variant_dark",
6413
+ "system_primary_fixed": "@color/system_primary_fixed_dark",
6414
+ "system_primary_fixed_dim": "@color/system_primary_fixed_dim_dark",
6415
+ "system_secondary_fixed": "@color/system_secondary_fixed_dark",
6416
+ "system_secondary_fixed_dim": "@color/system_secondary_fixed_dim_dark",
6417
+ "system_tertiary_fixed": "@color/system_tertiary_fixed_dark",
6418
+ "system_tertiary_fixed_dim": "@color/system_tertiary_fixed_dim_dark",
6419
+ "semanticGreenContainerLow": "#00522D",
6420
+ "semanticGreenOnContainerLow": "#84FAB1",
6421
+ "semanticGreenContainer": "#26A565",
6422
+ "semanticGreenOnContainer": "#00210F",
6423
+ "semanticGreenOnContainerVariant": "#00210F",
6424
+ "semanticGreenContainerHigh": "#3FB876",
6425
+ "semanticGreenOnContainerHigh": "#410002",
6426
+ "semanticGreenOnSurface": "#E5F9E1",
6427
+ "semanticGreenOnSurfaceVariant": "#3FB876",
6428
+ "semanticGreenSurfaceContainerLow": "#00210F",
6429
+ "semanticGreenSurfaceContainer": "#022513",
6430
+ "semanticGreenSurfaceContainerHigh": "#0D301C",
6431
+ "semanticGreenSurfaceContainerHighest": "#193B27",
6432
+ "semanticYellowContainerLow": "#594400",
6433
+ "semanticYellowOnContainerLow": "#FFDF93",
6434
+ "semanticYellowContainer": "#F5BF00",
6435
+ "semanticYellowOnContainer": "#241A00",
6436
+ "semanticYellowContainerHigh": "#F5BF00",
6437
+ "semanticYellowOnContainerHigh": "#241A00",
6438
+ "semanticYellowOnSurface": "#FFF2DB",
6439
+ "semanticYellowOnSurfaceVariant": "#CA9D00",
6440
+ "semanticYellowSurfaceContainerLow": "#241A00",
6441
+ "semanticYellowSurfaceContainer": "#291E00",
6442
+ "semanticYellowSurfaceContainerHigh": "#362800",
6443
+ "semanticYellowSurfaceContainerHighest": "#423308",
6444
+ "semanticRedContainerLow": "#910A0E",
6445
+ "semanticRedOnContainerLow": "#FFDAD6",
6446
+ "semanticRedContainer": "#F95A4F",
6447
+ "semanticRedOnContainer": "#410002",
6448
+ "semanticRedOnContainerVariant": "#410002",
6449
+ "semanticRedContainerHigh": "#F95A4F",
6450
+ "semanticRedOnContainerHigh": "#410002",
6451
+ "semanticRedOnSurface": "#FFF0EE",
6452
+ "semanticRedOnSurfaceVariant": "#FF7B6E",
6453
+ "semanticRedSurfaceContainerLow": "#33110E",
6454
+ "semanticRedSurfaceContainer": "#381511",
6455
+ "semanticRedSurfaceContainerHigh": "#441F1B",
6456
+ "semanticRedSurfaceContainerHighest": "#512925",
6457
+ "semanticBlueContainerLow": "#00429B",
6458
+ "semanticBlueOnContainerLow": "#D5E3FF",
6459
+ "semanticBlueContainer": "#4E8FF8",
6460
+ "semanticBlueOnContainer": "#001945",
6461
+ "semanticBlueOnContainerVariant": "#001945",
6462
+ "semanticBlueContainerHigh": "#68A4FE",
6463
+ "semanticBlueOnContainerHigh": "#001945",
6464
+ "semanticBlueOnSurface": "#F0F3FF",
6465
+ "semanticBlueOnSurfaceVariant": "#68A4FE",
6466
+ "semanticBlueSurfaceContainerLow": "#001945",
6467
+ "semanticBlueSurfaceContainer": "#001D4D",
6468
+ "semanticBlueSurfaceContainerHigh": "#002761",
6469
+ "semanticBlueSurfaceContainerHighest": "#003177",
6470
+ "system_accent1_0": "@color/system_accent1_0_dark",
6471
+ "system_accent1_10": "@color/system_accent1_10_dark",
6472
+ "system_accent1_50": "@color/system_accent1_50_dark",
6473
+ "system_accent1_100": "@color/system_accent1_100_dark",
6474
+ "system_accent1_200": "@color/system_accent1_200_dark",
6475
+ "system_accent1_300": "@color/system_accent1_300_dark",
6476
+ "system_accent1_400": "@color/system_accent1_400_dark",
6477
+ "system_accent1_500": "@color/system_accent1_500_dark",
6478
+ "system_accent1_600": "@color/system_accent1_600_dark",
6479
+ "system_accent1_700": "@color/system_accent1_700_dark",
6480
+ "system_accent1_800": "@color/system_accent1_800_dark",
6481
+ "system_accent1_900": "@color/system_accent1_900_dark",
6482
+ "system_accent1_1000": "@color/system_accent1_1000_dark",
6483
+ "system_accent2_0": "@color/system_accent2_0_dark",
6484
+ "system_accent2_10": "@color/system_accent2_10_dark",
6485
+ "system_accent2_50": "@color/system_accent2_50_dark",
6486
+ "system_accent2_100": "@color/system_accent2_100_dark",
6487
+ "system_accent2_200": "@color/system_accent2_200_dark",
6488
+ "system_accent2_300": "@color/system_accent2_300_dark",
6489
+ "system_accent2_400": "@color/system_accent2_400_dark",
6490
+ "system_accent2_500": "@color/system_accent2_500_dark",
6491
+ "system_accent2_600": "@color/system_accent2_600_dark",
6492
+ "system_accent2_700": "@color/system_accent2_700_dark",
6493
+ "system_accent2_800": "@color/system_accent2_800_dark",
6494
+ "system_accent2_900": "@color/system_accent2_900_dark",
6495
+ "system_accent2_1000": "@color/system_accent2_1000_dark",
6496
+ "system_accent3_0": "@color/system_accent3_0_dark",
6497
+ "system_accent3_10": "@color/system_accent3_10_dark",
6498
+ "system_accent3_50": "@color/system_accent3_50_dark",
6499
+ "system_accent3_100": "@color/system_accent3_100_dark",
6500
+ "system_accent3_200": "@color/system_accent3_200_dark",
6501
+ "system_accent3_300": "@color/system_accent3_300_dark",
6502
+ "system_accent3_400": "@color/system_accent3_400_dark",
6503
+ "system_accent3_500": "@color/system_accent3_500_dark",
6504
+ "system_accent3_600": "@color/system_accent3_600_dark",
6505
+ "system_accent3_700": "@color/system_accent3_700_dark",
6506
+ "system_accent3_800": "@color/system_accent3_800_dark",
6507
+ "system_accent3_900": "@color/system_accent3_900_dark",
6508
+ "system_accent3_1000": "@color/system_accent3_1000_dark",
6509
+ "system_neutral1_0": "@color/system_neutral1_0_dark",
6510
+ "system_neutral1_10": "@color/system_neutral1_10_dark",
6511
+ "system_neutral1_50": "@color/system_neutral1_50_dark",
6512
+ "system_neutral1_100": "@color/system_neutral1_100_dark",
6513
+ "system_neutral1_200": "@color/system_neutral1_200_dark",
6514
+ "system_neutral1_300": "@color/system_neutral1_300_dark",
6515
+ "system_neutral1_400": "@color/system_neutral1_400_dark",
6516
+ "system_neutral1_500": "@color/system_neutral1_500_dark",
6517
+ "system_neutral1_600": "@color/system_neutral1_600_dark",
6518
+ "system_neutral1_700": "@color/system_neutral1_700_dark",
6519
+ "system_neutral1_800": "@color/system_neutral1_800_dark",
6520
+ "system_neutral1_900": "@color/system_neutral1_900_dark",
6521
+ "system_neutral1_1000": "@color/system_neutral1_1000_dark",
6522
+ "system_neutral2_0": "@color/system_neutral2_0_dark",
6523
+ "system_neutral2_10": "@color/system_neutral2_10_dark",
6524
+ "system_neutral2_50": "@color/system_neutral2_50_dark",
6525
+ "system_neutral2_100": "@color/system_neutral2_100_dark",
6526
+ "system_neutral2_200": "@color/system_neutral2_200_dark",
6527
+ "system_neutral2_300": "@color/system_neutral2_300_dark",
6528
+ "system_neutral2_400": "@color/system_neutral2_400_dark",
6529
+ "system_neutral2_500": "@color/system_neutral2_500_dark",
6530
+ "system_neutral2_600": "@color/system_neutral2_600_dark",
6531
+ "system_neutral2_700": "@color/system_neutral2_700_dark",
6532
+ "system_neutral2_800": "@color/system_neutral2_800_dark",
6533
+ "system_neutral2_900": "@color/system_neutral2_900_dark",
6534
+ "system_neutral2_1000": "@color/system_neutral2_1000_dark",
6535
+ "system_error_0": "@color/system_error_0_dark",
6536
+ "system_error_10": "@color/system_error_10_dark",
6537
+ "system_error_50": "@color/system_error_50_dark",
6538
+ "system_error_100": "@color/system_error_100_dark",
6539
+ "system_error_200": "@color/system_error_200_dark",
6540
+ "system_error_300": "@color/system_error_300_dark",
6541
+ "system_error_400": "@color/system_error_400_dark",
6542
+ "system_error_500": "@color/system_error_500_dark",
6543
+ "system_error_600": "@color/system_error_600_dark",
6544
+ "system_error_700": "@color/system_error_700_dark",
6545
+ "system_error_800": "@color/system_error_800_dark",
6546
+ "system_error_900": "@color/system_error_900_dark",
6547
+ "system_error_1000": "@color/system_error_1000_dark",
6548
+ "materialColorBackground": "@color/system_background_dark",
6549
+ "materialColorControlActivated": "@color/system_control_activated_dark",
6550
+ "materialColorControlHighlight": "@color/system_control_highlight_dark",
6551
+ "materialColorControlNormal": "@color/system_control_normal_dark",
6552
+ "materialColorError": "@color/system_error_dark",
6553
+ "materialColorErrorContainer": "@color/system_error_container_dark",
6554
+ "materialColorErrorDim": "@color/system_error_dim_dark",
6555
+ "materialColorInverseOnSurface": "@color/system_inverse_on_surface_dark",
6556
+ "materialColorInversePrimary": "@color/system_inverse_primary_dark",
6557
+ "materialColorInverseSurface": "@color/system_inverse_surface_dark",
6558
+ "materialColorOnBackground": "@color/system_on_background_dark",
6559
+ "materialColorOnError": "@color/system_on_error_dark",
6560
+ "materialColorOnErrorContainer": "@color/system_on_error_container_dark",
6561
+ "materialColorOnPrimary": "@color/system_on_primary_dark",
6562
+ "materialColorOnPrimaryContainer": "@color/system_on_primary_container_dark",
6563
+ "materialColorOnSecondary": "@color/system_on_secondary_dark",
6564
+ "materialColorOnSecondaryContainer": "@color/system_on_secondary_container_dark",
6565
+ "materialColorOnSurface": "@color/system_on_surface_dark",
6566
+ "materialColorOnSurfaceVariant": "@color/system_on_surface_variant_dark",
6567
+ "materialColorOnTertiary": "@color/system_on_tertiary_dark",
6568
+ "materialColorOnTertiaryContainer": "@color/system_on_tertiary_container_dark",
6569
+ "materialColorOutline": "@color/system_outline_dark",
6570
+ "materialColorOutlineVariant": "@color/system_outline_variant_dark",
6571
+ "materialColorPaletteKeyColorError": "@color/system_palette_key_color_error_dark",
6572
+ "materialColorPaletteKeyColorNeutral": "@color/system_palette_key_color_neutral_dark",
6573
+ "materialColorPaletteKeyColorNeutralVariant": "@color/system_palette_key_color_neutral_variant_dark",
6574
+ "materialColorPaletteKeyColorPrimary": "@color/system_palette_key_color_primary_dark",
6575
+ "materialColorPaletteKeyColorSecondary": "@color/system_palette_key_color_secondary_dark",
6576
+ "materialColorPaletteKeyColorTertiary": "@color/system_palette_key_color_tertiary_dark",
6577
+ "materialColorPrimary": "@color/system_primary_dark",
6578
+ "materialColorPrimaryContainer": "@color/system_primary_container_dark",
6579
+ "materialColorPrimaryDim": "@color/system_primary_dim_dark",
6580
+ "materialColorScrim": "@color/system_scrim_dark",
6581
+ "materialColorSecondary": "@color/system_secondary_dark",
6582
+ "materialColorSecondaryContainer": "@color/system_secondary_container_dark",
6583
+ "materialColorSecondaryDim": "@color/system_secondary_dim_dark",
6584
+ "materialColorShadow": "@color/system_shadow_dark",
6585
+ "materialColorSurface": "@color/system_surface_dark",
6586
+ "materialColorSurfaceBright": "@color/system_surface_bright_dark",
6587
+ "materialColorSurfaceContainer": "@color/system_surface_container_dark",
6588
+ "materialColorSurfaceContainerHigh": "@color/system_surface_container_high_dark",
6589
+ "materialColorSurfaceContainerHighest": "@color/system_surface_container_highest_dark",
6590
+ "materialColorSurfaceContainerLow": "@color/system_surface_container_low_dark",
6591
+ "materialColorSurfaceContainerLowest": "@color/system_surface_container_lowest_dark",
6592
+ "materialColorSurfaceDim": "@color/system_surface_dim_dark",
6593
+ "materialColorSurfaceTint": "@color/system_surface_tint_dark",
6594
+ "materialColorSurfaceVariant": "@color/system_surface_variant_dark",
6595
+ "materialColorTertiary": "@color/system_tertiary_dark",
6596
+ "materialColorTertiaryContainer": "@color/system_tertiary_container_dark",
6597
+ "materialColorTertiaryDim": "@color/system_tertiary_dim_dark",
6598
+ "materialColorTextHintInverse": "@color/system_text_hint_inverse_dark",
6599
+ "materialColorTextPrimaryInverse": "@color/system_text_primary_inverse_dark",
6600
+ "materialColorTextPrimaryInverseDisableOnly": "@color/system_text_primary_inverse_disable_only_dark",
6601
+ "materialColorTextSecondaryAndTertiaryInverse": "@color/system_text_secondary_and_tertiary_inverse_dark",
6602
+ "materialColorTextSecondaryAndTertiaryInverseDisabled": "@color/system_text_secondary_and_tertiary_inverse_disabled_dark",
6603
+ "materialColorOnPrimaryFixed": "@color/system_on_primary_fixed_dark",
6604
+ "materialColorOnPrimaryFixedVariant": "@color/system_on_primary_fixed_variant_dark",
6605
+ "materialColorOnSecondaryFixed": "@color/system_on_secondary_fixed_dark",
6606
+ "materialColorOnSecondaryFixedVariant": "@color/system_on_secondary_fixed_variant_dark",
6607
+ "materialColorOnTertiaryFixed": "@color/system_on_tertiary_fixed_dark",
6608
+ "materialColorOnTertiaryFixedVariant": "@color/system_on_tertiary_fixed_variant_dark",
6609
+ "materialColorPrimaryFixed": "@color/system_primary_fixed_dark",
6610
+ "materialColorPrimaryFixedDim": "@color/system_primary_fixed_dim_dark",
6611
+ "materialColorSecondaryFixed": "@color/system_secondary_fixed_dark",
6612
+ "materialColorSecondaryFixedDim": "@color/system_secondary_fixed_dim_dark",
6613
+ "materialColorTertiaryFixed": "@color/system_tertiary_fixed_dark",
6614
+ "materialColorTertiaryFixedDim": "@color/system_tertiary_fixed_dim_dark",
6615
+ "customColorBrandA": "@color/system_brand_a_dark",
6616
+ "customColorBrandB": "@color/system_brand_b_dark",
6617
+ "customColorBrandC": "@color/system_brand_c_dark",
6618
+ "customColorBrandD": "@color/system_brand_d_dark",
6619
+ "customColorClockHour": "@color/system_clock_hour_dark",
6620
+ "customColorClockMinute": "@color/system_clock_minute_dark",
6621
+ "customColorClockSecond": "@color/system_clock_second_dark",
6622
+ "customColorOnShadeActive": "@color/system_on_shade_active_dark",
6623
+ "customColorOnShadeActiveVariant": "@color/system_on_shade_active_variant_dark",
6624
+ "customColorOnShadeInactive": "@color/system_on_shade_inactive_dark",
6625
+ "customColorOnShadeInactiveVariant": "@color/system_on_shade_inactive_variant_dark",
6626
+ "customColorOnThemeApp": "@color/system_on_theme_app_dark",
6627
+ "customColorOverviewBackground": "@color/system_overview_background_dark",
6628
+ "customColorShadeActive": "@color/system_shade_active_dark",
6629
+ "customColorShadeDisabled": "@color/system_shade_disabled_dark",
6630
+ "customColorShadeInactive": "@color/system_shade_inactive_dark",
6631
+ "customColorSurfaceEffect0": "@color/system_surface_effect_0_dark",
6632
+ "customColorSurfaceEffect0Fallback": "@color/system_surface_effect_0_fallback_dark",
6633
+ "customColorSurfaceEffect1": "@color/system_surface_effect_1_dark",
6634
+ "customColorSurfaceEffect2": "@color/system_surface_effect_2_dark",
6635
+ "customColorSurfaceEffect3": "@color/system_surface_effect_3_dark",
6636
+ "customColorThemeApp": "@color/system_theme_app_dark",
6637
+ "customColorThemeAppRing": "@color/system_theme_app_ring_dark",
6638
+ "customColorThemeNotif": "@color/system_theme_notif_dark",
6639
+ "customColorUnderSurface": "@color/system_under_surface_dark",
6640
+ "customColorWeatherTemp": "@color/system_weather_temp_dark",
6641
+ "customColorWidgetBackground": "@color/system_widget_background_dark"
6642
+ }
6302
6643
  }
6303
6644
  }
package/src/kotlin-app.ts CHANGED
@@ -9,10 +9,22 @@ import {
9
9
  frameworkColor,
10
10
  readResourceValues,
11
11
  resolveThemeAttribute,
12
+ type ResourceValues,
12
13
  } from './android-theme'
13
14
  import { parseXml, type XmlElement } from './android-xml'
14
15
  import frameworkThemes from './generated/android-framework-themes.json' with { type: 'json' }
15
16
 
17
+ // statusBarColor and navigationBarColor are ARGB
18
+ export interface KotlinWindowTheme {
19
+ edgeToEdgeEnforced: boolean
20
+ statusBarColor: number
21
+ navigationBarColor: number
22
+ statusBarContrastEnforced: boolean
23
+ navigationBarContrastEnforced: boolean
24
+ lightStatusBar: boolean
25
+ lightNavigationBar: boolean
26
+ }
27
+
16
28
  export interface KotlinAppProject {
17
29
  projectDir: string
18
30
  moduleDir: string
@@ -21,17 +33,9 @@ export interface KotlinAppProject {
21
33
  packageName: string
22
34
  namespace: string
23
35
  targetSdk: number
24
- // the launched activity's window as its theme and target SDK configure it;
25
- // statusBarColor and navigationBarColor are ARGB
26
- window: {
27
- edgeToEdgeEnforced: boolean
28
- statusBarColor: number
29
- navigationBarColor: number
30
- statusBarContrastEnforced: boolean
31
- navigationBarContrastEnforced: boolean
32
- lightStatusBar: boolean
33
- lightNavigationBar: boolean
34
- }
36
+ // the launched activity's window as its theme and target SDK configure it
37
+ // in a day and a night configuration
38
+ window: { day: KotlinWindowTheme; night: KotlinWindowTheme }
35
39
  applicationClass: string | null
36
40
  launcher: { name: string; targetClass: string }
37
41
  // back reaches the activity through its window's back dispatch rather than
@@ -188,24 +192,38 @@ function defaultTheme(targetSdk: number): string {
188
192
  // out, which only target 35 may. an enforced window's status bar is
189
193
  // transparent and setStatusBarColor does nothing. an unset or @null value
190
194
  // reads as the default PhoneWindow passes, as TypedArray returns it.
195
+ // a night configuration takes the styles and colors values-night redefines,
196
+ // in the app and the framework, over values.
191
197
  function readWindowTheme(
192
198
  moduleDir: string,
193
199
  theme: string | undefined,
194
200
  targetSdk: number,
195
- ): KotlinAppProject['window'] {
196
- const values = path.join(moduleDir, 'src/main/res/values')
197
- const app = readResourceValues(
198
- fs.existsSync(values)
199
- ? fs
200
- .readdirSync(values)
201
- .filter((entry) => entry.endsWith('.xml'))
202
- .map((entry) => {
203
- const file = path.join(values, entry)
204
- return { file, text: fs.readFileSync(file, 'utf8') }
205
- })
206
- : [],
207
- )
208
- const sources = { android: frameworkThemes, app }
201
+ night: boolean,
202
+ ): KotlinWindowTheme {
203
+ const read = (qualifier: string) => {
204
+ const values = path.join(moduleDir, 'src/main/res', qualifier)
205
+ return readResourceValues(
206
+ fs.existsSync(values)
207
+ ? fs
208
+ .readdirSync(values)
209
+ .filter((entry) => entry.endsWith('.xml'))
210
+ .map((entry) => {
211
+ const file = path.join(values, entry)
212
+ return { file, text: fs.readFileSync(file, 'utf8') }
213
+ })
214
+ : [],
215
+ )
216
+ }
217
+ const over = (base: ResourceValues, qualified: ResourceValues): ResourceValues => ({
218
+ styles: { ...base.styles, ...qualified.styles },
219
+ colors: { ...base.colors, ...qualified.colors },
220
+ })
221
+ const sources = night
222
+ ? {
223
+ android: over(frameworkThemes, frameworkThemes.night),
224
+ app: over(read('values'), read('values-night')),
225
+ }
226
+ : { android: frameworkThemes, app: read('values') }
209
227
  const name = theme ?? defaultTheme(targetSdk)
210
228
  const flag = (attribute: string, fallback = false) => {
211
229
  const value = resolveThemeAttribute(name, attribute, sources)
@@ -452,7 +470,10 @@ export function readKotlinApp(
452
470
  packageName: applicationId ?? base,
453
471
  namespace: base,
454
472
  targetSdk,
455
- window: readWindowTheme(moduleDir, theme, targetSdk),
473
+ window: {
474
+ day: readWindowTheme(moduleDir, theme, targetSdk, false),
475
+ night: readWindowTheme(moduleDir, theme, targetSdk, true),
476
+ },
456
477
  applicationClass: applicationName ? className(applicationName) : null,
457
478
  launcher: { name: launcherName, targetClass },
458
479
  predictiveBack,