0
0
mirror of https://github.com/florisboard/florisboard.git synced 2024-09-19 11:32:18 +02:00

Enable "dynamic" color schemes for all supported api levels. The fallback m3 scheme is used

This commit is contained in:
lm41 2024-07-10 17:51:12 +02:00
parent be4cd4d897
commit b91ef2b974
No known key found for this signature in database
15 changed files with 235 additions and 108 deletions

View File

@ -208,6 +208,7 @@ dependencies {
implementation(project(":lib:kotlin"))
implementation(project(":lib:native"))
implementation(project(":lib:snygg"))
implementation(project(":lib:theme"))
testImplementation(libs.equalsverifier)
testImplementation(libs.kotest.assertions.core)

View File

@ -18,22 +18,20 @@ package dev.patrickgold.florisboard.app.apptheme
import android.app.Activity
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
import dev.patrickgold.florisboard.app.AppTheme
import org.florisboard.lib.android.AndroidVersion
import org.florisboard.lib.theme.amoledDark
import org.florisboard.lib.theme.amoledFlorisColorScheme
import org.florisboard.lib.theme.darkFlorisColorScheme
import org.florisboard.lib.theme.lightFlorisColorScheme
/*private val AmoledDarkColorPalette = darkColorScheme(
primary = Green500,
@ -74,86 +72,7 @@ private val LightColorPalette = lightColorScheme(
*/
)*/
private val lightScheme = lightColorScheme(
primary = primaryLight,
onPrimary = onPrimaryLight,
primaryContainer = primaryContainerLight,
onPrimaryContainer = onPrimaryContainerLight,
secondary = secondaryLight,
onSecondary = onSecondaryLight,
secondaryContainer = secondaryContainerLight,
onSecondaryContainer = onSecondaryContainerLight,
tertiary = tertiaryLight,
onTertiary = onTertiaryLight,
tertiaryContainer = tertiaryContainerLight,
onTertiaryContainer = onTertiaryContainerLight,
error = errorLight,
onError = onErrorLight,
errorContainer = errorContainerLight,
onErrorContainer = onErrorContainerLight,
background = backgroundLight,
onBackground = onBackgroundLight,
surface = surfaceLight,
onSurface = onSurfaceLight,
surfaceVariant = surfaceVariantLight,
onSurfaceVariant = onSurfaceVariantLight,
outline = outlineLight,
outlineVariant = outlineVariantLight,
scrim = scrimLight,
inverseSurface = inverseSurfaceLight,
inverseOnSurface = inverseOnSurfaceLight,
inversePrimary = inversePrimaryLight,
surfaceDim = surfaceDimLight,
surfaceBright = surfaceBrightLight,
surfaceContainerLowest = surfaceContainerLowestLight,
surfaceContainerLow = surfaceContainerLowLight,
surfaceContainer = surfaceContainerLight,
surfaceContainerHigh = surfaceContainerHighLight,
surfaceContainerHighest = surfaceContainerHighestLight,
)
private val darkScheme = darkColorScheme(
primary = primaryDark,
onPrimary = onPrimaryDark,
primaryContainer = primaryContainerDark,
onPrimaryContainer = onPrimaryContainerDark,
secondary = secondaryDark,
onSecondary = onSecondaryDark,
secondaryContainer = secondaryContainerDark,
onSecondaryContainer = onSecondaryContainerDark,
tertiary = tertiaryDark,
onTertiary = onTertiaryDark,
tertiaryContainer = tertiaryContainerDark,
onTertiaryContainer = onTertiaryContainerDark,
error = errorDark,
onError = onErrorDark,
errorContainer = errorContainerDark,
onErrorContainer = onErrorContainerDark,
background = backgroundDark,
onBackground = onBackgroundDark,
surface = surfaceDark,
onSurface = onSurfaceDark,
surfaceVariant = surfaceVariantDark,
onSurfaceVariant = onSurfaceVariantDark,
outline = outlineDark,
outlineVariant = outlineVariantDark,
scrim = scrimDark,
inverseSurface = inverseSurfaceDark,
inverseOnSurface = inverseOnSurfaceDark,
inversePrimary = inversePrimaryDark,
surfaceDim = surfaceDimDark,
surfaceBright = surfaceBrightDark,
surfaceContainerLowest = surfaceContainerLowestDark,
surfaceContainerLow = surfaceContainerLowDark,
surfaceContainer = surfaceContainerDark,
surfaceContainerHigh = surfaceContainerHighDark,
surfaceContainerHighest = surfaceContainerHighestDark,
)
private val amoledScheme = darkScheme.copy(
background = amoledDark,
surface = amoledDark
)
@Composable
fun FlorisAppTheme(
@ -172,8 +91,8 @@ fun FlorisAppTheme(
else -> {
when {
isSystemInDarkTheme() -> darkScheme
else -> lightScheme
isSystemInDarkTheme() -> darkFlorisColorScheme
else -> lightFlorisColorScheme
}
}
}
@ -190,20 +109,20 @@ fun FlorisAppTheme(
else -> {
when {
isSystemInDarkTheme() -> amoledScheme
else -> lightScheme
isSystemInDarkTheme() -> amoledFlorisColorScheme
else -> lightFlorisColorScheme
}
}
}
AppTheme.LIGHT -> when {
isMaterialYouAware -> dynamicLightColorScheme(LocalContext.current)
else -> lightScheme
else -> lightFlorisColorScheme
}
AppTheme.DARK -> when {
isMaterialYouAware -> dynamicDarkColorScheme(LocalContext.current)
else -> darkScheme
else -> darkFlorisColorScheme
}
AppTheme.AMOLED_DARK -> when {
@ -212,24 +131,24 @@ fun FlorisAppTheme(
surface = amoledDark,
)
else -> amoledScheme
else -> amoledFlorisColorScheme
}
}
} else {
when (theme) {
AppTheme.AUTO -> when {
isSystemInDarkTheme() -> darkScheme
else -> lightScheme
isSystemInDarkTheme() -> darkFlorisColorScheme
else -> lightFlorisColorScheme
}
AppTheme.AUTO_AMOLED -> when {
isSystemInDarkTheme() -> darkScheme
else -> lightScheme
isSystemInDarkTheme() -> darkFlorisColorScheme
else -> lightFlorisColorScheme
}
AppTheme.LIGHT -> lightScheme
AppTheme.DARK -> darkScheme
AppTheme.AMOLED_DARK -> amoledScheme
AppTheme.LIGHT -> lightFlorisColorScheme
AppTheme.DARK -> darkFlorisColorScheme
AppTheme.AMOLED_DARK -> amoledFlorisColorScheme
}
}

