Add theme color customization on Settings
This commit is contained in:
parent
323dec9e78
commit
c06053c5dc
6 changed files with 219 additions and 58 deletions
|
|
@ -1,15 +1,18 @@
|
||||||
package mg.dot.feufaro.midi
|
package mg.dot.feufaro.midi
|
||||||
|
|
||||||
import SharedScreenModel
|
import SharedScreenModel
|
||||||
|
import com.russhwolf.settings.Settings
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import org.billthefarmer.mididriver.MidiDriver
|
import org.billthefarmer.mididriver.MidiDriver
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
import org.koin.core.component.inject
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.RandomAccessFile
|
import java.io.RandomAccessFile
|
||||||
|
|
||||||
actual class FMediaPlayer actual constructor(
|
actual class FMediaPlayer actual constructor(
|
||||||
private val filename: String,
|
private val filename: String,
|
||||||
private val onFinished: () -> Unit
|
private val onFinished: () -> Unit
|
||||||
) {
|
): KoinComponent {
|
||||||
private data class MidiEvent(
|
private data class MidiEvent(
|
||||||
val tickAbsolute: Long,
|
val tickAbsolute: Long,
|
||||||
val type: Int,
|
val type: Int,
|
||||||
|
|
@ -137,6 +140,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
private var syncJob: Job? = null
|
private var syncJob: Job? = null
|
||||||
private var dynamicJob: Job? = null
|
private var dynamicJob: Job? = null
|
||||||
private var boundModel: SharedScreenModel? = null
|
private var boundModel: SharedScreenModel? = null
|
||||||
|
private val settings: Settings by inject()
|
||||||
|
|
||||||
private data class NavigationStep(
|
private data class NavigationStep(
|
||||||
val marker: String,
|
val marker: String,
|
||||||
|
|
@ -162,6 +166,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
midiDriver.start()
|
midiDriver.start()
|
||||||
|
loadVoiceVolumes()
|
||||||
val file = File(filename)
|
val file = File(filename)
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -698,8 +703,27 @@ actual class FMediaPlayer actual constructor(
|
||||||
actual fun clearLoop() { isLoopingAB = false; pointA = -1L; pointB = -1L }
|
actual fun clearLoop() { isLoopingAB = false; pointA = -1L; pointB = -1L }
|
||||||
actual fun getLoopState() = Triple(pointA, pointB, isLoopingAB)
|
actual fun getLoopState() = Triple(pointA, pointB, isLoopingAB)
|
||||||
actual fun toggleVoice(index: Int) { applyVoiceStates() }
|
actual fun toggleVoice(index: Int) { applyVoiceStates() }
|
||||||
|
private fun saveVoicesVolumes() {
|
||||||
|
val data = voiceVolumes.joinToString(",")
|
||||||
|
settings.putString("voices_volumes", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadVoiceVolumes() {
|
||||||
|
val data = settings.getString("voices_volumes", "127,127,127,127")
|
||||||
|
val volumesArray = data.split(",")
|
||||||
|
|
||||||
|
if (volumesArray.size == 4) {
|
||||||
|
for (i in 0 until 4) {
|
||||||
|
voiceVolumes[i] = volumesArray[i].toFloatOrNull() ?: 127f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
actual fun updateVoiceVolume(voiceIndex: Int, newVolume: Float) {
|
actual fun updateVoiceVolume(voiceIndex: Int, newVolume: Float) {
|
||||||
if (voiceIndex in 0..3) { voiceVolumes[voiceIndex] = newVolume; applyVoiceStates() }
|
if (voiceIndex in 0..3) {
|
||||||
|
voiceVolumes[voiceIndex] = newVolume;
|
||||||
|
saveVoicesVolumes()
|
||||||
|
applyVoiceStates()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
actual fun getVoiceVolumes(): List<Float> = voiceVolumes.toList()
|
actual fun getVoiceVolumes(): List<Float> = voiceVolumes.toList()
|
||||||
actual fun changeInstru(noInstru: Int) {
|
actual fun changeInstru(noInstru: Int) {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ fun App() {
|
||||||
val displayConfigManager = koinInject<DisplayConfigManager>()
|
val displayConfigManager = koinInject<DisplayConfigManager>()
|
||||||
val currentDisplayConfig by displayConfigManager.displayConfig.collectAsState()
|
val currentDisplayConfig by displayConfigManager.displayConfig.collectAsState()
|
||||||
|
|
||||||
FeufaroTheme(themeModeSelected = currentDisplayConfig.themeMode, userFontSize = currentDisplayConfig.fontSize) {
|
FeufaroTheme(config = currentDisplayConfig) {
|
||||||
Navigator(screen = ScreenSolfa) {
|
Navigator(screen = ScreenSolfa) {
|
||||||
CurrentScreen()
|
CurrentScreen()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import kotlinx.serialization.json.Json
|
||||||
import mg.dot.feufaro.config.AppConfigJson
|
import mg.dot.feufaro.config.AppConfigJson
|
||||||
import mg.dot.feufaro.config.DisplayConfig
|
import mg.dot.feufaro.config.DisplayConfig
|
||||||
import java.util.prefs.Preferences
|
import java.util.prefs.Preferences
|
||||||
|
import com.russhwolf.settings.Settings
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AppConfigJson(
|
data class AppConfigJson(
|
||||||
|
|
@ -35,10 +36,10 @@ fun AppConfigJson.toDisplayConfig(defaultConfig: DisplayConfig): DisplayConfig {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
class DisplayConfigManager(
|
class DisplayConfigManager(
|
||||||
private val fileRepository: FileRepository
|
private val fileRepository: FileRepository,
|
||||||
|
private val settings: Settings
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
private val prefs = Preferences.userRoot().node("mg.dot.feufaro")
|
|
||||||
private val _displayConfig = MutableStateFlow(DisplayConfig())
|
private val _displayConfig = MutableStateFlow(DisplayConfig())
|
||||||
val displayConfig: StateFlow<DisplayConfig> = _displayConfig.asStateFlow()
|
val displayConfig: StateFlow<DisplayConfig> = _displayConfig.asStateFlow()
|
||||||
private val configScope = CoroutineScope(Dispatchers.Default)
|
private val configScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
|
@ -52,15 +53,35 @@ class DisplayConfigManager(
|
||||||
loadConfigFromFile("assets://config.json")
|
loadConfigFromFile("assets://config.json")
|
||||||
|
|
||||||
val jsonConfig = _displayConfig.value
|
val jsonConfig = _displayConfig.value
|
||||||
val finalTheme = prefs.get("themeMode", jsonConfig.themeMode)
|
val finalTheme = settings.getString("themeMode", jsonConfig.themeMode)
|
||||||
val finalFontSize = prefs.getFloat("fontSize", jsonConfig.fontSize)
|
val finalFontSize = settings.getFloat("fontSize", jsonConfig.fontSize)
|
||||||
|
|
||||||
|
val pBlue = settings.getString("primaryBlueHex", jsonConfig.primaryBlueHex)
|
||||||
|
val aYellow = settings.getString("accentYellowHex", jsonConfig.accentYellowHex)
|
||||||
|
val aGreen = settings.getString("accentGreenHex", jsonConfig.accentGreenHex)
|
||||||
|
val aPink = settings.getString("accentPinkHex", jsonConfig.accentPinkHex)
|
||||||
|
|
||||||
_displayConfig.value = jsonConfig.copy(
|
_displayConfig.value = jsonConfig.copy(
|
||||||
themeMode = finalTheme,
|
themeMode = finalTheme,
|
||||||
fontSize = finalFontSize
|
fontSize = finalFontSize,
|
||||||
|
primaryBlueHex = pBlue,
|
||||||
|
accentYellowHex = aYellow,
|
||||||
|
accentGreenHex = aGreen,
|
||||||
|
accentPinkHex = aPink
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun updateCustomColor(key: String, hexValue: String) {
|
||||||
|
settings.putString(key, hexValue)
|
||||||
|
|
||||||
|
_displayConfig.value = when(key) {
|
||||||
|
"primaryBlueHex" -> _displayConfig.value.copy(primaryBlueHex = hexValue)
|
||||||
|
"accentYellowHex" -> _displayConfig.value.copy(accentYellowHex = hexValue)
|
||||||
|
"accentGreenHex" -> _displayConfig.value.copy(accentGreenHex = hexValue)
|
||||||
|
"accentPinkHex" -> _displayConfig.value.copy(accentPinkHex = hexValue)
|
||||||
|
else -> _displayConfig.value
|
||||||
|
}
|
||||||
|
}
|
||||||
suspend fun loadConfigFromFile(filePath: String) {
|
suspend fun loadConfigFromFile(filePath: String) {
|
||||||
try {
|
try {
|
||||||
val jsonString = fileRepository.readFileContent(filePath)
|
val jsonString = fileRepository.readFileContent(filePath)
|
||||||
|
|
@ -74,22 +95,23 @@ class DisplayConfigManager(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateThemeMode(themeMode: String) {
|
fun updateThemeMode(themeMode: String) {
|
||||||
prefs.put("themeMode", themeMode)
|
settings.putString("themeMode", themeMode)
|
||||||
prefs.flush()
|
|
||||||
_displayConfig.value = _displayConfig.value.copy(themeMode = themeMode)
|
_displayConfig.value = _displayConfig.value.copy(themeMode = themeMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateFontSize(fontSize: Float) {
|
fun updateFontSize(fontSize: Float) {
|
||||||
prefs.putFloat("fontSize", fontSize)
|
settings.putFloat("fontSize", fontSize)
|
||||||
prefs.flush()
|
|
||||||
_displayConfig.value = _displayConfig.value.copy(fontSize = fontSize)
|
_displayConfig.value = _displayConfig.value.copy(fontSize = fontSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetToDefault() {
|
fun resetToDefault() {
|
||||||
try {
|
try {
|
||||||
prefs.remove("themeMode")
|
settings.remove("themeMode")
|
||||||
prefs.remove("fontSize")
|
settings.remove("fontSize")
|
||||||
prefs.flush()
|
settings.remove("primaryBlueHex")
|
||||||
|
settings.remove("accentYellowHex")
|
||||||
|
settings.remove("accentGreenHex")
|
||||||
|
settings.remove("accentPinkHex")
|
||||||
|
|
||||||
loadInitialConfig()
|
loadInitialConfig()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ data class DisplayConfig (
|
||||||
val themeMode: String = "LIGHT",
|
val themeMode: String = "LIGHT",
|
||||||
val fontSize: Float = 14f,
|
val fontSize: Float = 14f,
|
||||||
val playlist: List<String> = emptyList(),
|
val playlist: List<String> = emptyList(),
|
||||||
|
val primaryBlueHex: String = "#5061FF",
|
||||||
|
val accentYellowHex: String = "#FFFFFA54",
|
||||||
|
val accentGreenHex: String = "#3EFF96",
|
||||||
|
val accentPinkHex: String = "#FFFF4FA8",
|
||||||
val buttonContainerColorHex: String = "#737EFC",
|
val buttonContainerColorHex: String = "#737EFC",
|
||||||
val buttonContentColorHex: String = "#FFFFFF",
|
val buttonContentColorHex: String = "#FFFFFF",
|
||||||
val buttonDisabledContainerColorHex: String = "#CCCCCC",
|
val buttonDisabledContainerColorHex: String = "#CCCCCC",
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import mg.dot.feufaro.getPlatform
|
||||||
import mg.dot.feufaro.midi.Dynamic
|
import mg.dot.feufaro.midi.Dynamic
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Settings(
|
fun Settings(
|
||||||
sharedScreenModel: SharedScreenModel,
|
sharedScreenModel: SharedScreenModel,
|
||||||
|
|
@ -146,12 +146,11 @@ fun Settings(
|
||||||
|
|
||||||
HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
|
HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
|
||||||
|
|
||||||
Row(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 4.dp),
|
.padding(vertical = 8.dp),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "Taille de la police",
|
text = "Taille de la police",
|
||||||
|
|
@ -160,8 +159,9 @@ fun Settings(
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(15.dp)
|
horizontalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|
@ -169,11 +169,13 @@ fun Settings(
|
||||||
displayConfigManager.updateFontSize(currentDisplayConfig.fontSize - 0.5f)
|
displayConfigManager.updateFontSize(currentDisplayConfig.fontSize - 0.5f)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.size(25.dp).background(MaterialTheme.colorScheme.primary, CircleShape)
|
modifier = Modifier.size(32.dp).background(MaterialTheme.colorScheme.primary, CircleShape)
|
||||||
) {
|
) {
|
||||||
Text("-", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.titleLarge, color = Color.White)
|
Text("-", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.titleLarge, color = Color.White)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = tempFontSize.toString(),
|
value = tempFontSize.toString(),
|
||||||
onValueChange = {},
|
onValueChange = {},
|
||||||
|
|
@ -183,19 +185,97 @@ fun Settings(
|
||||||
shape = RoundedCornerShape(12.dp)
|
shape = RoundedCornerShape(12.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (currentDisplayConfig.fontSize < 30f) {
|
if (currentDisplayConfig.fontSize < 30f) {
|
||||||
displayConfigManager.updateFontSize(currentDisplayConfig.fontSize + 0.5f)
|
displayConfigManager.updateFontSize(currentDisplayConfig.fontSize + 0.5f)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.size(25.dp).background(MaterialTheme.colorScheme.primary, CircleShape)
|
modifier = Modifier.size(32.dp).background(MaterialTheme.colorScheme.primary, CircleShape)
|
||||||
) {
|
) {
|
||||||
Text("+", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.titleLarge, color = Color.White)
|
Text("+", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.titleLarge, color = Color.White)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HorizontalDivider(color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f))
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 8.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Personnalisation des couleurs",
|
||||||
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
|
||||||
|
val colorPickers = listOf(
|
||||||
|
Triple("Couleur Primaire", "primaryBlueHex", currentDisplayConfig.primaryBlueHex),
|
||||||
|
Triple("Couleur Secondaire", "accentGreenHex", currentDisplayConfig.accentGreenHex),
|
||||||
|
Triple("Couleur Tertiaire", "accentYellowHex", currentDisplayConfig.accentYellowHex),
|
||||||
|
Triple("Autre couleur", "accentPinkHex", currentDisplayConfig.accentPinkHex)
|
||||||
|
)
|
||||||
|
|
||||||
|
val availableColors = ThemeDefaults.availableColors
|
||||||
|
|
||||||
|
colorPickers.forEach { (label, configKey, currentHex) ->
|
||||||
|
var showLocalPicker by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(label, style = MaterialTheme.typography.bodyMedium)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(36.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(currentHex.toColorOrDefault(Color.Gray))
|
||||||
|
.border(2.dp, MaterialTheme.colorScheme.outline, CircleShape)
|
||||||
|
.clickable { showLocalPicker = !showLocalPicker }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(visible = showLocalPicker) {
|
||||||
|
FlowRow(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f), RoundedCornerShape(8.dp))
|
||||||
|
.padding(12.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||||
|
) {
|
||||||
|
availableColors.forEach { colorHex ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(32.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(colorHex.toColorOrDefault(Color.Gray))
|
||||||
|
.border(
|
||||||
|
width = if (currentHex.uppercase() == colorHex.uppercase()) 2.5.dp else 0.dp,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
|
shape = CircleShape
|
||||||
|
)
|
||||||
|
.clickable {
|
||||||
|
displayConfigManager.updateCustomColor(configKey, colorHex)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onClick = { displayConfigManager.resetToDefault() },
|
onClick = { displayConfigManager.resetToDefault() },
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,98 @@
|
||||||
package mg.dot.feufaro.ui
|
package mg.dot.feufaro.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.material3.ColorScheme
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Typography
|
|
||||||
import androidx.compose.material3.darkColorScheme
|
|
||||||
import androidx.compose.material3.lightColorScheme
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import mg.dot.feufaro.config.DisplayConfig
|
||||||
|
|
||||||
|
fun String.toColorOrDefault(defaultColor: Color): Color {
|
||||||
|
return try {
|
||||||
|
val cleaned = this.removePrefix("#").trim()
|
||||||
|
|
||||||
|
when (cleaned.length) {
|
||||||
|
6 -> {
|
||||||
|
val longValue = "FF$cleaned".toLong(16)
|
||||||
|
Color(longValue)
|
||||||
|
}
|
||||||
|
8 -> {
|
||||||
|
val longValue = cleaned.toLong(16)
|
||||||
|
Color(longValue)
|
||||||
|
}
|
||||||
|
else -> defaultColor
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
defaultColor
|
||||||
|
}
|
||||||
|
}
|
||||||
object ThemeDefaults {
|
object ThemeDefaults {
|
||||||
val PrimaryBlue = Color(0xFF5061FF)
|
val availableColors = listOf(
|
||||||
val AccentYellow = Color(0xFFFFFA54)
|
"#5061FF", // Bleu (défaut)
|
||||||
val AccentGreen = Color(0xFF3EFF96)
|
"#FFD662", // Jaune (défaut)
|
||||||
val AccentPink = Color(0xFFFF4FA8)
|
"#3EFF96", // Vert (défaut)
|
||||||
|
"#FF4FA8", // Rose (défaut)
|
||||||
|
"#FF1744", // Rouge
|
||||||
|
"#FF8C42", // Orange
|
||||||
|
"#FFC857", // Or
|
||||||
|
"#6BCB77", // Vert nature
|
||||||
|
"#00C2A8", // Turquoise
|
||||||
|
"#4D96FF", // Bleu ciel
|
||||||
|
"#422057", // Violet
|
||||||
|
"#D65DB1", // Magenta
|
||||||
|
"#7B61FF", // Lavande
|
||||||
|
"#00B8D9", // Cyan
|
||||||
|
"#009688", // Sarcelle
|
||||||
|
"#8BC34A", // Vert lime
|
||||||
|
"#795548", // Marron
|
||||||
|
"#607D8B", // Bleu gris
|
||||||
|
"#E91E63", // Fuchsia
|
||||||
|
"#1A1A1A", // Noir profond
|
||||||
|
)
|
||||||
|
|
||||||
val LightBackground = Color(0xFFF9F9FB)
|
val LightBackground = Color(0xFFF9F9FB)
|
||||||
val DarkBackground = Color(0xFF121214)
|
val DarkBackground = Color(0xFF121214)
|
||||||
|
|
||||||
|
|
||||||
fun getSelectedThemeColors(themeModeStr: String): Pair<ColorScheme, ColorScheme> {
|
fun getSelectedThemeColors(config: DisplayConfig): Pair<ColorScheme, ColorScheme> {
|
||||||
return when (themeModeStr.uppercase()) {
|
val primaryBlue = config.primaryBlueHex.toColorOrDefault(Color(0xFF5061FF))
|
||||||
"SYSTEM", "DARK", "LIGHT" -> Pair(
|
val accentYellow = config.accentYellowHex.toColorOrDefault(Color(0xFFFFD662))
|
||||||
|
val accentGreen = config.accentGreenHex.toColorOrDefault(Color(0xFF3EFF96))
|
||||||
|
val accentPink = config.accentPinkHex.toColorOrDefault(Color(0xFFFF4FA8))
|
||||||
|
|
||||||
|
return Pair(
|
||||||
lightColorScheme(
|
lightColorScheme(
|
||||||
primary = PrimaryBlue.copy(alpha = 0.85f),
|
primary = primaryBlue.copy(alpha = 0.85f),
|
||||||
onPrimary = LightBackground,
|
onPrimary = LightBackground,
|
||||||
|
|
||||||
secondary = AccentGreen.copy(alpha = 0.85f),
|
secondary = accentGreen.copy(alpha = 0.85f),
|
||||||
onSecondary = DarkBackground,
|
onSecondary = DarkBackground,
|
||||||
secondaryContainer = AccentGreen.copy(alpha = 0.85f),
|
secondaryContainer = accentGreen.copy(alpha = 0.85f),
|
||||||
onSecondaryContainer = DarkBackground,
|
onSecondaryContainer = DarkBackground,
|
||||||
|
|
||||||
tertiary = AccentYellow.copy(alpha = 0.85f),
|
tertiary = accentYellow.copy(alpha = 0.85f),
|
||||||
onTertiary = DarkBackground,
|
onTertiary = DarkBackground,
|
||||||
|
|
||||||
error = AccentPink.copy(alpha = 0.85f),
|
error = accentPink.copy(alpha = 0.85f),
|
||||||
onError = LightBackground,
|
onError = LightBackground,
|
||||||
|
|
||||||
background = LightBackground,
|
background = LightBackground,
|
||||||
surface = LightBackground
|
surface = LightBackground
|
||||||
),
|
),
|
||||||
darkColorScheme(
|
darkColorScheme(
|
||||||
primary = PrimaryBlue,
|
primary = primaryBlue,
|
||||||
onPrimary = LightBackground,
|
onPrimary = LightBackground,
|
||||||
|
|
||||||
secondary = AccentGreen,
|
secondary = accentGreen,
|
||||||
onSecondary = LightBackground,
|
onSecondary = LightBackground,
|
||||||
secondaryContainer = AccentGreen,
|
secondaryContainer = accentGreen,
|
||||||
onSecondaryContainer = DarkBackground,
|
onSecondaryContainer = DarkBackground,
|
||||||
|
|
||||||
tertiary = AccentYellow,
|
tertiary = accentYellow,
|
||||||
onTertiary = DarkBackground,
|
onTertiary = DarkBackground,
|
||||||
|
|
||||||
error = AccentPink,
|
error = accentPink,
|
||||||
onError = LightBackground,
|
onError = LightBackground,
|
||||||
|
|
||||||
background = DarkBackground,
|
background = DarkBackground,
|
||||||
|
|
@ -64,30 +101,24 @@ object ThemeDefaults {
|
||||||
onSurface = LightBackground
|
onSurface = LightBackground
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else -> Pair(
|
|
||||||
lightColorScheme(primary = PrimaryBlue, background = LightBackground),
|
|
||||||
darkColorScheme(primary = PrimaryBlue, background = DarkBackground)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FeufaroTheme(
|
fun FeufaroTheme(
|
||||||
themeModeSelected: String,
|
config: DisplayConfig,
|
||||||
userFontSize: Float,
|
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
val (lightScheme, darkScheme) = ThemeDefaults.getSelectedThemeColors(themeModeSelected)
|
val (lightScheme, darkScheme) = ThemeDefaults.getSelectedThemeColors(config)
|
||||||
val useDarkTheme = when (themeModeSelected.uppercase()) {
|
val useDarkTheme = when (config.themeMode.uppercase()) {
|
||||||
"DARK" -> true
|
"DARK" -> true
|
||||||
"LIGHT" -> false
|
"LIGHT" -> false
|
||||||
else -> isSystemInDarkTheme()
|
else -> isSystemInDarkTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
val colorScheme = if (useDarkTheme) darkScheme else lightScheme
|
val colorScheme = if (useDarkTheme) darkScheme else lightScheme
|
||||||
|
|
||||||
val baseSize = userFontSize
|
val baseSize = config.fontSize
|
||||||
|
|
||||||
val customTypography = Typography(
|
val customTypography = Typography(
|
||||||
displayLarge = TextStyle(
|
displayLarge = TextStyle(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue