Replace the first palette with the color scheme provided by the system (#48)

* Replace the first palette with the color scheme provided by the system

* Clean up the code
This commit is contained in:
Ashinch 2022-05-07 00:39:38 +08:00 committed by GitHub
parent 4c7ff2a84e
commit b1f6b60e72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 177 additions and 31 deletions

View File

@ -1,5 +1,6 @@
package me.ash.reader.ui.page.home
import android.os.Build
import android.view.SoundEffectConstants
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Spacer
@ -13,6 +14,7 @@ import androidx.compose.ui.unit.Dp
import com.google.accompanist.pager.ExperimentalPagerApi
import me.ash.reader.data.entity.Filter
import me.ash.reader.data.preference.FlowFilterBarStylePreference
import me.ash.reader.data.preference.LocalThemeIndex
import me.ash.reader.ui.ext.getName
import me.ash.reader.ui.ext.surfaceColorAtElevation
import me.ash.reader.ui.theme.palette.onDark
@ -29,6 +31,7 @@ fun FilterBar(
filterOnClick: (Filter) -> Unit = {},
) {
val view = LocalView.current
val themeIndex = LocalThemeIndex.current
NavigationBar(
modifier = Modifier
@ -77,12 +80,12 @@ fun FilterBar(
filterOnClick(item)
},
colors = NavigationBarItemDefaults.colors(
// selectedIconColor = MaterialTheme.colorScheme.onSecondaryContainer alwaysLight true,
// unselectedIconColor = MaterialTheme.colorScheme.outline,
// selectedTextColor = MaterialTheme.colorScheme.onSurface alwaysLight true,
// unselectedTextColor = MaterialTheme.colorScheme.onSurfaceVariant,
indicatorColor = MaterialTheme.colorScheme.primaryContainer onDark MaterialTheme.colorScheme.secondaryContainer,
)
indicatorColor = if (themeIndex == 5 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
MaterialTheme.colorScheme.secondaryContainer
} else {
MaterialTheme.colorScheme.primaryContainer
} onDark MaterialTheme.colorScheme.secondaryContainer,
),
)
}
Spacer(modifier = Modifier.width(filterBarPadding))

View File

@ -204,7 +204,6 @@ fun ColorAndStyle(
)
}
@SuppressLint("FlowOperatorInvokedInComposition")
@Composable
fun Palettes(
modifier: Modifier = Modifier,

View File

@ -1,6 +1,5 @@
package me.ash.reader.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@ -14,7 +13,7 @@ import me.ash.reader.ui.theme.palette.dynamicLightColorScheme
@Composable
fun AppTheme(
useDarkTheme: Boolean = isSystemInDarkTheme(),
useDarkTheme: Boolean,
wallpaperPalettes: List<TonalPalettes> = extractTonalPalettesFromUserWallpaper(),
content: @Composable () -> Unit
) {
@ -34,7 +33,7 @@ fun AppTheme(
ProvideZcamViewingConditions {
CompositionLocalProvider(
LocalTonalPalettes provides tonalPalettes.also { it.Preheating() },
LocalTonalPalettes provides tonalPalettes.apply { Preheating() },
) {
MaterialTheme(
colorScheme =

View File

@ -5,6 +5,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.Color
import me.ash.reader.data.preference.LocalAmoledDarkTheme
import me.ash.reader.data.preference.LocalDarkTheme
@ -127,6 +128,7 @@ fun String.checkColorHex(): String? {
return "[0-9a-fA-F]{6}".toRegex().find(s)?.value
}
@Stable
fun String.safeHexToColor(): Color =
try {
Color(java.lang.Long.parseLong(this, 16))

View File

@ -3,11 +3,18 @@
*
* @link https://github.com/Kyant0/MusicYou
* @author Kyant0
* @modifier Ashinch
*/
package me.ash.reader.ui.theme.palette
import android.content.Context
import android.os.Build
import androidx.annotation.ColorRes
import androidx.annotation.DoNotInline
import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.graphics.Color
import me.ash.reader.ui.theme.palette.colorspace.cielab.CieLab
@ -21,6 +28,8 @@ typealias TonalValue = Int
typealias TonalPalette = MutableMap<TonalValue, Color>
val tonalTokens = listOf(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99, 100)
val LocalTonalPalettes = compositionLocalOf {
TonalPalettes(238.36, 15.0)
}
@ -97,20 +106,144 @@ data class TonalPalettes(
@Composable
fun Preheating() {
val tonalValues = listOf(0, 10, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 95, 98, 99, 100)
tonalValues.forEach { primary(it) }
tonalValues.forEach { secondary(it) }
tonalValues.forEach { tertiary(it) }
tonalValues.forEach { neutral(it) }
tonalValues.forEach { neutralVariant(it) }
tonalValues.forEach { error(it) }
tonalTokens.forEach { primary(it) }
tonalTokens.forEach { secondary(it) }
tonalTokens.forEach { tertiary(it) }
tonalTokens.forEach { neutral(it) }
tonalTokens.forEach { neutralVariant(it) }
tonalTokens.forEach { error(it) }
}
@RequiresApi(Build.VERSION_CODES.S)
private fun primarySystem(context: Context, tone: TonalValue): Color = when (tone) {
0 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_1000)
10 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_900)
20 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_800)
30 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_700)
40 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_600)
50 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_500)
60 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_400)
70 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_300)
80 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_200)
90 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_100)
95 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_50)
99 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_10)
100 -> ColorResourceHelper.getColor(context, android.R.color.system_accent1_0)
else -> throw IllegalArgumentException("Unknown primary tone: $tone")
}
@RequiresApi(Build.VERSION_CODES.S)
private fun secondarySystem(context: Context, tone: TonalValue): Color = when (tone) {
0 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_1000)
10 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_900)
20 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_800)
30 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_700)
40 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_600)
50 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_500)
60 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_400)
70 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_300)
80 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_200)
90 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_100)
95 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_50)
99 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_10)
100 -> ColorResourceHelper.getColor(context, android.R.color.system_accent2_0)
else -> throw IllegalArgumentException("Unknown secondary tone: $tone")
}
@RequiresApi(Build.VERSION_CODES.S)
private fun tertiarySystem(context: Context, tone: TonalValue): Color = when (tone) {
0 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_1000)
10 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_900)
20 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_800)
30 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_700)
40 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_600)
50 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_500)
60 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_400)
70 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_300)
80 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_200)
90 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_100)
95 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_50)
99 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_10)
100 -> ColorResourceHelper.getColor(context, android.R.color.system_accent3_0)
else -> throw IllegalArgumentException("Unknown tertiary tone: $tone")
}
@RequiresApi(Build.VERSION_CODES.S)
private fun neutralSystem(context: Context, tone: TonalValue): Color = when (tone) {
0 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_1000)
10 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_900)
20 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_800)
30 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_700)
40 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_600)
50 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_500)
60 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_400)
70 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_300)
80 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_200)
90 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_100)
95 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_50)
99 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_10)
100 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral1_0)
else -> throw IllegalArgumentException("Unknown neutral tone: $tone")
}
@RequiresApi(Build.VERSION_CODES.S)
private fun neutralVariantSystem(context: Context, tone: TonalValue): Color = when (tone) {
0 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_1000)
10 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_900)
20 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_800)
30 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_700)
40 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
50 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_500)
60 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_400)
70 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_300)
80 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_200)
90 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_100)
95 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_50)
99 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_10)
100 -> ColorResourceHelper.getColor(context, android.R.color.system_neutral2_0)
else -> throw IllegalArgumentException("Unknown neutral variant tone: $tone")
}
companion object {
@Composable
@Stable
fun Color.toTonalPalettes(): TonalPalettes {
val zcam = toRgb().toZcam()
return TonalPalettes(hue = zcam.hz, primaryChroma = zcam.Cz)
}
@RequiresApi(Build.VERSION_CODES.S)
@Composable
@Stable
fun Context.getSystemTonalPalettes(): TonalPalettes {
val tonalPalettes = LocalTonalPalettes.current
tonalTokens.forEach {
tonalPalettes.primary[it] = tonalPalettes.primarySystem(this, it)
}
tonalTokens.forEach {
tonalPalettes.secondary[it] = tonalPalettes.secondarySystem(this, it)
}
tonalTokens.forEach {
tonalPalettes.tertiary[it] = tonalPalettes.tertiarySystem(this, it)
}
tonalTokens.forEach {
tonalPalettes.neutral[it] = tonalPalettes.neutralSystem(this, it)
}
tonalTokens.forEach {
tonalPalettes.neutralVariant[it] = tonalPalettes.neutralVariantSystem(this, it)
}
tonalTokens.forEach {
tonalPalettes error it
}
return tonalPalettes
}
}
}
@RequiresApi(23)
object ColorResourceHelper {
@DoNotInline
fun getColor(context: Context, @ColorRes id: Int): Color {
return Color(context.resources.getColor(id, context.theme))
}
}