View File

@ -40,6 +40,8 @@ import org.florisboard.lib.snygg.Snygg
import org.florisboard.lib.snygg.SnyggStylesheet
import org.florisboard.lib.snygg.ui.ProvideSnyggUiDefaults
import org.florisboard.lib.snygg.ui.SnyggUiDefaults
import org.florisboard.lib.theme.darkFlorisColorScheme
import org.florisboard.lib.theme.lightFlorisColorScheme
private val LocalConfig = staticCompositionLocalOf<ThemeExtensionComponent> { error("not init") }
private val LocalStyle = staticCompositionLocalOf<SnyggStylesheet> { error("not init") }
@ -119,13 +121,13 @@ fun FlorisImeTheme(content: @Composable () -> Unit) {
if (AndroidVersion.ATLEAST_API31_S) {
dynamicDarkColorScheme(context)
} else {
MaterialDarkFallbackPalette
darkFlorisColorScheme
}
} else {
if (AndroidVersion.ATLEAST_API31_S) {
dynamicLightColorScheme(context)
} else {
MaterialLightFallbackPalette
lightFlorisColorScheme
}
}
MaterialTheme(materialColors) {

View File

@ -45,6 +45,7 @@ android {
dependencies {
implementation(project(":lib:android"))
implementation(project(":lib:kotlin"))
implementation(project(":lib:theme"))
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.compose.material3)

View File

@ -21,10 +21,13 @@ import androidx.compose.material3.ColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.ui.graphics.Color
import org.florisboard.lib.android.AndroidVersion
import org.florisboard.lib.snygg.value.MaterialYouColor.ColorName
import org.florisboard.lib.snygg.value.MaterialYouColor.ColorNameId
import org.florisboard.lib.snygg.value.MaterialYouColor.darkColorName
import org.florisboard.lib.snygg.value.MaterialYouColor.lightColorName
import org.florisboard.lib.theme.darkFlorisColorScheme
import org.florisboard.lib.theme.lightFlorisColorScheme
sealed interface SnyggMaterialYouValue : SnyggValue {
val colorName: String
@ -78,12 +81,20 @@ object MaterialYouColor {
private fun getAndCacheColorScheme(context: Context, dark: Boolean): ColorScheme {
return if (dark) {
if (darkColorScheme == null) {
darkColorScheme = dynamicDarkColorScheme(context)
darkColorScheme = if (AndroidVersion.ATLEAST_API31_S) {
dynamicDarkColorScheme(context)
} else {
darkFlorisColorScheme
}
}
darkColorScheme!!
} else {
if (lightColorScheme == null) {
lightColorScheme = dynamicLightColorScheme(context)
lightColorScheme = if (AndroidVersion.ATLEAST_API31_S) {
dynamicLightColorScheme(context)
} else {
lightFlorisColorScheme
}
}
lightColorScheme!!
}
@ -138,6 +149,8 @@ object MaterialYouColor {
fun loadColor(context: Context, colorName: String, dark: Boolean): Color {
val colorScheme = getAndCacheColorScheme(context, dark)
println(colorName)
return when (colorName) {
ColorPalette.Primary.id -> colorScheme.primary
ColorPalette.OnPrimary.id -> colorScheme.onPrimary
@ -176,6 +189,9 @@ object MaterialYouColor {
ColorPalette.SurfaceContainerLow.id -> colorScheme.surfaceContainerLow
ColorPalette.SurfaceContainerLowest.id -> colorScheme.surfaceContainerLowest
else -> colorScheme.primary
}.let {
println(it)
it
}
}
}

View File

@ -16,8 +16,6 @@
package org.florisboard.lib.snygg.value
import org.florisboard.lib.android.AndroidVersion
/**
* SnyggValue is the base interface for all possible property values a Snygg stylesheet can hold. In general, a Snygg
* value can be one specific type of value (e.g. a color, a keyword describing a behavior, shape, etc.).
@ -109,8 +107,8 @@ object SnyggImplicitInheritValue : SnyggValue, SnyggValueEncoder {
val SnyggVarValueEncoders = listOfNotNull(
SnyggSolidColorValue,
if (AndroidVersion.ATLEAST_API31_S) SnyggMaterialYouLightColorValue else null,
if (AndroidVersion.ATLEAST_API31_S) SnyggMaterialYouDarkColorValue else null,
SnyggMaterialYouLightColorValue,
SnyggMaterialYouDarkColorValue,
//SnyggImageRefValue,
SnyggRectangleShapeValue,
SnyggCircleShapeValue,

1
lib/theme/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,40 @@
plugins {
alias(libs.plugins.agp.library)
alias(libs.plugins.kotlin.android)
}
val projectMinSdk: String by project
val projectCompileSdk: String by project
android {
namespace = "org.florisboard.lib.theme"
compileSdk = projectCompileSdk.toInt()
defaultConfig {
minSdk = projectMinSdk.toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.kotlinx.serialization.json)
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.material3)
}

View File

21
lib/theme/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,22 @@
package org.florisboard.lib.theme
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("org.florisboard.lib.theme.test", appContext.packageName)
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
>
</manifest>

View File

@ -14,8 +14,10 @@
* limitations under the License.
*/
package dev.patrickgold.florisboard.app.apptheme
package org.florisboard.lib.theme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/* Legacy Colors
@ -100,3 +102,85 @@ val surfaceContainerHighDark = Color(0xFF262C24)
val surfaceContainerHighestDark = Color(0xFF30362E)
val amoledDark = Color(0xFF000000)
val lightFlorisColorScheme = lightColorScheme(
primary = primaryLight,
onPrimary = onPrimaryLight,
primaryContainer = primaryContainerLight,
onPrimaryContainer = onPrimaryContainerLight,
secondary = secondaryLight,
onSecondary = onSecondaryLight,
secondaryContainer = secondaryContainerLight,
onSecondaryContainer = onSecondaryContainerLight,
tertiary = tertiaryLight,
onTertiary = onTertiaryLight,
tertiaryContainer = tertiaryContainerLight,
onTertiaryContainer = onTertiaryContainerLight,
error = errorLight,
onError = onErrorLight,
errorContainer = errorContainerLight,
onErrorContainer = onErrorContainerLight,
background = backgroundLight,
onBackground = onBackgroundLight,
surface = surfaceLight,
onSurface = onSurfaceLight,
surfaceVariant = surfaceVariantLight,
onSurfaceVariant = onSurfaceVariantLight,
outline = outlineLight,
outlineVariant = outlineVariantLight,
scrim = scrimLight,
inverseSurface = inverseSurfaceLight,
inverseOnSurface = inverseOnSurfaceLight,
inversePrimary = inversePrimaryLight,
surfaceDim = surfaceDimLight,
surfaceBright = surfaceBrightLight,
surfaceContainerLowest = surfaceContainerLowestLight,
surfaceContainerLow = surfaceContainerLowLight,
surfaceContainer = surfaceContainerLight,
surfaceContainerHigh = surfaceContainerHighLight,
surfaceContainerHighest = surfaceContainerHighestLight,
)
val darkFlorisColorScheme = darkColorScheme(
primary = primaryDark,
onPrimary = onPrimaryDark,
primaryContainer = primaryContainerDark,
onPrimaryContainer = onPrimaryContainerDark,
secondary = secondaryDark,
onSecondary = onSecondaryDark,
secondaryContainer = secondaryContainerDark,
onSecondaryContainer = onSecondaryContainerDark,
tertiary = tertiaryDark,
onTertiary = onTertiaryDark,
tertiaryContainer = tertiaryContainerDark,
onTertiaryContainer = onTertiaryContainerDark,
error = errorDark,
onError = onErrorDark,
errorContainer = errorContainerDark,
onErrorContainer = onErrorContainerDark,
background = backgroundDark,
onBackground = onBackgroundDark,
surface = surfaceDark,
onSurface = onSurfaceDark,
surfaceVariant = surfaceVariantDark,
onSurfaceVariant = onSurfaceVariantDark,
outline = outlineDark,
outlineVariant = outlineVariantDark,
scrim = scrimDark,
inverseSurface = inverseSurfaceDark,
inverseOnSurface = inverseOnSurfaceDark,
inversePrimary = inversePrimaryDark,
surfaceDim = surfaceDimDark,
surfaceBright = surfaceBrightDark,
surfaceContainerLowest = surfaceContainerLowestDark,
surfaceContainerLow = surfaceContainerLowDark,
surfaceContainer = surfaceContainerDark,
surfaceContainerHigh = surfaceContainerHighDark,
surfaceContainerHighest = surfaceContainerHighestDark,
)
val amoledFlorisColorScheme = darkFlorisColorScheme.copy(
background = amoledDark,
surface = amoledDark
)

View File

@ -0,0 +1,16 @@
package org.florisboard.lib.theme
import org.junit.Assert.*
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@ -39,3 +39,4 @@ include(":lib:android")
include(":lib:kotlin")
include(":lib:native")
include(":lib:snygg")
include(":lib:theme")