diff --git a/resources/android/ActivityIndicatorRenderer.kt b/resources/android/ActivityIndicatorRenderer.kt index 19a19bc..57b3645 100644 --- a/resources/android/ActivityIndicatorRenderer.kt +++ b/resources/android/ActivityIndicatorRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.size import androidx.compose.material3.CircularProgressIndicator import androidx.compose.runtime.Composable @@ -11,6 +10,7 @@ import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.liveRegion import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -24,7 +24,7 @@ object ActivityIndicatorRenderer { val size = p.getString("size", "md") val a11yLabel = p.getString("a11y_label") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light // Optional override — primitives like spinners sometimes need to // match their container. When unset, fall through to theme.primary. diff --git a/resources/android/BadgeRenderer.kt b/resources/android/BadgeRenderer.kt index 51d440e..a428c91 100644 --- a/resources/android/BadgeRenderer.kt +++ b/resources/android/BadgeRenderer.kt @@ -1,7 +1,6 @@ package com.nativephp.plugins.native_ui.ui import androidx.compose.foundation.background -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.padding @@ -17,6 +16,7 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -32,7 +32,7 @@ object BadgeRenderer { val variant = p.getString("variant", "destructive") val a11yLabel = p.getString("a11y_label") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val (bg, fg) = when (variant) { "primary" -> theme.primary to theme.onPrimary diff --git a/resources/android/BareTextInputRenderer.kt b/resources/android/BareTextInputRenderer.kt index a52a7ef..8b73e38 100644 --- a/resources/android/BareTextInputRenderer.kt +++ b/resources/android/BareTextInputRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardActions @@ -21,6 +20,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.sp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.mobile.ui.nativerender.argbToComposeColor import com.nativephp.plugins.native_ui.NativeUITheme @@ -45,7 +45,7 @@ object BareTextInputRenderer { @Composable fun Render(node: NativeUINode, modifier: Modifier) { val props = parseTextInputProps(node) - val isDark = isSystemInDarkTheme() + val isDark = NativeAppearanceState.isDark() val theme = if (isDark) NativeUITheme.dark else NativeUITheme.light val customFontFamily = (if (props.fontName.isNotEmpty()) NativeUIFontResolver.resolve(LocalContext.current, props.fontName) else null) ?: nuiThemeDefaultFontFamily(LocalContext.current) diff --git a/resources/android/BottomSheetRenderer.kt b/resources/android/BottomSheetRenderer.kt index 18b733b..5f4e160 100644 --- a/resources/android/BottomSheetRenderer.kt +++ b/resources/android/BottomSheetRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.material3.BottomSheetDefaults @@ -13,6 +12,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.mobile.ui.nativerender.RenderNode @@ -51,7 +51,7 @@ object BottomSheetRenderer { if (!visible) return - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val skipPartial = !hasPartialDetent(detentsStr) val sheetState = rememberModalBottomSheetState( diff --git a/resources/android/ButtonGroupRenderer.kt b/resources/android/ButtonGroupRenderer.kt index c6651f6..ef57a75 100644 --- a/resources/android/ButtonGroupRenderer.kt +++ b/resources/android/ButtonGroupRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.SegmentedButton import androidx.compose.material3.SegmentedButtonDefaults import androidx.compose.material3.SingleChoiceSegmentedButtonRow @@ -14,6 +13,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -34,7 +34,7 @@ object ButtonGroupRenderer { if (options.isEmpty()) return - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light var selectedIndex by remember(node.id) { mutableStateOf(serverValue) } var lastSentValue by remember(node.id) { mutableStateOf(serverValue) } diff --git a/resources/android/ButtonRenderer.kt b/resources/android/ButtonRenderer.kt index c4123f1..5608e50 100644 --- a/resources/android/ButtonRenderer.kt +++ b/resources/android/ButtonRenderer.kt @@ -27,10 +27,10 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.MaterialIcon import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode -import androidx.compose.foundation.isSystemInDarkTheme import com.nativephp.plugins.native_ui.NativeUITheme import com.nativephp.plugins.native_ui.NativeUITokens @@ -70,7 +70,7 @@ object ButtonRenderer { // rather than a CompositionLocal because nothing in the render tree // currently provides one — the store is backed by `mutableStateOf`, so // Compose recomposes automatically when PHP pushes a theme update. - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val metrics = sizeMetrics(size, theme) // Leading — button labels are single-line, so this is usually a no-op. val lineHeight = nuiLineHeightUnit(p.getFloat("line_height_px", 0f), p.getFloat("line_height", 0f), metrics.textSize.value) diff --git a/resources/android/CheckboxRenderer.kt b/resources/android/CheckboxRenderer.kt index 45f0044..869e843 100644 --- a/resources/android/CheckboxRenderer.kt +++ b/resources/android/CheckboxRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.selection.toggleable @@ -17,6 +16,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -38,7 +38,7 @@ object CheckboxRenderer { val a11yLabel = p.getString("a11y_label") val a11yHint = p.getString("a11y_hint") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light var checked by remember(node.id) { mutableStateOf(serverValue) } var lastSentValue by remember(node.id) { mutableStateOf(serverValue) } diff --git a/resources/android/ChipRenderer.kt b/resources/android/ChipRenderer.kt index 679173e..e8f16dc 100644 --- a/resources/android/ChipRenderer.kt +++ b/resources/android/ChipRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChipDefaults @@ -13,6 +12,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.MaterialIcon import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode @@ -35,7 +35,7 @@ object ChipRenderer { val a11yLabel = p.getString("a11y_label") val a11yHint = p.getString("a11y_hint") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light var isSelected by remember(node.id) { mutableStateOf(serverValue) } var lastSentValue by remember(node.id) { mutableStateOf(serverValue) } diff --git a/resources/android/DatePickerRenderer.kt b/resources/android/DatePickerRenderer.kt index e8b0b5e..a4ac806 100644 --- a/resources/android/DatePickerRenderer.kt +++ b/resources/android/DatePickerRenderer.kt @@ -1,7 +1,6 @@ package com.nativephp.plugins.native_ui.ui import androidx.compose.foundation.clickable -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth @@ -28,6 +27,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.MaterialIcon import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode @@ -88,7 +88,7 @@ object DatePickerRenderer { val a11yLabel = p.getString("a11y_label") val a11yHint = p.getString("a11y_hint") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val zone = resolveZone(p.getString("timezone")) val locale = resolveLocale(p.getString("locale")) val is24 = resolve24Hour(hourFormat, locale) diff --git a/resources/android/FilledTextInputRenderer.kt b/resources/android/FilledTextInputRenderer.kt index 0231c9c..237f0fc 100644 --- a/resources/android/FilledTextInputRenderer.kt +++ b/resources/android/FilledTextInputRenderer.kt @@ -3,7 +3,6 @@ package com.nativephp.plugins.native_ui.ui import androidx.compose.foundation.interaction.FocusInteraction import androidx.compose.foundation.interaction.Interaction import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.foundation.text.KeyboardActions @@ -25,6 +24,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -42,7 +42,7 @@ object FilledTextInputRenderer { @Composable fun Render(node: NativeUINode, modifier: Modifier) { val props = parseTextInputProps(node) - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val scope = rememberCoroutineScope() // Local state owns text + caret (TextFieldValue). Initial caret sits at diff --git a/resources/android/IconRenderer.kt b/resources/android/IconRenderer.kt index d668014..46f0654 100644 --- a/resources/android/IconRenderer.kt +++ b/resources/android/IconRenderer.kt @@ -1,13 +1,13 @@ package com.nativephp.plugins.native_ui.ui import androidx.compose.foundation.clickable -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode @@ -19,7 +19,7 @@ object IconRenderer { val a11yLabel = p.getString("a11y_label") val lightArgb = p.getColor("color", 0xFF000000.toInt()) val darkArgb = p.getColor("dark_color", 0) - val isDark = isSystemInDarkTheme() + val isDark = NativeAppearanceState.isDark() val effectiveArgb = if (isDark && darkArgb != 0) darkArgb else lightArgb com.nativephp.mobile.ui.MaterialIcon( diff --git a/resources/android/ModalRenderer.kt b/resources/android/ModalRenderer.kt index d651223..2c44467 100644 --- a/resources/android/ModalRenderer.kt +++ b/resources/android/ModalRenderer.kt @@ -3,7 +3,6 @@ package com.nativephp.plugins.native_ui.ui import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -27,6 +26,7 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeElementBridge import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.mobile.ui.nativerender.NodeView @@ -49,7 +49,7 @@ object ModalRenderer { val a11yLabel = node.props.getString("a11y_label") val nodeId = node.id - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light var showModal by remember { mutableStateOf(false) } LaunchedEffect(visible) { showModal = visible } diff --git a/resources/android/NavRenderers.kt b/resources/android/NavRenderers.kt index 41c880b..5943b34 100644 --- a/resources/android/NavRenderers.kt +++ b/resources/android/NavRenderers.kt @@ -4,7 +4,7 @@ import android.content.Intent import android.net.Uri import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.isSystemInDarkTheme +import com.nativephp.mobile.ui.NativeAppearanceState import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.offset @@ -54,7 +54,7 @@ object TopBarRenderer { // Honor explicit text_color / background_color from NavBar builder; // fall back to system dark-theme heuristic only when nothing is set. - val isDark = isSystemInDarkTheme() + val isDark = NativeAppearanceState.isDark() val textArgb = props.getColor("text_color", 0) val textColor = if (textArgb != 0) Color(textArgb) else if (isDark) Color.White else Color.Black val bgArgb = props.getColor("background_color", 0) diff --git a/resources/android/OutlinedTextInputRenderer.kt b/resources/android/OutlinedTextInputRenderer.kt index 4013484..4fe2036 100644 --- a/resources/android/OutlinedTextInputRenderer.kt +++ b/resources/android/OutlinedTextInputRenderer.kt @@ -3,7 +3,6 @@ package com.nativephp.plugins.native_ui.ui import androidx.compose.foundation.interaction.FocusInteraction import androidx.compose.foundation.interaction.Interaction import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.foundation.text.KeyboardActions @@ -25,6 +24,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -41,7 +41,7 @@ object OutlinedTextInputRenderer { @Composable fun Render(node: NativeUINode, modifier: Modifier) { val props = parseTextInputProps(node) - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val scope = rememberCoroutineScope() // Echo-prevention sync (plan K). Local state owns what the user is diff --git a/resources/android/ProgressBarRenderer.kt b/resources/android/ProgressBarRenderer.kt index 75045c0..94f27fa 100644 --- a/resources/android/ProgressBarRenderer.kt +++ b/resources/android/ProgressBarRenderer.kt @@ -1,12 +1,12 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.LinearProgressIndicator import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -21,7 +21,7 @@ object ProgressBarRenderer { val indeterminate = p.getBool("indeterminate") val a11yLabel = p.getString("a11y_label") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val overrideArgb = p.getColor("color", 0) val trackOverride = p.getColor("track_color", 0) diff --git a/resources/android/RadioGroupRenderer.kt b/resources/android/RadioGroupRenderer.kt index d212879..97c49c5 100644 --- a/resources/android/RadioGroupRenderer.kt +++ b/resources/android/RadioGroupRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height @@ -13,6 +12,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.mobile.ui.nativerender.RenderNode @@ -35,7 +35,7 @@ object RadioGroupRenderer { val a11yLabel = p.getString("a11y_label") val a11yHint = p.getString("a11y_hint") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light var selectedValue by remember(node.id) { mutableStateOf(serverValue) } var lastSentValue by remember(node.id) { mutableStateOf(serverValue) } diff --git a/resources/android/RadioRenderer.kt b/resources/android/RadioRenderer.kt index d3decda..f168ccb 100644 --- a/resources/android/RadioRenderer.kt +++ b/resources/android/RadioRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -13,6 +12,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -44,7 +44,7 @@ object RadioRenderer { val disabled = groupDisabled || p.getBool("disabled") val isSelected = selectedValue == value - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val colors = RadioButtonDefaults.colors( selectedColor = theme.primary, diff --git a/resources/android/SelectRenderer.kt b/resources/android/SelectRenderer.kt index f428552..99b7072 100644 --- a/resources/android/SelectRenderer.kt +++ b/resources/android/SelectRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExposedDropdownMenuAnchorType @@ -17,6 +16,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextStyle +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -41,7 +41,7 @@ object SelectRenderer { val a11yLabel = p.getString("a11y_label") val a11yHint = p.getString("a11y_hint") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light var expanded by remember { mutableStateOf(false) } var selectedValue by remember(node.id) { mutableStateOf(serverValue) } diff --git a/resources/android/SheetPaneRenderer.kt b/resources/android/SheetPaneRenderer.kt index dc8766e..b83182a 100644 --- a/resources/android/SheetPaneRenderer.kt +++ b/resources/android/SheetPaneRenderer.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.draggable import androidx.compose.foundation.gestures.rememberDraggableState -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -23,6 +22,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.AlignItems import com.nativephp.mobile.ui.nativerender.FlexContainer import com.nativephp.mobile.ui.nativerender.FlexDirection @@ -54,7 +54,7 @@ object SheetPaneRenderer { @Composable fun Render(node: NativeUINode, modifier: Modifier) { val p = node.props - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val density = LocalDensity.current val detents = remember(p.getString("detents", "")) { diff --git a/resources/android/SliderRenderer.kt b/resources/android/SliderRenderer.kt index 5aa5740..c470bdd 100644 --- a/resources/android/SliderRenderer.kt +++ b/resources/android/SliderRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.Slider import androidx.compose.material3.SliderDefaults import androidx.compose.runtime.Composable @@ -12,6 +11,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -42,7 +42,7 @@ object SliderRenderer { val a11yLabel = p.getString("a11y_label") val a11yHint = p.getString("a11y_hint") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val scope = rememberCoroutineScope() var value by remember(node.id) { mutableFloatStateOf(serverValue) } diff --git a/resources/android/TabRowRenderer.kt b/resources/android/TabRowRenderer.kt index 3660f06..0b773a0 100644 --- a/resources/android/TabRowRenderer.kt +++ b/resources/android/TabRowRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Column import androidx.compose.material3.PrimaryTabRow import androidx.compose.material3.Tab @@ -15,6 +14,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.MaterialIcon import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode @@ -32,7 +32,7 @@ object TabRowRenderer { val onChangeCb = p.getCallbackId("on_change") val a11yLabel = p.getString("a11y_label") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light val tabs = node.children.filter { it.type == "tab" } if (tabs.isEmpty()) return diff --git a/resources/android/TextRenderer.kt b/resources/android/TextRenderer.kt index 97d03c6..5eb7b7e 100644 --- a/resources/android/TextRenderer.kt +++ b/resources/android/TextRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import android.content.Context @@ -23,6 +22,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.em import androidx.compose.ui.unit.sp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.mobile.ui.nativerender.argbToComposeColor @@ -57,7 +57,7 @@ object TextRenderer { val maxLines = p.getInt("max_lines") val textAlign = resolveTextAlign(p.getInt("text_align")) - val isDark = isSystemInDarkTheme() + val isDark = NativeAppearanceState.isDark() val darkColor = if (isDark) p.getColor("dark_color", 0) else 0 val textArgb = if (darkColor != 0) darkColor else p.getColor("color", 0xFF000000.toInt()) Text( @@ -94,7 +94,7 @@ object TextRenderer { @Composable private fun RenderComposed(node: NativeUINode, modifier: Modifier) { val p = node.props - val isDark = isSystemInDarkTheme() + val isDark = NativeAppearanceState.isDark() val maxLines = p.getInt("max_lines") // Leading applies to the whole string; base the multiplier on the // node's own font size (the root run's size). diff --git a/resources/android/ToggleRenderer.kt b/resources/android/ToggleRenderer.kt index b51f013..125e885 100644 --- a/resources/android/ToggleRenderer.kt +++ b/resources/android/ToggleRenderer.kt @@ -1,6 +1,5 @@ package com.nativephp.plugins.native_ui.ui -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.width @@ -18,6 +17,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp +import com.nativephp.mobile.ui.NativeAppearanceState import com.nativephp.mobile.ui.nativerender.NativeUIBridge import com.nativephp.mobile.ui.nativerender.NativeUINode import com.nativephp.plugins.native_ui.NativeUITheme @@ -40,7 +40,7 @@ object ToggleRenderer { val a11yLabel = p.getString("a11y_label") val a11yHint = p.getString("a11y_hint") - val theme = if (isSystemInDarkTheme()) NativeUITheme.dark else NativeUITheme.light + val theme = if (NativeAppearanceState.isDark()) NativeUITheme.dark else NativeUITheme.light var checked by remember(node.id) { mutableStateOf(serverValue) } var lastSentValue by remember(node.id) { mutableStateOf(serverValue) } diff --git a/tests/AndroidAppearanceTest.php b/tests/AndroidAppearanceTest.php new file mode 100644 index 0000000..8af7255 --- /dev/null +++ b/tests/AndroidAppearanceTest.php @@ -0,0 +1,17 @@ +not->toBeFalse()->not->toBeEmpty(); + + foreach ($renderers as $renderer) { + $source = file_get_contents($renderer); + + if (str_contains($source, 'NativeUITheme.dark')) { + expect($source) + ->not->toContain('isSystemInDarkTheme()') + ->toContain('NativeAppearanceState.isDark()'); + } + } +});