From c213f5d507bbc3e31699787b0a3f1e0913c8adf7 Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Thu, 11 Jan 2024 23:12:46 +0800 Subject: [PATCH] feat: update demo --- samples/shared/src/commonMain/kotlin/App.kt | 167 ++++++++++++++---- .../src/commonMain/kotlin/Components.kt | 50 ++++++ .../src/commonMain/kotlin/Preferences.kt | 145 +++++++++++++++ 3 files changed, 327 insertions(+), 35 deletions(-) create mode 100644 samples/shared/src/commonMain/kotlin/Components.kt create mode 100644 samples/shared/src/commonMain/kotlin/Preferences.kt diff --git a/samples/shared/src/commonMain/kotlin/App.kt b/samples/shared/src/commonMain/kotlin/App.kt index 9fff8d2..3a2f021 100644 --- a/samples/shared/src/commonMain/kotlin/App.kt +++ b/samples/shared/src/commonMain/kotlin/App.kt @@ -21,18 +21,20 @@ */ @file:OptIn(ExperimentalFoundationApi::class) +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -41,34 +43,79 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.em +import com.highcapable.betterandroid.compose.extension.ui.ComponentPadding +import com.highcapable.betterandroid.compose.multiplatform.backpress.BackHandler +import com.highcapable.betterandroid.compose.multiplatform.systembar.PlatformSystemBarStyle +import com.highcapable.betterandroid.compose.multiplatform.systembar.rememberSystemBarsController +import com.highcapable.betterandroid.compose.multiplatform.systembar.setStyle import com.highcapable.flexiui.FlexiTheme import com.highcapable.flexiui.component.AreaBox import com.highcapable.flexiui.component.AreaColumn +import com.highcapable.flexiui.component.Button +import com.highcapable.flexiui.component.DropdownList +import com.highcapable.flexiui.component.DropdownMenuItem +import com.highcapable.flexiui.component.HorizontalItemBox import com.highcapable.flexiui.component.Icon import com.highcapable.flexiui.component.IconDefaults import com.highcapable.flexiui.component.NavigationBarItem import com.highcapable.flexiui.component.NavigationBarRow import com.highcapable.flexiui.component.PrimaryAppBar import com.highcapable.flexiui.component.Scaffold +import com.highcapable.flexiui.component.SecondaryAppBar +import com.highcapable.flexiui.component.Surface import com.highcapable.flexiui.component.SwitchItem import com.highcapable.flexiui.component.Text import com.highcapable.flexiui.resources.FlexiIcons import kotlinx.coroutines.launch -@Stable -data class AppPreferences( - var darkMode: MutableState = mutableStateOf(false), - var followSystemDarkMode: MutableState = mutableStateOf(false) -) +private const val PROJECT_URL = "https://github.com/BetterAndroid/FlexiUI" +@Composable +private fun FlexiDemoTheme(content: @Composable () -> Unit) { + val systemBars = rememberSystemBarsController() + val darkMode by remember { Preferences.darkMode } + val followSystemDarkMode by remember { Preferences.followSystemDarkMode } + val currentDarkMode = if (followSystemDarkMode) isSystemInDarkTheme() else darkMode + val colorScheme by remember { Preferences.colorScheme } + systemBars.setStyle( + if (currentDarkMode) + PlatformSystemBarStyle.DarkTransparent + else PlatformSystemBarStyle.LightTransparent + ) + FlexiTheme( + colors = colorScheme.toColors(currentDarkMode), + content = content + ) +} + +/** Simulate a router. */ @Stable -private val Preferences = AppPreferences() +private var CurrentPage = mutableStateOf(0) + +@Composable +private fun rememberCurrentPage() = remember { CurrentPage } + +@Composable +private fun Page(page: Int, content: @Composable () -> Unit) { + val currentPage by remember { CurrentPage } + AnimatedVisibility( + visible = currentPage == page, + enter = fadeIn(), + exit = fadeOut() + ) { content() } +} @Composable fun App() { - FlexiTheme { - MainScreen() + FlexiDemoTheme { + // Surface will keep the content background color when animation. + Surface(padding = ComponentPadding()) { + Page(0) { MainScreen() } + Page(1) { SecondaryScreen() } + } } } @@ -77,13 +124,14 @@ fun MainScreen() { val pageCount = 2 val state = rememberPagerState(pageCount = { pageCount }) val scope = rememberCoroutineScope() + val uriHandler = LocalUriHandler.current Scaffold( appBar = { PrimaryAppBar( title = { Text("Flexi UI Demo") }, actions = { ActionIconButton( - onClick = { /* TODO */ } + onClick = { uriHandler.openUri(PROJECT_URL) } ) { Icon(FlexiIcons.GitHub) } } ) @@ -127,24 +175,61 @@ fun MainHomePage() { } PrimarySpacer() AreaColumn(modifier = Modifier.fillMaxWidth()) { + var colorScheme by remember { Preferences.colorScheme } var darkMode by remember { Preferences.darkMode } var followSystemDarkMode by remember { Preferences.followSystemDarkMode } SecondaryText("Theme Style") PrimarySpacer() - SwitchItem( - checked = darkMode, - onCheckedChange = { darkMode = it } - ) { Text("Enable night mode") } - SecondarySpacer() - SecondaryText("Manually switch the current theme to night mode.") - PrimarySpacer() + AnimatedVisibility(visible = !followSystemDarkMode) { + Column { + SwitchItem( + checked = darkMode, + onCheckedChange = { darkMode = it } + ) { Text("Enable night mode") } + SecondarySpacer() + SecondaryText("Manually switch the current theme to night mode.") + PrimarySpacer() + } + } SwitchItem( checked = followSystemDarkMode, onCheckedChange = { followSystemDarkMode = it } ) { Text("Follow system night mode") } SecondarySpacer() SecondaryText("Follow the system theme to switch day and night mode.") + PrimarySpacer() + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + var expanded by remember { mutableStateOf(false) } + Text("Current Theme") + PrimarySpacer() + DropdownList( + modifier = Modifier.fillMaxWidth(), + expanded = expanded, + onExpandedChange = { expanded = it }, + text = { Text(colorScheme.toName()) }, + ) { + colorSchemes().forEach { + DropdownMenuItem( + actived = colorScheme == it, + onClick = { + expanded = false + colorScheme = it + } + ) { Text(it.toName()) } + } + } + } } + PrimarySpacer() + var currentPage by rememberCurrentPage() + HorizontalItemBox( + onClick = { currentPage = 1 }, + title = { Text("Single Page Demo") }, + subtitle = { Text("Open a single page.") } + ) } } @@ -158,20 +243,32 @@ fun MainComponentPage() { } @Composable -private fun PrimarySpacer() { - Spacer(modifier = Modifier.height(10.dp)) -} - -@Composable -private fun SecondarySpacer() { - Spacer(modifier = Modifier.height(5.dp)) -} - -@Composable -private fun SecondaryText(text: String) { - Text( - text = text, - color = FlexiTheme.colors.textSecondary, - style = FlexiTheme.typography.secondary - ) +fun SecondaryScreen() { + var currentPage by rememberCurrentPage() + Scaffold( + appBar = { + SecondaryAppBar( + title = { Text("Single Page") }, + navigationIcon = { + NavigationIconButton(onClick = { currentPage = 0 }) + } + ) + } + ) { + AreaColumn(modifier = Modifier.fillMaxWidth()) { + Text( + """ + Now, you open a separate secondary page. + You can click the button below to back to the homepage. + """.trimIndent(), + style = FlexiTheme.typography.primary.copy(lineHeight = 2.em) + ) + PrimarySpacer() + Button( + modifier = Modifier.fillMaxWidth(), + onClick = { currentPage = 0 } + ) { Text("Take Me Home") } + } + BackHandler { currentPage = 0 } + } } \ No newline at end of file diff --git a/samples/shared/src/commonMain/kotlin/Components.kt b/samples/shared/src/commonMain/kotlin/Components.kt new file mode 100644 index 0000000..bc003a2 --- /dev/null +++ b/samples/shared/src/commonMain/kotlin/Components.kt @@ -0,0 +1,50 @@ +/* + * Flexi UI - A flexible and useful UI component library. + * Copyright (C) 2019-2024 HighCapable + * https://github.com/BetterAndroid/FlexiUI + * + * Apache License Version 2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is created by fankes on 2024/1/11. + */ + +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.highcapable.flexiui.FlexiTheme +import com.highcapable.flexiui.component.Text + +// TODO: Some components can be include to Flexi UI (To be determined) + +@Composable +fun PrimarySpacer() { + Spacer(modifier = Modifier.size(10.dp)) +} + +@Composable +fun SecondarySpacer() { + Spacer(modifier = Modifier.size(5.dp)) +} + +@Composable +fun SecondaryText(text: String) { + Text( + text = text, + color = FlexiTheme.colors.textSecondary, + style = FlexiTheme.typography.secondary + ) +} \ No newline at end of file diff --git a/samples/shared/src/commonMain/kotlin/Preferences.kt b/samples/shared/src/commonMain/kotlin/Preferences.kt new file mode 100644 index 0000000..af586b6 --- /dev/null +++ b/samples/shared/src/commonMain/kotlin/Preferences.kt @@ -0,0 +1,145 @@ +/* + * Flexi UI - A flexible and useful UI component library. + * Copyright (C) 2019-2024 HighCapable + * https://github.com/BetterAndroid/FlexiUI + * + * Apache License Version 2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is created by fankes on 2024/1/11. + */ + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.Stable +import androidx.compose.runtime.mutableStateOf +import com.highcapable.flexiui.blueColors +import com.highcapable.flexiui.defaultColors +import com.highcapable.flexiui.greenColors +import com.highcapable.flexiui.isSystemColorAvailable +import com.highcapable.flexiui.orangeColors +import com.highcapable.flexiui.pinkColors +import com.highcapable.flexiui.purpleColors +import com.highcapable.flexiui.redColors +import com.highcapable.flexiui.systemColors +import com.highcapable.flexiui.yellowColors + +@Stable +data class AppPreferences( + var colorScheme: MutableState = mutableStateOf(ColorScheme.Default), + var darkMode: MutableState = mutableStateOf(false), + var followSystemDarkMode: MutableState = mutableStateOf(false) +) + +// TODO: Include ColorScheme to Flexi UI's Colors.kt + +@Stable +val Preferences = AppPreferences() + +@Stable +enum class ColorScheme { + Default, + DefaultBlack, + System, + SystemBlack, + Red, + RedBlack, + Pink, + PinkBlack, + Purple, + PurpleBlack, + Orange, + OrangeBlack, + Yellow, + YellowBlack, + Green, + GreenBlack, + Blue, + BlueBlack +} + +@Composable +fun colorSchemes(): Array { + val defaultColors = arrayOf( + ColorScheme.Default, + ColorScheme.DefaultBlack + ) + val systemColors = arrayOf( + ColorScheme.System, + ColorScheme.SystemBlack + ) + val presetColors = arrayOf( + ColorScheme.Red, + ColorScheme.RedBlack, + ColorScheme.Pink, + ColorScheme.PinkBlack, + ColorScheme.Purple, + ColorScheme.PurpleBlack, + ColorScheme.Orange, + ColorScheme.OrangeBlack, + ColorScheme.Yellow, + ColorScheme.YellowBlack, + ColorScheme.Green, + ColorScheme.GreenBlack, + ColorScheme.Blue, + ColorScheme.BlueBlack + ) + return if (isSystemColorAvailable()) + defaultColors + systemColors + presetColors + else defaultColors + presetColors +} + +@Composable +fun ColorScheme.toColors(darkMode: Boolean) = when (this) { + ColorScheme.Default -> defaultColors(darkMode) + ColorScheme.DefaultBlack -> defaultColors(darkMode, blackDarkMode = true) + ColorScheme.System -> systemColors(darkMode) + ColorScheme.SystemBlack -> systemColors(darkMode, blackDarkMode = true) + ColorScheme.Red -> redColors(darkMode) + ColorScheme.RedBlack -> redColors(darkMode, blackDarkMode = true) + ColorScheme.Pink -> pinkColors(darkMode) + ColorScheme.PinkBlack -> pinkColors(darkMode, blackDarkMode = true) + ColorScheme.Purple -> purpleColors(darkMode) + ColorScheme.PurpleBlack -> purpleColors(darkMode, blackDarkMode = true) + ColorScheme.Orange -> orangeColors(darkMode) + ColorScheme.OrangeBlack -> orangeColors(darkMode, blackDarkMode = true) + ColorScheme.Yellow -> yellowColors(darkMode) + ColorScheme.YellowBlack -> yellowColors(darkMode, blackDarkMode = true) + ColorScheme.Green -> greenColors(darkMode) + ColorScheme.GreenBlack -> greenColors(darkMode, blackDarkMode = true) + ColorScheme.Blue -> blueColors(darkMode) + ColorScheme.BlueBlack -> blueColors(darkMode, blackDarkMode = true) +} + +@Stable +fun ColorScheme.toName() = when (this) { + ColorScheme.Default -> "Default" + ColorScheme.DefaultBlack -> "Default (Black)" + ColorScheme.System -> "System" + ColorScheme.SystemBlack -> "System (Black)" + ColorScheme.Red -> "Red" + ColorScheme.RedBlack -> "Red (Black)" + ColorScheme.Pink -> "Pink" + ColorScheme.PinkBlack -> "Pink (Black)" + ColorScheme.Purple -> "Purple" + ColorScheme.PurpleBlack -> "Purple (Black)" + ColorScheme.Orange -> "Orange" + ColorScheme.OrangeBlack -> "Orange (Black)" + ColorScheme.Yellow -> "Yellow" + ColorScheme.YellowBlack -> "Yellow (Black)" + ColorScheme.Green -> "Green" + ColorScheme.GreenBlack -> "Green (Black)" + ColorScheme.Blue -> "Blue" + ColorScheme.BlueBlack -> "Blue (Black)" +} \ No newline at end of file