mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-28 02:29:09 +00:00
upgrade user theme selection, now multiple themes are possible
currently missing: old "show more/all colors", and import/export
This commit is contained in:
parent
40433bd8d2
commit
63bda02cc4
13 changed files with 430 additions and 109 deletions
|
@ -14,7 +14,7 @@ android {
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 2302
|
versionCode = 2302
|
||||||
versionName = "2.3"
|
versionName = "2.3+dev1"
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters.clear()
|
abiFilters.clear()
|
||||||
abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64"))
|
abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64"))
|
||||||
|
|
|
@ -24,6 +24,7 @@ import helium314.keyboard.latin.utils.brightenOrDarken
|
||||||
import helium314.keyboard.latin.utils.isBrightColor
|
import helium314.keyboard.latin.utils.isBrightColor
|
||||||
import helium314.keyboard.latin.utils.isGoodContrast
|
import helium314.keyboard.latin.utils.isGoodContrast
|
||||||
import helium314.keyboard.latin.utils.prefs
|
import helium314.keyboard.latin.utils.prefs
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.util.EnumMap
|
import java.util.EnumMap
|
||||||
|
|
||||||
|
@ -59,19 +60,23 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) {
|
||||||
const val THEME_PINK = "pink"
|
const val THEME_PINK = "pink"
|
||||||
const val THEME_SAND = "sand"
|
const val THEME_SAND = "sand"
|
||||||
const val THEME_VIOLETTE = "violette"
|
const val THEME_VIOLETTE = "violette"
|
||||||
fun getAvailableColors(prefs: SharedPreferences, isNight: Boolean) = listOfNotNull(
|
fun getAvailableDefaultColors(prefs: SharedPreferences, isNight: Boolean) = listOfNotNull(
|
||||||
if (!isNight) THEME_LIGHT else null, THEME_DARK, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) THEME_DYNAMIC else null,
|
if (!isNight) THEME_LIGHT else null, THEME_DARK,
|
||||||
if (prefs.getString(Settings.PREF_THEME_STYLE, Defaults.PREF_THEME_STYLE) == STYLE_HOLO) THEME_HOLO_WHITE else null,
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) THEME_DYNAMIC else null,
|
||||||
THEME_DARKER, THEME_BLACK, if (!isNight) THEME_BLUE_GRAY else null, if (!isNight) THEME_BROWN else null,
|
if (prefs.getString(Settings.PREF_THEME_STYLE, Defaults.PREF_THEME_STYLE) == STYLE_HOLO) THEME_HOLO_WHITE else null,
|
||||||
THEME_CHOCOLATE, THEME_CLOUDY, THEME_FOREST, if (!isNight) THEME_INDIGO else null, if (!isNight) THEME_PINK else null,
|
THEME_DARKER,
|
||||||
THEME_OCEAN, if (!isNight) THEME_SAND else null, THEME_VIOLETTE
|
THEME_BLACK,
|
||||||
) + prefs.all.keys.mapNotNull {
|
if (!isNight) THEME_BLUE_GRAY else null,
|
||||||
when {
|
if (!isNight) THEME_BROWN else null,
|
||||||
it.startsWith(Settings.PREF_USER_COLORS_PREFIX) -> it.substringAfter(Settings.PREF_USER_COLORS_PREFIX)
|
THEME_CHOCOLATE,
|
||||||
it.startsWith(Settings.PREF_USER_ALL_COLORS_PREFIX) -> it.substringAfter(Settings.PREF_USER_ALL_COLORS_PREFIX)
|
THEME_CLOUDY,
|
||||||
else -> null
|
THEME_FOREST,
|
||||||
}
|
if (!isNight) THEME_INDIGO else null,
|
||||||
}.toSortedSet() // we don't want duplicates, and we want a consistent order
|
if (!isNight) THEME_PINK else null,
|
||||||
|
THEME_OCEAN,
|
||||||
|
if (!isNight) THEME_SAND else null,
|
||||||
|
THEME_VIOLETTE
|
||||||
|
)
|
||||||
val STYLES = arrayOf(STYLE_MATERIAL, STYLE_HOLO, STYLE_ROUNDED)
|
val STYLES = arrayOf(STYLE_MATERIAL, STYLE_HOLO, STYLE_ROUNDED)
|
||||||
|
|
||||||
// These should be aligned with Keyboard.themeId and Keyboard.Case.keyboardTheme
|
// These should be aligned with Keyboard.themeId and Keyboard.Case.keyboardTheme
|
||||||
|
@ -326,13 +331,13 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeUserColors(prefs: SharedPreferences, themeName: String, colors: Map<String, Pair<Int?, Boolean>>) {
|
fun writeUserColors(prefs: SharedPreferences, themeName: String, colors: List<ColorSetting>) {
|
||||||
val key = Settings.PREF_USER_COLORS_PREFIX + themeName
|
val key = Settings.PREF_USER_COLORS_PREFIX + themeName
|
||||||
val value = Json.encodeToString(colors.filterValues { it.first != null })
|
val value = Json.encodeToString(colors.filter { it.color != null || it.auto == false })
|
||||||
prefs.edit().putString(key, value).apply()
|
prefs.edit().putString(key, value).apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readUserColors(prefs: SharedPreferences, themeName: String): Map<String, Pair<Int, Boolean>> {
|
fun readUserColors(prefs: SharedPreferences, themeName: String): List<ColorSetting> {
|
||||||
val key = Settings.PREF_USER_COLORS_PREFIX + themeName
|
val key = Settings.PREF_USER_COLORS_PREFIX + themeName
|
||||||
return Json.decodeFromString(prefs.getString(key, Defaults.PREF_USER_COLORS)!!)
|
return Json.decodeFromString(prefs.getString(key, Defaults.PREF_USER_COLORS)!!)
|
||||||
}
|
}
|
||||||
|
@ -368,14 +373,16 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) {
|
||||||
return colorMap
|
return colorMap
|
||||||
}
|
}
|
||||||
|
|
||||||
fun determineUserColor(colors: Map<String, Pair<Int?, Boolean>>, context: Context, colorName: String, isNight: Boolean): Int {
|
fun determineUserColor(colors: List<ColorSetting>, context: Context, colorName: String, isNight: Boolean): Int {
|
||||||
val (color, auto) = colors[colorName] ?: (null to true)
|
val c = colors.firstOrNull { it.name == colorName }
|
||||||
|
val color = c?.color
|
||||||
|
val auto = c?.auto ?: true
|
||||||
return if (auto || color == null)
|
return if (auto || color == null)
|
||||||
determineAutoColor(colors, colorName, isNight, context)
|
determineAutoColor(colors, colorName, isNight, context)
|
||||||
else color
|
else color
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun determineAutoColor(colors: Map<String, Pair<Int?, Boolean>>, colorName: String, isNight: Boolean, context: Context): Int {
|
private fun determineAutoColor(colors: List<ColorSetting>, colorName: String, isNight: Boolean, context: Context): Int {
|
||||||
when (colorName) {
|
when (colorName) {
|
||||||
COLOR_ACCENT -> {
|
COLOR_ACCENT -> {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||||
|
@ -427,3 +434,8 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ColorSetting(val name: String, val auto: Boolean?, val color: Int?) {
|
||||||
|
var displayName = name
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ package helium314.keyboard.latin
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
|
import helium314.keyboard.keyboard.ColorSetting
|
||||||
import helium314.keyboard.keyboard.KeyboardTheme
|
import helium314.keyboard.keyboard.KeyboardTheme
|
||||||
import helium314.keyboard.latin.common.ColorType
|
import helium314.keyboard.latin.common.ColorType
|
||||||
import helium314.keyboard.latin.common.LocaleUtils.constructLocale
|
import helium314.keyboard.latin.common.LocaleUtils.constructLocale
|
||||||
|
@ -167,14 +168,14 @@ fun checkVersionUpgrade(context: Context) {
|
||||||
}
|
}
|
||||||
// day colors
|
// day colors
|
||||||
val themeNameDay = context.getString(R.string.theme_name_user)
|
val themeNameDay = context.getString(R.string.theme_name_user)
|
||||||
val colorsDay = colorPrefsAndResIds.associate {
|
val colorsDay = colorPrefsAndResIds.map {
|
||||||
val pref = "theme_color_" + it.first
|
val pref = "theme_color_" + it.first
|
||||||
val color = if (prefs.contains(pref)) prefs.getInt(pref, 0) else null
|
val color = if (prefs.contains(pref)) prefs.getInt(pref, 0) else null
|
||||||
val result = it.first to (color to prefs.getBoolean(pref + "_auto", true))
|
val result = ColorSetting(it.first, prefs.getBoolean(pref + "_auto", true), color)
|
||||||
prefs.edit().remove(pref).remove(pref + "_auto").apply()
|
prefs.edit().remove(pref).remove(pref + "_auto").apply()
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
if (colorsDay.any { it.value.first != null }) {
|
if (colorsDay.any { it.color != null }) {
|
||||||
KeyboardTheme.writeUserColors(prefs, themeNameDay, colorsDay)
|
KeyboardTheme.writeUserColors(prefs, themeNameDay, colorsDay)
|
||||||
}
|
}
|
||||||
val moreColorsDay = prefs.getInt("theme_color_show_more_colors", 0)
|
val moreColorsDay = prefs.getInt("theme_color_show_more_colors", 0)
|
||||||
|
@ -190,14 +191,14 @@ fun checkVersionUpgrade(context: Context) {
|
||||||
|
|
||||||
// same for night colors
|
// same for night colors
|
||||||
val themeNameNight = context.getString(R.string.theme_name_user_night)
|
val themeNameNight = context.getString(R.string.theme_name_user_night)
|
||||||
val colorsNight = colorPrefsAndResIds.associate {
|
val colorsNight = colorPrefsAndResIds.map {
|
||||||
val pref = "theme_dark_color_" + it.first
|
val pref = "theme_dark_color_" + it.first
|
||||||
val color = if (prefs.contains(pref)) prefs.getInt(pref, 0) else null
|
val color = if (prefs.contains(pref)) prefs.getInt(pref, 0) else null
|
||||||
val result = it.first to (color to prefs.getBoolean(pref + "_auto", true))
|
val result = ColorSetting(it.first, prefs.getBoolean(pref + "_auto", true), color)
|
||||||
prefs.edit().remove(pref).remove(pref + "_auto").apply()
|
prefs.edit().remove(pref).remove(pref + "_auto").apply()
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
if (colorsNight.any { it.value.first != null }) {
|
if (colorsNight.any { it.color!= null }) {
|
||||||
KeyboardTheme.writeUserColors(prefs, themeNameNight, colorsNight)
|
KeyboardTheme.writeUserColors(prefs, themeNameNight, colorsNight)
|
||||||
}
|
}
|
||||||
val moreColorsNight = prefs.getInt("theme_dark_color_show_more_colors", 0)
|
val moreColorsNight = prefs.getInt("theme_dark_color_show_more_colors", 0)
|
||||||
|
|
|
@ -143,7 +143,7 @@ object Defaults {
|
||||||
const val PREF_SHOW_SUGGESTION_INFOS = false
|
const val PREF_SHOW_SUGGESTION_INFOS = false
|
||||||
const val PREF_FORCE_NON_DISTINCT_MULTITOUCH = false
|
const val PREF_FORCE_NON_DISTINCT_MULTITOUCH = false
|
||||||
const val PREF_SLIDING_KEY_INPUT_PREVIEW = true
|
const val PREF_SLIDING_KEY_INPUT_PREVIEW = true
|
||||||
const val PREF_USER_COLORS = "{}"
|
const val PREF_USER_COLORS = "[]"
|
||||||
const val PREF_USER_MORE_COLORS = 0
|
const val PREF_USER_MORE_COLORS = 0
|
||||||
const val PREF_USER_ALL_COLORS = ""
|
const val PREF_USER_ALL_COLORS = ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import androidx.navigation.compose.rememberNavController
|
||||||
import helium314.keyboard.settings.screens.AboutScreen
|
import helium314.keyboard.settings.screens.AboutScreen
|
||||||
import helium314.keyboard.settings.screens.AdvancedSettingsScreen
|
import helium314.keyboard.settings.screens.AdvancedSettingsScreen
|
||||||
import helium314.keyboard.settings.screens.AppearanceScreen
|
import helium314.keyboard.settings.screens.AppearanceScreen
|
||||||
|
import helium314.keyboard.settings.screens.ColorsScreen
|
||||||
import helium314.keyboard.settings.screens.DebugScreen
|
import helium314.keyboard.settings.screens.DebugScreen
|
||||||
import helium314.keyboard.settings.screens.GestureTypingScreen
|
import helium314.keyboard.settings.screens.GestureTypingScreen
|
||||||
import helium314.keyboard.settings.screens.MainSettingsScreen
|
import helium314.keyboard.settings.screens.MainSettingsScreen
|
||||||
|
@ -95,16 +96,10 @@ fun SettingsNavHost(
|
||||||
// )
|
// )
|
||||||
}
|
}
|
||||||
composable(SettingsDestination.Colors) {
|
composable(SettingsDestination.Colors) {
|
||||||
// ColorsScreen(
|
ColorsScreen(isNight = false, onClickBack = ::goBack)
|
||||||
// night = false,
|
|
||||||
// onClickBack = ::goBack
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
composable(SettingsDestination.ColorsNight) {
|
composable(SettingsDestination.ColorsNight) {
|
||||||
// ColorsScreen(
|
ColorsScreen(isNight = true, onClickBack = ::goBack)
|
||||||
// night = true,
|
|
||||||
// onClickBack = ::goBack
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ package helium314.keyboard.settings.dialogs
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
|
@ -17,21 +17,19 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Paint
|
||||||
|
import androidx.compose.ui.graphics.PaintingStyle
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
|
import androidx.compose.ui.text.TextRange
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.github.skydoves.colorpicker.compose.AlphaSlider
|
import com.github.skydoves.colorpicker.compose.AlphaSlider
|
||||||
import com.github.skydoves.colorpicker.compose.BrightnessSlider
|
import com.github.skydoves.colorpicker.compose.BrightnessSlider
|
||||||
import com.github.skydoves.colorpicker.compose.ColorEnvelope
|
|
||||||
import com.github.skydoves.colorpicker.compose.HsvColorPicker
|
import com.github.skydoves.colorpicker.compose.HsvColorPicker
|
||||||
import com.github.skydoves.colorpicker.compose.rememberColorPickerController
|
import com.github.skydoves.colorpicker.compose.rememberColorPickerController
|
||||||
|
|
||||||
// todo:
|
|
||||||
// setting from text doesn't work
|
|
||||||
// weird effect on start, did this start with the top row showing colors?
|
|
||||||
// text field doesn't look nice
|
|
||||||
// for initial color picks performance is not good
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ColorPickerDialog(
|
fun ColorPickerDialog(
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
|
@ -40,8 +38,17 @@ fun ColorPickerDialog(
|
||||||
onConfirmed: (Int) -> Unit,
|
onConfirmed: (Int) -> Unit,
|
||||||
) {
|
) {
|
||||||
val controller = rememberColorPickerController()
|
val controller = rememberColorPickerController()
|
||||||
|
val wheelPaint = Paint().apply {
|
||||||
|
alpha = 0.5f
|
||||||
|
style = PaintingStyle.Stroke
|
||||||
|
strokeWidth = 5f
|
||||||
|
color = Color.White
|
||||||
|
}
|
||||||
|
controller.wheelPaint = wheelPaint
|
||||||
val barHeight = 35.dp
|
val barHeight = 35.dp
|
||||||
var value by remember { mutableStateOf(TextFieldValue(initialColor.toString(16))) }
|
val initialString = initialColor.toUInt().toString(16)
|
||||||
|
var textValue by remember { mutableStateOf(TextFieldValue(initialString, TextRange(initialString.length))) }
|
||||||
|
var currentColor by remember { mutableStateOf(Color(initialColor)) }
|
||||||
ThreeButtonAlertDialog(
|
ThreeButtonAlertDialog(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
onConfirmed = { onConfirmed(controller.selectedColor.value.toArgb()) },
|
onConfirmed = { onConfirmed(controller.selectedColor.value.toArgb()) },
|
||||||
|
@ -56,7 +63,7 @@ fun ColorPickerDialog(
|
||||||
.height(barHeight))
|
.height(barHeight))
|
||||||
{ }
|
{ }
|
||||||
Surface(
|
Surface(
|
||||||
color = controller.selectedColor.value,
|
color = currentColor,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
.padding(end = 10.dp)
|
.padding(end = 10.dp)
|
||||||
.height(barHeight))
|
.height(barHeight))
|
||||||
|
@ -65,13 +72,15 @@ fun ColorPickerDialog(
|
||||||
HsvColorPicker(
|
HsvColorPicker(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.fillMaxHeight(0.6f)
|
.height(300.dp)
|
||||||
.padding(10.dp),
|
.padding(10.dp),
|
||||||
controller = controller,
|
controller = controller,
|
||||||
onColorChanged = { colorEnvelope: ColorEnvelope ->
|
onColorChanged = {
|
||||||
value = TextFieldValue(colorEnvelope.hexCode)
|
if (it.fromUser)
|
||||||
|
textValue = TextFieldValue(it.hexCode, selection = TextRange(it.hexCode.length))
|
||||||
|
currentColor = it.color
|
||||||
},
|
},
|
||||||
initialColor = Color(initialColor)
|
initialColor = Color(initialColor),
|
||||||
)
|
)
|
||||||
AlphaSlider(
|
AlphaSlider(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -79,6 +88,8 @@ fun ColorPickerDialog(
|
||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
.height(barHeight),
|
.height(barHeight),
|
||||||
controller = controller,
|
controller = controller,
|
||||||
|
initialColor = Color(initialColor),
|
||||||
|
wheelPaint = wheelPaint
|
||||||
)
|
)
|
||||||
BrightnessSlider(
|
BrightnessSlider(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -86,13 +97,18 @@ fun ColorPickerDialog(
|
||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
.height(barHeight),
|
.height(barHeight),
|
||||||
controller = controller,
|
controller = controller,
|
||||||
|
initialColor = Color(initialColor),
|
||||||
|
wheelPaint = wheelPaint
|
||||||
)
|
)
|
||||||
TextField(
|
TextField(
|
||||||
value = value,
|
value = textValue,
|
||||||
|
// KeyboardType.Password is a crappy way of avoiding suggestions... is there really no way in compose?
|
||||||
|
keyboardOptions = KeyboardOptions(autoCorrectEnabled = false, keyboardType = KeyboardType.Password),
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
val androidColor = kotlin.runCatching { android.graphics.Color.parseColor("#$it") }.getOrNull()
|
textValue = it
|
||||||
|
val androidColor = kotlin.runCatching { android.graphics.Color.parseColor("#${it.text}") }.getOrNull()
|
||||||
if (androidColor != null)
|
if (androidColor != null)
|
||||||
controller.selectByColor(Color(androidColor), true)
|
controller.selectByColor(Color(androidColor), false)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -103,5 +119,5 @@ fun ColorPickerDialog(
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun Preview() {
|
private fun Preview() {
|
||||||
ColorPickerDialog({}, android.graphics.Color.MAGENTA, "color name", {})
|
ColorPickerDialog({}, -0x0f4488aa, "color name", {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
package helium314.keyboard.settings.dialogs
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.LocalTextStyle
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.RadioButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import helium314.keyboard.keyboard.KeyboardTheme
|
||||||
|
import helium314.keyboard.latin.R
|
||||||
|
import helium314.keyboard.latin.settings.Settings
|
||||||
|
import helium314.keyboard.latin.utils.getStringResourceOrName
|
||||||
|
import helium314.keyboard.latin.utils.prefs
|
||||||
|
import helium314.keyboard.settings.Setting
|
||||||
|
import helium314.keyboard.settings.SettingsDestination
|
||||||
|
import helium314.keyboard.settings.keyboardNeedsReload
|
||||||
|
|
||||||
|
// specialized variant of ListPickerDialog
|
||||||
|
@Composable
|
||||||
|
fun ColorThemePickerDialog(
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
setting: Setting,
|
||||||
|
isNight: Boolean,
|
||||||
|
default: String
|
||||||
|
) {
|
||||||
|
val ctx = LocalContext.current
|
||||||
|
val prefs = ctx.prefs()
|
||||||
|
val defaultColors = KeyboardTheme.getAvailableDefaultColors(prefs, false)
|
||||||
|
|
||||||
|
// prefs.all is null in preview only
|
||||||
|
val userColors = (prefs.all ?: mapOf(Settings.PREF_USER_COLORS_PREFIX + "usercolor" to "") ).keys.mapNotNull {
|
||||||
|
when {
|
||||||
|
it.startsWith(Settings.PREF_USER_COLORS_PREFIX) -> it.substringAfter(Settings.PREF_USER_COLORS_PREFIX)
|
||||||
|
it.startsWith(Settings.PREF_USER_ALL_COLORS_PREFIX) -> it.substringAfter(Settings.PREF_USER_ALL_COLORS_PREFIX)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}.toSortedSet() // we don't want duplicates, and we want a consistent order
|
||||||
|
val selectedColor = prefs.getString(setting.key, default)!!
|
||||||
|
if (selectedColor !in defaultColors)
|
||||||
|
userColors.add(selectedColor) // there are cases where we have no settings for a user theme
|
||||||
|
|
||||||
|
val colors = defaultColors + userColors + ""
|
||||||
|
val state = rememberLazyListState()
|
||||||
|
LaunchedEffect(selectedColor) {
|
||||||
|
val index = colors.indexOf(selectedColor)
|
||||||
|
if (index != -1) state.scrollToItem(index, -state.layoutInfo.viewportSize.height / 3)
|
||||||
|
}
|
||||||
|
ThreeButtonAlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
cancelButtonText = stringResource(R.string.dialog_close),
|
||||||
|
onConfirmed = { },
|
||||||
|
confirmButtonText = null,
|
||||||
|
// neutralButtonText = stringResource(R.string.load),
|
||||||
|
onNeutral = {
|
||||||
|
// todo: launcher to select file
|
||||||
|
// when importing make sure name is not in use
|
||||||
|
},
|
||||||
|
title = { Text(setting.title) },
|
||||||
|
text = {
|
||||||
|
CompositionLocalProvider(
|
||||||
|
LocalTextStyle provides MaterialTheme.typography.bodyLarge
|
||||||
|
) {
|
||||||
|
LazyColumn(state = state) {
|
||||||
|
items(colors) { item ->
|
||||||
|
if (item == "") {
|
||||||
|
var textValue by remember { mutableStateOf(TextFieldValue()) }
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
Icon(painterResource(R.drawable.ic_plus), stringResource(R.string.add)) // todo: should it be a button?
|
||||||
|
TextField(
|
||||||
|
value = textValue,
|
||||||
|
onValueChange = { textValue = it },
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
singleLine = true
|
||||||
|
)
|
||||||
|
IconButton(
|
||||||
|
enabled = textValue.text.isNotEmpty() && textValue.text !in userColors,
|
||||||
|
onClick = {
|
||||||
|
onDismissRequest()
|
||||||
|
prefs.edit().putString(setting.key, textValue.text).apply()
|
||||||
|
if (isNight) SettingsDestination.navigateTo(SettingsDestination.ColorsNight)
|
||||||
|
else SettingsDestination.navigateTo(SettingsDestination.Colors)
|
||||||
|
keyboardNeedsReload = true
|
||||||
|
}
|
||||||
|
) { Icon(painterResource(R.drawable.ic_edit), null) }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable {
|
||||||
|
onDismissRequest()
|
||||||
|
prefs.edit().putString(setting.key, item).apply()
|
||||||
|
keyboardNeedsReload = true
|
||||||
|
}
|
||||||
|
.padding(start = 6.dp)
|
||||||
|
.heightIn(min = 40.dp)
|
||||||
|
) {
|
||||||
|
RadioButton(
|
||||||
|
selected = selectedColor == item,
|
||||||
|
onClick = {
|
||||||
|
onDismissRequest()
|
||||||
|
prefs.edit().putString(setting.key, item).apply()
|
||||||
|
keyboardNeedsReload = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = item.getStringResourceOrName("theme_name_", ctx),
|
||||||
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
)
|
||||||
|
if (item in userColors) {
|
||||||
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
IconButton(
|
||||||
|
onClick = { showDialog = true }
|
||||||
|
) { Icon(painterResource(R.drawable.ic_bin), null) }
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
onDismissRequest()
|
||||||
|
prefs.edit().putString(setting.key, item).apply()
|
||||||
|
if (isNight) SettingsDestination.navigateTo(SettingsDestination.ColorsNight)
|
||||||
|
else SettingsDestination.navigateTo(SettingsDestination.Colors)
|
||||||
|
keyboardNeedsReload = true
|
||||||
|
}
|
||||||
|
) { Icon(painterResource(R.drawable.ic_edit), null) }
|
||||||
|
if (showDialog)
|
||||||
|
ConfirmationDialog(
|
||||||
|
onDismissRequest = { showDialog = false },
|
||||||
|
text = { Text(stringResource(R.string.delete_confirmation, item)) },
|
||||||
|
onConfirmed = {
|
||||||
|
onDismissRequest()
|
||||||
|
prefs.edit().remove(Settings.PREF_USER_COLORS_PREFIX + item)
|
||||||
|
.remove(Settings.PREF_USER_ALL_COLORS_PREFIX + item)
|
||||||
|
.remove(Settings.PREF_USER_MORE_COLORS_PREFIX + item).apply()
|
||||||
|
if (item == selectedColor)
|
||||||
|
prefs.edit().remove(setting.key).apply()
|
||||||
|
keyboardNeedsReload = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun PreviewListPickerDialog() {
|
||||||
|
ColorThemePickerDialog(
|
||||||
|
onDismissRequest = {},
|
||||||
|
setting = Setting(LocalContext.current, "", R.string.settings) {},
|
||||||
|
default = "dark",
|
||||||
|
isNight = true
|
||||||
|
)
|
||||||
|
}
|
|
@ -86,7 +86,6 @@ fun <T: Any> ListPickerDialog(
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = getItemName(item),
|
text = getItemName(item),
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,12 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import helium314.keyboard.keyboard.KeyboardSwitcher
|
import helium314.keyboard.keyboard.KeyboardSwitcher
|
||||||
import helium314.keyboard.keyboard.KeyboardTheme
|
import helium314.keyboard.keyboard.KeyboardTheme
|
||||||
import helium314.keyboard.latin.R
|
import helium314.keyboard.latin.R
|
||||||
import helium314.keyboard.latin.settings.ColorsNightSettingsFragment
|
|
||||||
import helium314.keyboard.latin.settings.ColorsSettingsFragment
|
|
||||||
import helium314.keyboard.latin.settings.Defaults
|
import helium314.keyboard.latin.settings.Defaults
|
||||||
import helium314.keyboard.latin.settings.Settings
|
import helium314.keyboard.latin.settings.Settings
|
||||||
import helium314.keyboard.latin.utils.Log
|
import helium314.keyboard.latin.utils.Log
|
||||||
import helium314.keyboard.latin.utils.getActivity
|
import helium314.keyboard.latin.utils.getActivity
|
||||||
import helium314.keyboard.latin.utils.getStringResourceOrName
|
import helium314.keyboard.latin.utils.getStringResourceOrName
|
||||||
import helium314.keyboard.latin.utils.prefs
|
import helium314.keyboard.latin.utils.prefs
|
||||||
import helium314.keyboard.latin.utils.switchTo
|
|
||||||
import helium314.keyboard.settings.SettingsContainer
|
import helium314.keyboard.settings.SettingsContainer
|
||||||
import helium314.keyboard.settings.preferences.ListPreference
|
import helium314.keyboard.settings.preferences.ListPreference
|
||||||
import helium314.keyboard.settings.SettingsWithoutKey
|
import helium314.keyboard.settings.SettingsWithoutKey
|
||||||
|
@ -36,6 +33,7 @@ import helium314.keyboard.settings.SettingsActivity
|
||||||
import helium314.keyboard.settings.preferences.SliderPreference
|
import helium314.keyboard.settings.preferences.SliderPreference
|
||||||
import helium314.keyboard.settings.preferences.SwitchPreference
|
import helium314.keyboard.settings.preferences.SwitchPreference
|
||||||
import helium314.keyboard.settings.Theme
|
import helium314.keyboard.settings.Theme
|
||||||
|
import helium314.keyboard.settings.dialogs.ColorThemePickerDialog
|
||||||
import helium314.keyboard.settings.dialogs.CustomizeIconsDialog
|
import helium314.keyboard.settings.dialogs.CustomizeIconsDialog
|
||||||
import helium314.keyboard.settings.dialogs.TextInputDialog
|
import helium314.keyboard.settings.dialogs.TextInputDialog
|
||||||
import helium314.keyboard.settings.keyboardNeedsReload
|
import helium314.keyboard.settings.keyboardNeedsReload
|
||||||
|
@ -58,14 +56,10 @@ fun AppearanceScreen(
|
||||||
Settings.PREF_ICON_STYLE,
|
Settings.PREF_ICON_STYLE,
|
||||||
Settings.PREF_CUSTOM_ICON_NAMES,
|
Settings.PREF_CUSTOM_ICON_NAMES,
|
||||||
Settings.PREF_THEME_COLORS,
|
Settings.PREF_THEME_COLORS,
|
||||||
// if (prefs.getString(Settings.PREF_THEME_COLORS, Defaults.PREF_THEME_COLORS) == KeyboardTheme.THEME_USER)
|
|
||||||
// SettingsWithoutKey.ADJUST_COLORS else null, // todo: remove, this should be part of the color selection menu
|
|
||||||
Settings.PREF_THEME_KEY_BORDERS,
|
Settings.PREF_THEME_KEY_BORDERS,
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
||||||
Settings.PREF_THEME_DAY_NIGHT else null,
|
Settings.PREF_THEME_DAY_NIGHT else null,
|
||||||
if (dayNightMode) Settings.PREF_THEME_COLORS_NIGHT else null,
|
if (dayNightMode) Settings.PREF_THEME_COLORS_NIGHT else null,
|
||||||
// if (dayNightMode && prefs.getString(Settings.PREF_THEME_COLORS_NIGHT, Defaults.PREF_THEME_COLORS_NIGHT) == KeyboardTheme.THEME_USER_NIGHT)
|
|
||||||
// SettingsWithoutKey.ADJUST_COLORS_NIGHT else null, // todo: remove, this should be part of the color selection menu
|
|
||||||
Settings.PREF_NAVBAR_COLOR,
|
Settings.PREF_NAVBAR_COLOR,
|
||||||
SettingsWithoutKey.BACKGROUND_IMAGE,
|
SettingsWithoutKey.BACKGROUND_IMAGE,
|
||||||
SettingsWithoutKey.BACKGROUND_IMAGE_LANDSCAPE,
|
SettingsWithoutKey.BACKGROUND_IMAGE_LANDSCAPE,
|
||||||
|
@ -139,54 +133,44 @@ fun createAppearanceSettings(context: Context) = listOf(
|
||||||
},
|
},
|
||||||
Setting(context, Settings.PREF_THEME_COLORS, R.string.theme_colors) { setting ->
|
Setting(context, Settings.PREF_THEME_COLORS, R.string.theme_colors) { setting ->
|
||||||
val ctx = LocalContext.current
|
val ctx = LocalContext.current
|
||||||
|
val prefs = ctx.prefs()
|
||||||
val b = (ctx.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState()
|
val b = (ctx.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState()
|
||||||
if ((b?.value ?: 0) < 0)
|
if ((b?.value ?: 0) < 0)
|
||||||
Log.v("irrelevant", "stupid way to trigger recomposition on preference change")
|
Log.v("irrelevant", "stupid way to trigger recomposition on preference change")
|
||||||
val items = KeyboardTheme.getAvailableColors(ctx.prefs(), false).map {
|
var showDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
it.getStringResourceOrName("theme_name_", ctx) to it
|
Preference(
|
||||||
}
|
name = setting.title,
|
||||||
ListPreference(
|
description = prefs.getString(setting.key, Defaults.PREF_THEME_COLORS)!!.getStringResourceOrName("theme_name_", ctx),
|
||||||
setting,
|
onClick = { showDialog = true }
|
||||||
items,
|
)
|
||||||
Defaults.PREF_THEME_COLORS
|
if (showDialog)
|
||||||
) { keyboardNeedsReload = true }
|
ColorThemePickerDialog(
|
||||||
|
onDismissRequest = { showDialog = false },
|
||||||
|
setting = setting,
|
||||||
|
isNight = false,
|
||||||
|
default = Defaults.PREF_THEME_COLORS
|
||||||
|
)
|
||||||
},
|
},
|
||||||
Setting(context, Settings.PREF_THEME_COLORS_NIGHT, R.string.theme_colors_night) { setting ->
|
Setting(context, Settings.PREF_THEME_COLORS_NIGHT, R.string.theme_colors_night) { setting ->
|
||||||
val ctx = LocalContext.current
|
val ctx = LocalContext.current
|
||||||
val b = (ctx.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState()
|
val b = (ctx.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState()
|
||||||
|
val prefs = ctx.prefs()
|
||||||
if ((b?.value ?: 0) < 0)
|
if ((b?.value ?: 0) < 0)
|
||||||
Log.v("irrelevant", "stupid way to trigger recomposition on preference change")
|
Log.v("irrelevant", "stupid way to trigger recomposition on preference change")
|
||||||
val items = KeyboardTheme.getAvailableColors(ctx.prefs(), true).map {
|
var showDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
it.getStringResourceOrName("theme_name_", ctx) to it
|
|
||||||
}
|
|
||||||
ListPreference(
|
|
||||||
setting,
|
|
||||||
items,
|
|
||||||
Defaults.PREF_THEME_COLORS_NIGHT
|
|
||||||
) { keyboardNeedsReload = true }
|
|
||||||
},
|
|
||||||
/* Setting(context, SettingsWithoutKey.ADJUST_COLORS, R.string.select_user_colors, R.string.select_user_colors_summary) {
|
|
||||||
val ctx = LocalContext.current
|
|
||||||
Preference(
|
Preference(
|
||||||
name = it.title,
|
name = setting.title,
|
||||||
description = it.description,
|
description = prefs.getString(setting.key, Defaults.PREF_THEME_COLORS_NIGHT)!!.getStringResourceOrName("theme_name_", ctx),
|
||||||
onClick = {
|
onClick = { showDialog = true }
|
||||||
ctx.getActivity()?.switchTo(ColorsSettingsFragment())
|
|
||||||
//SettingsDestination.navigateTo(SettingsDestination.Colors) todo: soon
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
if (showDialog)
|
||||||
|
ColorThemePickerDialog(
|
||||||
|
onDismissRequest = { showDialog = false },
|
||||||
|
setting = setting,
|
||||||
|
isNight = true,
|
||||||
|
default = Defaults.PREF_THEME_COLORS_NIGHT
|
||||||
|
)
|
||||||
},
|
},
|
||||||
Setting(context, SettingsWithoutKey.ADJUST_COLORS_NIGHT, R.string.select_user_colors_night, R.string.select_user_colors_summary) {
|
|
||||||
val ctx = LocalContext.current
|
|
||||||
Preference(
|
|
||||||
name = it.title,
|
|
||||||
description = it.description,
|
|
||||||
onClick = {
|
|
||||||
ctx.getActivity()?.switchTo(ColorsNightSettingsFragment())
|
|
||||||
//SettingsDestination.navigateTo(SettingsDestination.ColorsNight) todo: soon
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},*/
|
|
||||||
Setting(context, Settings.PREF_THEME_KEY_BORDERS, R.string.key_borders) {
|
Setting(context, Settings.PREF_THEME_KEY_BORDERS, R.string.key_borders) {
|
||||||
SwitchPreference(it, Defaults.PREF_THEME_KEY_BORDERS)
|
SwitchPreference(it, Defaults.PREF_THEME_KEY_BORDERS)
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,34 +1,161 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
package helium314.keyboard.settings.screens
|
package helium314.keyboard.settings.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.material3.LocalContentColor
|
||||||
|
import androidx.compose.material3.LocalTextStyle
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Switch
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import helium314.keyboard.keyboard.ColorSetting
|
||||||
|
import helium314.keyboard.keyboard.KeyboardTheme
|
||||||
import helium314.keyboard.latin.R
|
import helium314.keyboard.latin.R
|
||||||
|
import helium314.keyboard.latin.common.ColorType
|
||||||
|
import helium314.keyboard.latin.common.default
|
||||||
|
import helium314.keyboard.latin.settings.Defaults
|
||||||
|
import helium314.keyboard.latin.settings.Settings
|
||||||
|
import helium314.keyboard.latin.settings.colorPrefsAndResIds
|
||||||
|
import helium314.keyboard.latin.settings.getColorPrefsToHideInitially
|
||||||
|
import helium314.keyboard.latin.utils.Log
|
||||||
|
import helium314.keyboard.latin.utils.getActivity
|
||||||
|
import helium314.keyboard.latin.utils.prefs
|
||||||
import helium314.keyboard.settings.SearchScreen
|
import helium314.keyboard.settings.SearchScreen
|
||||||
|
import helium314.keyboard.settings.SettingsActivity
|
||||||
|
import helium314.keyboard.settings.Theme
|
||||||
|
import helium314.keyboard.settings.dialogs.ColorPickerDialog
|
||||||
|
import helium314.keyboard.settings.keyboardNeedsReload
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ColorsScreen(
|
fun ColorsScreen(
|
||||||
night: Boolean,
|
isNight: Boolean,
|
||||||
onClickBack: () -> Unit
|
onClickBack: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
// todo:
|
||||||
|
// allow switching moreColors (three dot menu? dropdown / spinner for visibility?)
|
||||||
|
// allow save (load should be in theme selector, maybe here too)
|
||||||
|
// import/export should now also store theme name
|
||||||
|
// handle name collisions on load by simply appending a number
|
||||||
|
// allow editing theme name
|
||||||
|
// make sure import of old colors works
|
||||||
|
|
||||||
var availableColors by remember { mutableStateOf(emptyList<ColorSetting>()) } // todo (later): type?
|
val ctx = LocalContext.current
|
||||||
// todo (later): save / load / type selection here? or in ... menu as previously?
|
val prefs = ctx.prefs()
|
||||||
|
val b = (ctx.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState()
|
||||||
|
if ((b?.value ?: 0) < 0)
|
||||||
|
Log.v("irrelevant", "stupid way to trigger recomposition on preference change")
|
||||||
|
|
||||||
|
val themeName = if (isNight) prefs.getString(Settings.PREF_THEME_COLORS_NIGHT, Defaults.PREF_THEME_COLORS_NIGHT)!!
|
||||||
|
else prefs.getString(Settings.PREF_THEME_COLORS, Defaults.PREF_THEME_COLORS)!!
|
||||||
|
val moreColors = KeyboardTheme.readUserMoreColors(prefs, themeName)
|
||||||
|
val userColors = KeyboardTheme.readUserColors(prefs, themeName)
|
||||||
|
val shownColors = if (moreColors == 2) {
|
||||||
|
val allColors = KeyboardTheme.readUserAllColors(prefs, themeName)
|
||||||
|
ColorType.entries.map {
|
||||||
|
ColorSetting(it.name, null, allColors[it] ?: it.default())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val toDisplay = colorPrefsAndResIds.map { (colorName, resId) ->
|
||||||
|
val cs = userColors.firstOrNull { it.name == colorName } ?: ColorSetting(colorName, true, null)
|
||||||
|
cs.displayName = stringResource(resId)
|
||||||
|
cs
|
||||||
|
}
|
||||||
|
val colorsToHide = getColorPrefsToHideInitially(prefs)
|
||||||
|
if (moreColors == 1) toDisplay
|
||||||
|
else toDisplay.filter { it.color != null || it.name !in colorsToHide }
|
||||||
|
}
|
||||||
|
fun ColorSetting.displayColor() = if (auto == true) KeyboardTheme.determineUserColor(userColors, ctx, name, isNight)
|
||||||
|
else color ?: KeyboardTheme.determineUserColor(userColors, ctx, name, isNight)
|
||||||
|
|
||||||
|
var chosenColor: ColorSetting? by remember { mutableStateOf(null) }
|
||||||
SearchScreen(
|
SearchScreen(
|
||||||
title = stringResource(if (night) R.string.select_user_colors_night else R.string.select_user_colors),
|
title = themeName,
|
||||||
onClickBack = onClickBack,
|
onClickBack = onClickBack,
|
||||||
filteredItems = { search -> availableColors.filter { it.displayName.contains(search, true) } },
|
filteredItems = { search -> shownColors.filter {
|
||||||
itemContent = { }
|
it.displayName.split(" ", "_").any { it.startsWith(search, true) }
|
||||||
|
} },
|
||||||
|
itemContent = { colorSetting ->
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
.clickable { chosenColor = colorSetting }
|
||||||
|
) {
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(Color(colorSetting.displayColor()), shape = CircleShape)
|
||||||
|
.size(50.dp)
|
||||||
|
)
|
||||||
|
Column(Modifier.weight(1f).padding(horizontal = 16.dp)) {
|
||||||
|
Text(colorSetting.displayName)
|
||||||
|
if (colorSetting.auto == true)
|
||||||
|
CompositionLocalProvider(
|
||||||
|
LocalTextStyle provides MaterialTheme.typography.bodyMedium,
|
||||||
|
LocalContentColor provides MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.auto_user_color))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (colorSetting.auto != null)
|
||||||
|
Switch(colorSetting.auto, onCheckedChange = {
|
||||||
|
val oldUserColors = KeyboardTheme.readUserColors(prefs, themeName)
|
||||||
|
val newUserColors = (oldUserColors + ColorSetting(colorSetting.name, it, colorSetting.color))
|
||||||
|
.reversed().distinctBy { it.displayName }
|
||||||
|
KeyboardTheme.writeUserColors(prefs, themeName, newUserColors)
|
||||||
|
keyboardNeedsReload = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
if (chosenColor != null) {
|
||||||
|
val color = chosenColor!!
|
||||||
|
ColorPickerDialog(
|
||||||
|
onDismissRequest = { chosenColor = null },
|
||||||
|
initialColor = color.displayColor(),
|
||||||
|
title = color.displayName,
|
||||||
|
) {
|
||||||
|
if (moreColors == 2) {
|
||||||
|
val oldColors = KeyboardTheme.readUserAllColors(prefs, themeName)
|
||||||
|
oldColors[ColorType.valueOf(color.name)] = it
|
||||||
|
KeyboardTheme.writeUserAllColors(prefs, themeName, oldColors)
|
||||||
|
} else {
|
||||||
|
val oldUserColors = KeyboardTheme.readUserColors(prefs, themeName)
|
||||||
|
val newUserColors = (oldUserColors + ColorSetting(color.name, false, it))
|
||||||
|
.reversed().distinctBy { it.displayName }
|
||||||
|
KeyboardTheme.writeUserColors(prefs, themeName, newUserColors)
|
||||||
|
}
|
||||||
|
keyboardNeedsReload = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ColorSetting(
|
@Preview
|
||||||
val key: String, // old, this should go away
|
@Composable
|
||||||
val displayName: String,
|
private fun Preview() {
|
||||||
var auto: Boolean, // not for all
|
Theme(true) {
|
||||||
var color: Int
|
Surface {
|
||||||
)
|
ColorsScreen(false) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:src="@drawable/ic_user_dictionary_edit"
|
android:src="@drawable/ic_edit"
|
||||||
android:contentDescription="@null">
|
android:contentDescription="@null">
|
||||||
</ImageView>
|
</ImageView>
|
||||||
|
|
||||||
|
|
|
@ -987,4 +987,6 @@ New dictionary:
|
||||||
<string name="customize_icons">Customize icons</string>
|
<string name="customize_icons">Customize icons</string>
|
||||||
<!-- Confirmation message when resetting all custom icons -->
|
<!-- Confirmation message when resetting all custom icons -->
|
||||||
<string name="customize_icons_reset_message">Really reset all customized icons?</string>
|
<string name="customize_icons_reset_message">Really reset all customized icons?</string>
|
||||||
|
<!-- Confirmation message when deleting a something (used for custom colors) -->
|
||||||
|
<string name="delete_confirmation">Really delete %s?</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Reference in a new issue