From 90cbd4cbbfc52a8c8b4a49c5bc4ce4fd7ace5a78 Mon Sep 17 00:00:00 2001 From: Walter Huf Date: Fri, 15 Mar 2024 15:40:24 -0700 Subject: [PATCH] Initial Bavaria Classic theme --- app/build.gradle.kts | 1 + .../io/bimmergestalt/headunit/MainActivity.kt | 34 ++--- .../headunit/ui/components/Gauge.kt | 1 - .../headunit/ui/components/TopBar.kt | 8 - .../bimmergestalt/headunit/ui/screens/Main.kt | 1 - .../headunit/ui/screens/RHMIScreen.kt | 1 + .../drawable/bavaria_home_drawer.xml | 36 +++++ .../drawable/bavaria_title_glow.xml | 38 +++++ .../drawable/bavaria_tray.xml | 49 ++++++ .../composeResources/values/strings.xml | 12 ++ .../headunit/apps/calendar/CalendarApp.kt | 1 + .../headunit/apps/calendar/CalendarAppDay.kt | 1 + .../headunit/models/ThemeSettings.kt | 2 +- .../headunit/screens/HeadunitScreen.kt | 2 + .../headunit/screens/HomeScreen.kt | 120 +++++++++++++++ .../io/bimmergestalt/headunit/screens/Main.kt | 27 ---- .../bimmergestalt/headunit/screens/Office.kt | 27 ++++ .../headunit/screens/SettingsScreen.kt | 26 ++-- .../headunit/ui/components/AppListEntry.kt | 6 +- .../headunit/ui/components/Background.kt | 61 ++++++++ .../headunit/ui/components/Calendar.kt | 2 +- .../headunit/ui/components/Checkbox.kt | 5 +- .../headunit/ui/components/TopBar.kt | 141 ++++++++++++++++++ .../headunit/ui/theme/Appearance.kt | 7 +- .../bimmergestalt/headunit/ui/theme/Color.kt | 9 ++ .../headunit/ui/theme/Metrics.kt | 17 +++ .../bimmergestalt/headunit/ui/theme/Theme.kt | 42 +++++- .../bimmergestalt/headunit/ui/theme/Type.kt | 18 ++- .../kotlin/io/bimmergestalt/headunit/main.kt | 45 ++---- build.gradle.kts | 6 + gradle/libs.versions.toml | 4 +- 31 files changed, 640 insertions(+), 110 deletions(-) delete mode 100644 app/src/androidMain/java/io/bimmergestalt/headunit/ui/components/TopBar.kt create mode 100644 app/src/commonMain/composeResources/drawable/bavaria_home_drawer.xml create mode 100644 app/src/commonMain/composeResources/drawable/bavaria_title_glow.xml create mode 100644 app/src/commonMain/composeResources/drawable/bavaria_tray.xml create mode 100644 app/src/commonMain/composeResources/values/strings.xml create mode 100644 app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/HomeScreen.kt delete mode 100644 app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/Main.kt create mode 100644 app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/Office.kt create mode 100644 app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Background.kt create mode 100644 app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/TopBar.kt create mode 100644 app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Metrics.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 96bcb6a..2215c7a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -57,6 +57,7 @@ kotlin { @OptIn(ExperimentalComposeLibrary::class) implementation(compose.components.resources) +// api(libs.moko.compose) implementation(libs.kotlinx.datetime) implementation(libs.voyager.navigator) implementation(libs.voyager.screenModel) diff --git a/app/src/androidMain/java/io/bimmergestalt/headunit/MainActivity.kt b/app/src/androidMain/java/io/bimmergestalt/headunit/MainActivity.kt index 30d0e58..911a1a0 100644 --- a/app/src/androidMain/java/io/bimmergestalt/headunit/MainActivity.kt +++ b/app/src/androidMain/java/io/bimmergestalt/headunit/MainActivity.kt @@ -9,6 +9,7 @@ import androidx.activity.compose.setContent import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding @@ -24,6 +25,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import cafe.adriel.voyager.navigator.Navigator @@ -32,8 +34,13 @@ import io.bimmergestalt.headunit.bcl.ServerService import io.bimmergestalt.headunit.models.RHMIAppsModel import io.bimmergestalt.headunit.models.ThemeSettings import io.bimmergestalt.headunit.screens.HeadunitScreen +import io.bimmergestalt.headunit.screens.HomeScreen +import io.bimmergestalt.headunit.ui.components.Background +import io.bimmergestalt.headunit.ui.components.StaticTopBar +import io.bimmergestalt.headunit.ui.components.TopBar import io.bimmergestalt.headunit.ui.screens.AppListScreen import io.bimmergestalt.headunit.ui.screens.RHMIScreen +import io.bimmergestalt.headunit.ui.theme.Appearance import io.bimmergestalt.headunit.ui.theme.HeadunitktAndroidTheme import io.bimmergestalt.headunit.ui.theme.Theme import io.bimmergestalt.headunit.utils.LaunchedEffectAndCollect @@ -74,30 +81,21 @@ fun Contents() { color = background ) { // Greeting("Android") - Navigator(AppListScreen) { navigator -> + val homeScreen = if (Theme.appearance == Appearance.Material) AppListScreen else HomeScreen + Navigator(homeScreen) { navigator -> + Background(navigator) SlideTransition(navigator) { screen -> - Scaffold(topBar = { - Row(verticalAlignment = Alignment.CenterVertically) { - if (screen != AppListScreen) { - IconButton(onClick = {navigator.pop()}) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) - } - } else { - IconButton(onClick = {}, enabled = false) { - Icon(Icons.Filled.Home, contentDescription = null) - } - } - if (screen is HeadunitScreen) { - Text(screen.title, modifier = Modifier.padding(6.dp, 6.dp), - color= Theme.colorScheme.onBackground, style = Theme.typography.titleMedium) - } + Scaffold(containerColor = Color.Transparent, topBar = { TopBar(navigator, screen) }) { padding -> + val appearancePadding = when(Theme.appearance) { + Appearance.Material -> padding + Appearance.Bavaria -> PaddingValues(start=100.dp, top = padding.calculateTopPadding()) } - }) { padding -> - Box(modifier = Modifier.padding(padding)) { + Box(modifier = Modifier.padding(appearancePadding)) { screen.Content() } } } + StaticTopBar(navigator = navigator) LaunchedEffectAndCollect(flow = RHMIAppsModel.incomingEvents) { incomingEvent -> Log.i("MainActivity", "Examining incomingEvent $incomingEvent") diff --git a/app/src/androidMain/java/io/bimmergestalt/headunit/ui/components/Gauge.kt b/app/src/androidMain/java/io/bimmergestalt/headunit/ui/components/Gauge.kt index 0087aff..dc4750f 100644 --- a/app/src/androidMain/java/io/bimmergestalt/headunit/ui/components/Gauge.kt +++ b/app/src/androidMain/java/io/bimmergestalt/headunit/ui/components/Gauge.kt @@ -3,7 +3,6 @@ package io.bimmergestalt.headunit.ui.components import androidx.compose.material3.Slider import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import io.bimmergestalt.headunit.models.RHMIAppInfo import io.bimmergestalt.idriveconnectkit.rhmi.RHMIModel @Composable diff --git a/app/src/androidMain/java/io/bimmergestalt/headunit/ui/components/TopBar.kt b/app/src/androidMain/java/io/bimmergestalt/headunit/ui/components/TopBar.kt deleted file mode 100644 index 1a3a91f..0000000 --- a/app/src/androidMain/java/io/bimmergestalt/headunit/ui/components/TopBar.kt +++ /dev/null @@ -1,8 +0,0 @@ -package io.bimmergestalt.headunit.ui.components - -import androidx.compose.runtime.Composable - -@Composable -fun TopBar() { - -} \ No newline at end of file diff --git a/app/src/androidMain/java/io/bimmergestalt/headunit/ui/screens/Main.kt b/app/src/androidMain/java/io/bimmergestalt/headunit/ui/screens/Main.kt index ab492ea..c876f42 100644 --- a/app/src/androidMain/java/io/bimmergestalt/headunit/ui/screens/Main.kt +++ b/app/src/androidMain/java/io/bimmergestalt/headunit/ui/screens/Main.kt @@ -20,7 +20,6 @@ import io.bimmergestalt.headunit.ui.components.AppList import io.bimmergestalt.headunit.ui.components.AppListEntry import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.imageResource -import org.jetbrains.compose.resources.painterResource object AppListScreen: Screen { diff --git a/app/src/androidMain/java/io/bimmergestalt/headunit/ui/screens/RHMIScreen.kt b/app/src/androidMain/java/io/bimmergestalt/headunit/ui/screens/RHMIScreen.kt index de9c942..3308e1a 100644 --- a/app/src/androidMain/java/io/bimmergestalt/headunit/ui/screens/RHMIScreen.kt +++ b/app/src/androidMain/java/io/bimmergestalt/headunit/ui/screens/RHMIScreen.kt @@ -27,6 +27,7 @@ class RHMIScreen(val app: RHMIAppInfo, val stateId: Int): HeadunitScreen { get() = "RHMIScreen(app=${app.appId}, stateId=$stateId)" override val title: String + @Composable get() { return if (state is RHMIState.CalendarMonthState) { val dateInt = state.getDateModel()?.asRaIntModel()?.value ?: 0 diff --git a/app/src/commonMain/composeResources/drawable/bavaria_home_drawer.xml b/app/src/commonMain/composeResources/drawable/bavaria_home_drawer.xml new file mode 100644 index 0000000..cfb89fc --- /dev/null +++ b/app/src/commonMain/composeResources/drawable/bavaria_home_drawer.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/commonMain/composeResources/drawable/bavaria_title_glow.xml b/app/src/commonMain/composeResources/drawable/bavaria_title_glow.xml new file mode 100644 index 0000000..284aa42 --- /dev/null +++ b/app/src/commonMain/composeResources/drawable/bavaria_title_glow.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/commonMain/composeResources/drawable/bavaria_tray.xml b/app/src/commonMain/composeResources/drawable/bavaria_tray.xml new file mode 100644 index 0000000..66c5e3b --- /dev/null +++ b/app/src/commonMain/composeResources/drawable/bavaria_tray.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/commonMain/composeResources/values/strings.xml b/app/src/commonMain/composeResources/values/strings.xml new file mode 100644 index 0000000..fdc69cf --- /dev/null +++ b/app/src/commonMain/composeResources/values/strings.xml @@ -0,0 +1,12 @@ + + Headunit + Main menu + Multimedia + Radio + Telephone + Navigation + Office + ConnectedDrive + Vehicle Information + Settings + \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/apps/calendar/CalendarApp.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/apps/calendar/CalendarApp.kt index 62e0613..842a3bf 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/apps/calendar/CalendarApp.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/apps/calendar/CalendarApp.kt @@ -50,6 +50,7 @@ object CalendarApp: HeadunitScreen { private var selectedDate by mutableStateOf(Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date) override val title: String + @Composable get() = LocalDate.Format { monthName(MonthNames.ENGLISH_FULL) chars(", ") diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/apps/calendar/CalendarAppDay.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/apps/calendar/CalendarAppDay.kt index af24aeb..dd60e03 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/apps/calendar/CalendarAppDay.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/apps/calendar/CalendarAppDay.kt @@ -10,6 +10,7 @@ import kotlinx.datetime.format.Padding class CalendarAppDay(val date: LocalDate, val events: List): HeadunitScreen { override val title: String + @Composable get() = LocalDate.Format { monthName(MonthNames.ENGLISH_FULL) chars(" ") diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/models/ThemeSettings.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/models/ThemeSettings.kt index b9dbfae..a7e455a 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/models/ThemeSettings.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/models/ThemeSettings.kt @@ -19,7 +19,7 @@ object ThemeSettings { ColorTheme.Leaves, ) - var appearance by mutableStateOf(Appearance.Material) + var appearance by mutableStateOf(Appearance.Bavaria) val availableAppearances = listOf( Appearance.Material, Appearance.Bavaria, diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/HeadunitScreen.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/HeadunitScreen.kt index 9f958d4..725fa66 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/HeadunitScreen.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/HeadunitScreen.kt @@ -1,7 +1,9 @@ package io.bimmergestalt.headunit.screens +import androidx.compose.runtime.Composable import cafe.adriel.voyager.core.screen.Screen interface HeadunitScreen: Screen { + @get:Composable val title: String } \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/HomeScreen.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/HomeScreen.kt new file mode 100644 index 0000000..6e9b596 --- /dev/null +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/HomeScreen.kt @@ -0,0 +1,120 @@ +@file:OptIn(ExperimentalResourceApi::class) + +package io.bimmergestalt.headunit.screens + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredWidth +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Button +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.paint +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.TileMode +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import headunit_kt.app.generated.resources.Res +import headunit_kt.app.generated.resources.* +import io.bimmergestalt.headunit.apps.calendar.CalendarApp +import io.bimmergestalt.headunit.models.ImageTintable +import io.bimmergestalt.headunit.ui.components.AppListEntry +import io.bimmergestalt.headunit.ui.theme.Appearance +import io.bimmergestalt.headunit.ui.theme.Theme +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.imageResource +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.resources.stringResource + +@OptIn(ExperimentalResourceApi::class) +object HomeScreen: HeadunitScreen { + + override val title: String + @Composable get() = stringResource(Res.string.lbl_main_menu) + + @Composable + override fun Content() { + when (Theme.appearance) { + Appearance.Material -> HomeScreenMaterial() + Appearance.Bavaria -> HomeScreenBavaria() + } + } +} + +@Composable +fun HomeScreenMaterial() { + val navigator = LocalNavigator.currentOrThrow + Column { + Text("It works!", color = Theme.colorScheme.onBackground) + + val navigator = LocalNavigator.currentOrThrow + + Column(modifier = Modifier + .padding(10.dp) + .verticalScroll(rememberScrollState())) { + + val settingsIcon = ImageTintable(imageResource(resource = Res.drawable.ic_carinfo), true) + AppListEntry(icon = settingsIcon, name = "Settings") { + navigator.push(SettingsScreen) + } + } + Button(onClick = {navigator.push(CalendarApp)}) { + Text("Calendar", color = Theme.colorScheme.onPrimaryContainer) + } + Button(onClick = {navigator.push(SettingsScreen)}) { + Text("Settings", color = Theme.colorScheme.onPrimaryContainer) + } + } +} + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun HomeScreenBavaria() { + val entries = listOf( + stringResource(Res.string.lbl_main_multimedia) to null, + stringResource(Res.string.lbl_main_radio) to null, + stringResource(Res.string.lbl_main_telephone) to null, + stringResource(Res.string.lbl_main_navigation) to null, + stringResource(Res.string.lbl_main_office) to OfficeScreen, + stringResource(Res.string.lbl_main_connecteddrive) to null, + stringResource(Res.string.lbl_main_vehicle_information) to null, + stringResource(Res.string.lbl_main_settings) to SettingsScreen, + ) + val navigator = LocalNavigator.currentOrThrow + val lineGradient = Brush.horizontalGradient( + 0f to Color(50, 50, 50), + 0.05f to Color(128, 128, 128), + 0.8f to Color(128, 128, 128), + 1f to Color(20, 20, 20), +// endX = 10f, tileMode = TileMode.Repeated + ) + Box { + Column(modifier=Modifier.width(IntrinsicSize.Min)) { + entries.forEach { (name, screen) -> + val modifier = if (screen == null) Modifier else + Modifier.clickable { navigator.push(screen) } + Column(modifier = modifier.padding(vertical=Theme.metrics.list_row_padding)) { // big clickable box + Text(name, modifier = Modifier.requiredWidth(IntrinsicSize.Max), softWrap = false, + color=Theme.colorScheme.onBackground, style = Theme.typography.labelLarge) + Box(modifier = Modifier.background(lineGradient).height(1.dp).fillMaxWidth()) + + } + } + } + } +} \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/Main.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/Main.kt deleted file mode 100644 index 058a766..0000000 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/Main.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.bimmergestalt.headunit.screens - -import androidx.compose.foundation.layout.Column -import androidx.compose.material3.Button -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import cafe.adriel.voyager.core.screen.Screen -import cafe.adriel.voyager.navigator.LocalNavigator -import cafe.adriel.voyager.navigator.currentOrThrow -import io.bimmergestalt.headunit.apps.calendar.CalendarApp -import io.bimmergestalt.headunit.ui.theme.Theme - -object MainScreen: Screen { - @Composable - override fun Content() { - val navigator = LocalNavigator.currentOrThrow - Column { - Text("It works!", color = Theme.colorScheme.onBackground) - Button(onClick = {navigator.push(CalendarApp)}) { - Text("Calendar", color = Theme.colorScheme.onPrimaryContainer) - } - Button(onClick = {navigator.push(SettingsScreen)}) { - Text("Settings", color = Theme.colorScheme.onPrimaryContainer) - } - } - } -} \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/Office.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/Office.kt new file mode 100644 index 0000000..d2fc2ac --- /dev/null +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/Office.kt @@ -0,0 +1,27 @@ +package io.bimmergestalt.headunit.screens + +import androidx.compose.runtime.Composable +import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.currentOrThrow +import headunit_kt.app.generated.resources.Res +import headunit_kt.app.generated.resources.lbl_main_office +import io.bimmergestalt.headunit.apps.calendar.CalendarApp +import io.bimmergestalt.headunit.ui.components.AppListEntry +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.stringResource + +object OfficeScreen: HeadunitScreen { + @OptIn(ExperimentalResourceApi::class) + override val title: String + @Composable + get() = stringResource(Res.string.lbl_main_office) + + @Composable + override fun Content() { + val navigator = LocalNavigator.currentOrThrow + AppListEntry(icon = null, name = "Calendar") { + navigator.push(CalendarApp) + } + } + +} \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/SettingsScreen.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/SettingsScreen.kt index 20bd7e6..62952ac 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/SettingsScreen.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/screens/SettingsScreen.kt @@ -1,5 +1,6 @@ package io.bimmergestalt.headunit.screens +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Column @@ -12,50 +13,57 @@ import io.bimmergestalt.headunit.models.ThemeSettings import io.bimmergestalt.headunit.ui.components.LabelledCheckbox import io.bimmergestalt.headunit.ui.components.LabelledRadioButton import io.bimmergestalt.headunit.ui.components.SectionHeader +import io.bimmergestalt.headunit.ui.theme.Appearance import io.bimmergestalt.headunit.ui.theme.Theme object SettingsScreen: HeadunitScreen { override val title: String + @Composable get() = "Settings" @Composable override fun Content() { val color by animateColorAsState( - targetValue = Theme.colorScheme.primary, - label="Primary color") + targetValue = Theme.colorScheme.onBackground, + label="Text color") + val themeViewModel = ThemeSettings Column { - ColorSettings(color=color) - HorizontalDivider(color=color) + AnimatedVisibility( true || themeViewModel.appearance == Appearance.Material) { + Column { + ColorSettings(color = color) + HorizontalDivider(color = color) + } + } AppearanceSettings(color=color) } } @Composable - fun ColorSettings(color: Color = Theme.colorScheme.primary) { + fun ColorSettings(color: Color = Theme.colorScheme.onBackground) { val themeViewModel = ThemeSettings LabelledCheckbox( state = themeViewModel.darkMode ?: isSystemInDarkTheme(), onCheckedChange = { themeViewModel.darkMode = it } ) { - Text("Dark mode", color = color) + Text("Dark mode", color = color, style = Theme.typography.labelLarge) } themeViewModel.availableThemes.forEach { LabelledRadioButton(state = themeViewModel.colorTheme == it, onClick = {themeViewModel.colorTheme = it}) { - Text(it.name, color = color) + Text(it.name, color = color, style = Theme.typography.labelLarge) } } } @Composable - fun AppearanceSettings(color: Color = Theme.colorScheme.primary) { + fun AppearanceSettings(color: Color = Theme.colorScheme.onBackground) { val themeViewModel = ThemeSettings SectionHeader("Appearance", color = color) themeViewModel.availableAppearances.forEach { LabelledRadioButton(state = themeViewModel.appearance == it, onClick = {themeViewModel.appearance = it}) { - Text(it.name, color = color) + Text(it.name, color = color, style = Theme.typography.labelLarge) } } } diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/AppListEntry.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/AppListEntry.kt index 37d292f..71a5f75 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/AppListEntry.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/AppListEntry.kt @@ -23,18 +23,18 @@ fun AppListEntry(icon: ImageTintable?, name: String, onClick: () -> Unit) { modifier = Modifier .clickable { onClick() } .fillMaxWidth() - .padding(vertical = 4.dp) + .padding(vertical = Theme.metrics.list_row_padding) ) { val iconSizeModifier = Modifier .padding(4.dp) .size(32.dp) if (icon != null) { Image(icon.image, null, modifier = iconSizeModifier, - colorFilter = if (icon.tintable) tintFilter(Theme.colorScheme.primary, !isSystemInDarkTheme()) else null) + colorFilter = if (icon.tintable) tintFilter(Theme.colorScheme.onBackground, !isSystemInDarkTheme()) else null) } else { Box(modifier = iconSizeModifier) } - Text(name, style = Theme.typography.headlineSmall, color= Theme.colorScheme.primary) + Text(name, style = Theme.typography.headlineSmall, color= Theme.colorScheme.onBackground) } } \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Background.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Background.kt new file mode 100644 index 0000000..7212ab7 --- /dev/null +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Background.kt @@ -0,0 +1,61 @@ +package io.bimmergestalt.headunit.ui.components + +import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredHeight +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Home +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.navigator.Navigator +import headunit_kt.app.generated.resources.Res +import headunit_kt.app.generated.resources.bavaria_home_drawer +import headunit_kt.app.generated.resources.bavaria_title_glow +import headunit_kt.app.generated.resources.bavaria_tray +import io.bimmergestalt.headunit.screens.HeadunitScreen +import io.bimmergestalt.headunit.ui.theme.Appearance +import io.bimmergestalt.headunit.ui.theme.Theme +import kotlinx.datetime.Clock +import kotlinx.datetime.LocalTime +import kotlinx.datetime.TimeZone +import kotlinx.datetime.format.Padding +import kotlinx.datetime.format.char +import kotlinx.datetime.toLocalDateTime +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource + +@Composable +fun Background(navigator: Navigator) { + when (Theme.appearance) { + Appearance.Material -> BackgroundMaterial(navigator) + Appearance.Bavaria -> BackgroundBavaria(navigator) + } +} + +@Composable +fun BackgroundMaterial(navigator: Navigator) { } + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun BackgroundBavaria(navigator: Navigator) { + Box { + Image( + painterResource(Res.drawable.bavaria_home_drawer), null, + alignment = Alignment.TopStart, + modifier = Modifier.requiredHeight(400.dp) + ) + } +} diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Calendar.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Calendar.kt index 15f8bc6..cc1efb3 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Calendar.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Calendar.kt @@ -146,7 +146,7 @@ fun CalendarDayView(modifier: Modifier = Modifier, events: List, @Composable fun Preview() { - HeadunitktTheme(colorTheme = ColorTheme.Lagoon, + HeadunitktTheme(materialColorTheme = ColorTheme.Lagoon, darkTheme = isSystemInDarkTheme()) { Surface { // CalendarMonth( diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Checkbox.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Checkbox.kt index cd06ae1..3313210 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Checkbox.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/Checkbox.kt @@ -9,6 +9,7 @@ import androidx.compose.material3.RadioButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import io.bimmergestalt.headunit.ui.theme.Theme @Composable fun LabelledCheckbox( @@ -17,7 +18,7 @@ fun LabelledCheckbox( modifier: Modifier = Modifier.fillMaxWidth(), label: @Composable RowScope.() -> Unit) { Row(modifier = modifier.clickable { onCheckedChange(!state) }, verticalAlignment = Alignment.CenterVertically) { - Checkbox(checked=state, onCheckedChange = onCheckedChange) + Checkbox(checked=state, onCheckedChange = onCheckedChange, colors = Theme.checkboxColors) label() } } @@ -29,7 +30,7 @@ fun LabelledRadioButton( modifier: Modifier = Modifier.fillMaxWidth(), label: @Composable RowScope.() -> Unit) { Row(modifier = modifier.clickable { onClick() }, verticalAlignment = Alignment.CenterVertically) { - RadioButton(selected = state, onClick = onClick) + RadioButton(selected = state, onClick = onClick, colors = Theme.radioButtonColors) label() } } \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/TopBar.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/TopBar.kt new file mode 100644 index 0000000..b83449b --- /dev/null +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/components/TopBar.kt @@ -0,0 +1,141 @@ +package io.bimmergestalt.headunit.ui.components + +import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Home +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.Navigator +import headunit_kt.app.generated.resources.Res +import headunit_kt.app.generated.resources.bavaria_home_drawer +import headunit_kt.app.generated.resources.bavaria_title_glow +import headunit_kt.app.generated.resources.bavaria_tray +import io.bimmergestalt.headunit.screens.HeadunitScreen +import io.bimmergestalt.headunit.screens.HomeScreenBavaria +import io.bimmergestalt.headunit.screens.HomeScreenMaterial +import io.bimmergestalt.headunit.ui.theme.Appearance +import io.bimmergestalt.headunit.ui.theme.Theme +import kotlinx.datetime.Clock +import kotlinx.datetime.LocalDate +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.LocalTime +import kotlinx.datetime.TimeZone +import kotlinx.datetime.format.Padding +import kotlinx.datetime.format.char +import kotlinx.datetime.toLocalDateTime +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.painterResource + +@Composable +fun TopBar(navigator: Navigator, screen: Screen) { + when (Theme.appearance) { + Appearance.Material -> DefaultTopBar(navigator, screen) + Appearance.Bavaria -> BavariaTopBar(navigator, screen) + } +} + +@Composable +fun DefaultTopBar(navigator: Navigator, screen: Screen) { + Row(verticalAlignment = Alignment.CenterVertically) { + if (navigator.canPop) { + IconButton(onClick = {navigator.pop()}) { + Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) + } + } else { + IconButton(onClick = {}, enabled = false) { + Icon(Icons.Filled.Home, contentDescription = null) + } + } + if (screen is HeadunitScreen) { + Text(screen.title, modifier = Modifier.padding(6.dp, 6.dp), + color= Theme.colorScheme.onBackground, style = Theme.typography.titleMedium) + } + } +} + +@Composable +fun BavariaTopBar(navigator: Navigator, screen: Screen) { + // drawn in Background + Box(modifier = Modifier.height(48.dp)) +} + +@Composable +fun StaticTopBar(navigator: Navigator) { + when (Theme.appearance) { + Appearance.Material -> {} + Appearance.Bavaria -> BavariaStaticTopBar(navigator) + } +} + +@OptIn(ExperimentalResourceApi::class) +@Composable +fun BavariaStaticTopBar(navigator: Navigator) { + val screen = navigator.lastItem + + Box { + + Row(verticalAlignment = Alignment.CenterVertically) { + AnimatedContent(targetState = navigator.canPop) { canPop -> + if (canPop) { + IconButton(onClick = {navigator.pop()}) { + Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) + } + } else { + IconButton(onClick = {}, enabled = false) { + Icon(Icons.Filled.Home, contentDescription = null) + } + } + } + + if (screen is HeadunitScreen) { + Box { + Image( + painterResource(Res.drawable.bavaria_title_glow), null, + modifier = Modifier.height(32.dp), + contentScale = ContentScale.FillHeight + ) + AnimatedContent(screen.title) { title -> + Text(title, modifier = Modifier.padding(start=12.dp, top=4.dp, end=50.dp, bottom=6.dp), + softWrap = false, + color = Theme.colorScheme.onBackground, style = Theme.typography.titleMedium) + } + } + } + Spacer(Modifier.weight(1f)) + Box { + Image( + painterResource(Res.drawable.bavaria_tray), null, + modifier = Modifier.height(32.dp), + contentScale = ContentScale.FillHeight + ) + val now = Clock.System.now() + val localNow = now.toLocalDateTime(TimeZone.currentSystemDefault()).time + val timeFormatted = LocalTime.Format { + hour(Padding.ZERO) + char(':') + minute(Padding.ZERO) + }.format(localNow) + Text(timeFormatted, modifier = Modifier.padding(start=32.dp, top=4.dp, end=50.dp, bottom=6.dp), + softWrap = false, + color = Theme.colorScheme.onBackground, style = Theme.typography.titleMedium) + } + } + } +} \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Appearance.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Appearance.kt index 1181415..d78ae9a 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Appearance.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Appearance.kt @@ -1,10 +1,11 @@ package io.bimmergestalt.headunit.ui.theme +import androidx.compose.material3.ColorScheme import androidx.compose.runtime.staticCompositionLocalOf -enum class Appearance() { - Material, - Bavaria, +enum class Appearance(val colorScheme: ColorScheme?, val metrics: Metrics) { + Material(null, MaterialMetrics), + Bavaria(ColorTheme.Bavaria, BavariaMetrics), } diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Color.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Color.kt index 662d547..c3d01ed 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Color.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Color.kt @@ -30,32 +30,41 @@ data class ColorTheme(val name: String, val light: ColorScheme, val dark: ColorS companion object { val Dynamic = ColorTheme("Dynamic", lightColorScheme(), darkColorScheme()) val Pink = ColorTheme("Pink", lightColorScheme( + onBackground = Purple40, primary = Purple40, secondary = PurpleGrey40, tertiary = Pink40, ), darkColorScheme( + onBackground = Purple80, primary = Purple80, secondary = PurpleGrey80, tertiary = Pink80, )) val Lagoon = ColorTheme("Lagoon", lightColorScheme( + onBackground = MidnightBlue, primary = MidnightBlue, secondary = DarkBlue, tertiary = Blue, ), darkColorScheme( + onBackground = Blue, primary = Blue, secondary = DarkBlue, tertiary = MidnightBlue, )) val Leaves = ColorTheme("Leaves", lightColorScheme( + onBackground = OliveGreen, primary = OliveGreen, secondary = Green, tertiary = LimeGreen, ), darkColorScheme( + onBackground = LimeGreen, primary = LimeGreen, secondary = YellowGreen, tertiary = Green, )) + val Bavaria = darkColorScheme( + background = Color(0xFF111111), + ) } } diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Metrics.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Metrics.kt new file mode 100644 index 0000000..52472a5 --- /dev/null +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Metrics.kt @@ -0,0 +1,17 @@ +package io.bimmergestalt.headunit.ui.theme + +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +data class Metrics( + val list_row_padding: Dp +) { +} + +val MaterialMetrics = Metrics( + list_row_padding = 4.dp +) + +val BavariaMetrics = Metrics( + list_row_padding = 2.dp +) \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Theme.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Theme.kt index 0ec1a37..0b9df3d 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Theme.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Theme.kt @@ -1,32 +1,42 @@ package io.bimmergestalt.headunit.ui.theme import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.CheckboxColors +import androidx.compose.material3.CheckboxDefaults import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.RadioButtonColors +import androidx.compose.material3.RadioButtonDefaults import androidx.compose.material3.Shapes import androidx.compose.material3.Typography import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.graphics.Color import io.bimmergestalt.headunit.models.ThemeSettings @Composable fun HeadunitktTheme( darkTheme: Boolean = isSystemInDarkTheme(), - colorTheme: ColorTheme = ColorTheme.Lagoon, + materialColorTheme: ColorTheme = ColorTheme.Lagoon, content: @Composable () -> Unit ) { - val colorScheme = when { - darkTheme -> colorTheme.dark - else -> colorTheme.light + val materialColorScheme = when { + darkTheme -> materialColorTheme.dark + else -> materialColorTheme.light } val themeViewModel = ThemeSettings + val colorScheme = themeViewModel.appearance.colorScheme ?: materialColorScheme + CompositionLocalProvider( LocalAppearance provides themeViewModel.appearance ) { MaterialTheme( colorScheme = colorScheme, - typography = Typography, + typography = when(Theme.appearance) { + Appearance.Material -> MaterialTypography + Appearance.Bavaria -> BavariaTypography + }, content = content ) } @@ -42,4 +52,26 @@ object Theme { @Composable get() = MaterialTheme.shapes val appearance: Appearance @Composable get() = LocalAppearance.current + + val metrics: Metrics + @Composable + get() = appearance.metrics + val checkboxColors: CheckboxColors + @Composable + get() = when(appearance) { + Appearance.Material -> CheckboxDefaults.colors() + else -> CheckboxDefaults.colors( + checkmarkColor = colorScheme.onBackground, + checkedColor = Color.Transparent, + uncheckedColor = Color.Transparent, + ) + } + val radioButtonColors: RadioButtonColors + @Composable + get() = when(appearance) { + Appearance.Material -> RadioButtonDefaults.colors() + else -> RadioButtonDefaults.colors( + selectedColor = colorScheme.onBackground, + ) + } } \ No newline at end of file diff --git a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Type.kt b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Type.kt index fa8e96f..76ad8af 100644 --- a/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Type.kt +++ b/app/src/commonMain/kotlin/io/bimmergestalt/headunit/ui/theme/Type.kt @@ -1,5 +1,6 @@ package io.bimmergestalt.headunit.ui.theme +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily @@ -7,7 +8,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp // Set of Material typography styles to start with -val Typography = Typography( +val MaterialTypography = Typography( bodyLarge = TextStyle( fontFamily = FontFamily.Default, fontWeight = FontWeight.Normal, @@ -31,4 +32,19 @@ val Typography = Typography( letterSpacing = 0.5.sp ) */ +) + +val BavariaTypography = Typography( + titleMedium = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + lineHeight = 32.sp, + fontSize = 24.sp + ), + labelLarge = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + lineHeight = 32.sp, + fontSize = 28.sp + ), ) \ No newline at end of file diff --git a/app/src/wasmJsMain/kotlin/io/bimmergestalt/headunit/main.kt b/app/src/wasmJsMain/kotlin/io/bimmergestalt/headunit/main.kt index 761d712..c18ed66 100644 --- a/app/src/wasmJsMain/kotlin/io/bimmergestalt/headunit/main.kt +++ b/app/src/wasmJsMain/kotlin/io/bimmergestalt/headunit/main.kt @@ -1,29 +1,26 @@ package io.bimmergestalt.headunit import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.Home -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.window.CanvasBasedWindow import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.transitions.SlideTransition import io.bimmergestalt.headunit.models.ThemeSettings -import io.bimmergestalt.headunit.screens.MainScreen -import io.bimmergestalt.headunit.screens.HeadunitScreen +import io.bimmergestalt.headunit.screens.HomeScreen +import io.bimmergestalt.headunit.ui.components.Background +import io.bimmergestalt.headunit.ui.components.StaticTopBar +import io.bimmergestalt.headunit.ui.components.TopBar +import io.bimmergestalt.headunit.ui.theme.Appearance import io.bimmergestalt.headunit.ui.theme.HeadunitktTheme import io.bimmergestalt.headunit.ui.theme.Theme @@ -37,37 +34,27 @@ fun main() { @Composable fun Contents() { val themeViewModel = ThemeSettings - HeadunitktTheme(colorTheme = themeViewModel.colorTheme, + HeadunitktTheme(materialColorTheme = themeViewModel.colorTheme, darkTheme = themeViewModel.darkMode) { val background by animateColorAsState( targetValue = Theme.colorScheme.background, label="Background color") Surface(modifier = Modifier.fillMaxSize(), color = background) { - Navigator(MainScreen) { navigator -> + Navigator(HomeScreen) { navigator -> + Background(navigator) SlideTransition(navigator) { screen -> - Scaffold(topBar = { - Row(verticalAlignment = Alignment.CenterVertically) { - if (navigator.canPop) { - IconButton(onClick = {navigator.pop()}) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) - } - } else { - IconButton(onClick = {}, enabled = false) { - Icon(Icons.Filled.Home, contentDescription = null) - } - } - if (screen is HeadunitScreen) { - Text(screen.title, modifier = Modifier.padding(6.dp, 6.dp), - color=Theme.colorScheme.onBackground, style = Theme.typography.titleMedium) - } + Scaffold(containerColor = Color.Transparent, topBar = { TopBar(navigator, screen) }) { padding -> + val appearancePadding = when(Theme.appearance) { + Appearance.Material -> padding + Appearance.Bavaria -> PaddingValues(start=100.dp, top = padding.calculateTopPadding()) } - }) { padding -> - Box(modifier = Modifier.padding(padding).padding(8.dp)) { + Box(modifier = Modifier.padding(appearancePadding).padding(8.dp)) { screen.Content() } } } + StaticTopBar(navigator = navigator) } } } diff --git a/build.gradle.kts b/build.gradle.kts index a7ae0de..1e37db1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,4 +4,10 @@ plugins { alias(libs.plugins.androidLibrary).apply(false) alias(libs.plugins.kotlinAndroid).apply(false) alias(libs.plugins.kotlinMultiplatform).apply(false) +} + +buildscript { + dependencies { + classpath(libs.moko.generator) + } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9749182..ad71771 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,6 +9,7 @@ androidx-activityCompose = "1.8.2" androidx-navigationCompose = "2.7.7" navigationRuntimeKtx = "2.7.7" org-jetbrains-kotlin-jvm = "1.9.20" +moko = "0.23.0" voyager = "1.1.0-alpha03" [libraries] @@ -27,8 +28,9 @@ compose-material3-android = { module = "androidx.compose.material3:material3-and kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version = "0.6.0-RC.2" } cache4k = { module = "io.github.reactivecircus.cache4k:cache4k", version="0.13.0" } +moko-compose = { module = "dev.icerock.moko:resources-compose", version.ref = "moko"} +moko-generator = { module = "dev.icerock.moko:resources-generator", version.ref = "moko"} pngj = { module = "ar.com.hjg:pngj", version = "2.1.0" } -androidx-navigation-runtime-ktx = { group = "androidx.navigation", name = "navigation-runtime-ktx", version.ref = "navigationRuntimeKtx" } voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" } voyager-screenModel = { module = "cafe.adriel.voyager:voyager-screenmodel", version.ref = "voyager" } voyager-tabNavigator = { module = "cafe.adriel.voyager:voyager-tab-navigator", version.ref = "voyager" }