View File

@ -8,43 +8,53 @@
package me.ash.reader.ui.theme.palette.dynamic
import android.annotation.SuppressLint
import android.app.WallpaperManager
import android.os.Build
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import kotlinx.coroutines.flow.map
import me.ash.reader.ui.ext.DataStoreKeys
import me.ash.reader.ui.ext.dataStore
import me.ash.reader.data.preference.LocalCustomPrimaryColor
import me.ash.reader.ui.theme.palette.TonalPalettes
import me.ash.reader.ui.theme.palette.TonalPalettes.Companion.getSystemTonalPalettes
import me.ash.reader.ui.theme.palette.TonalPalettes.Companion.toTonalPalettes
import me.ash.reader.ui.theme.palette.safeHexToColor
@SuppressLint("FlowOperatorInvokedInComposition")
object PresetColor {
val blue = Color(0xFF80BBFF)
val pink = Color(0xFFFFD8E4)
val purple = Color(0xFF62539f)
val yellow = Color(0xFFE9B666)
}
@Composable
@Stable
fun extractTonalPalettesFromUserWallpaper(): List<TonalPalettes> {
val context = LocalContext.current
val customPrimaryColor =
context.dataStore.data.map { it[DataStoreKeys.CustomPrimaryColor.key] ?: "" }
.collectAsState(initial = "").value
val customPrimaryColor = LocalCustomPrimaryColor.current
val preset = mutableListOf(
Color(0xFF80BBFF).toTonalPalettes(),
Color(0xFFFFD8E4).toTonalPalettes(),
Color(0xFF62539f).toTonalPalettes(),
Color(0xFFE9B666).toTonalPalettes(),
PresetColor.blue.toTonalPalettes(),
PresetColor.pink.toTonalPalettes(),
PresetColor.purple.toTonalPalettes(),
PresetColor.yellow.toTonalPalettes(),
customPrimaryColor.safeHexToColor().toTonalPalettes()
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 && !LocalView.current.isInEditMode) {
val colors = WallpaperManager.getInstance(LocalContext.current)
.getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
val primary = colors?.primaryColor?.toArgb()
val secondary = colors?.secondaryColor?.toArgb()
val tertiary = colors?.tertiaryColor?.toArgb()
if (primary != null) preset.add(Color(primary).toTonalPalettes())
if (primary != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
preset.add(context.getSystemTonalPalettes())
} else {
preset.add(Color(primary).toTonalPalettes())
}
}
if (secondary != null) preset.add(Color(secondary).toTonalPalettes())
if (tertiary != null) preset.add(Color(tertiary).toTonalPalettes())
}