feat: Add feature to change app theme and enable pure black dark theme
Closes: #30
This commit is contained in:
@@ -130,7 +130,7 @@ fun SettingsScreenRoot(
|
|||||||
alarmSound = alarmSound,
|
alarmSound = alarmSound,
|
||||||
onAlarmEnabledChange = viewModel::saveAlarmEnabled,
|
onAlarmEnabledChange = viewModel::saveAlarmEnabled,
|
||||||
onVibrateEnabledChange = viewModel::saveVibrateEnabled,
|
onVibrateEnabledChange = viewModel::saveVibrateEnabled,
|
||||||
onBlackThemeChange = {},
|
onBlackThemeChange = viewModel::saveBlackTheme,
|
||||||
onAlarmSoundChanged = {
|
onAlarmSoundChanged = {
|
||||||
viewModel.saveAlarmSound(it)
|
viewModel.saveAlarmSound(it)
|
||||||
Intent(context, TimerService::class.java).apply {
|
Intent(context, TimerService::class.java).apply {
|
||||||
@@ -138,6 +138,7 @@ fun SettingsScreenRoot(
|
|||||||
context.startService(this)
|
context.startService(this)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onThemeChange = viewModel::saveTheme,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -157,6 +158,7 @@ private fun SettingsScreen(
|
|||||||
onVibrateEnabledChange: (Boolean) -> Unit,
|
onVibrateEnabledChange: (Boolean) -> Unit,
|
||||||
onBlackThemeChange: (Boolean) -> Unit,
|
onBlackThemeChange: (Boolean) -> Unit,
|
||||||
onAlarmSoundChanged: (Uri?) -> Unit,
|
onAlarmSoundChanged: (Uri?) -> Unit,
|
||||||
|
onThemeChange: (String) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||||
@@ -164,6 +166,24 @@ private fun SettingsScreen(
|
|||||||
checkedIconColor = colorScheme.primary,
|
checkedIconColor = colorScheme.primary,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val themeMap: Map<String, Pair<Int, String>> = remember {
|
||||||
|
mapOf(
|
||||||
|
"auto" to Pair(
|
||||||
|
R.drawable.brightness_auto,
|
||||||
|
"System default"
|
||||||
|
),
|
||||||
|
"light" to Pair(R.drawable.light_mode, "Light"),
|
||||||
|
"dark" to Pair(R.drawable.dark_mode, "Dark")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val reverseThemeMap: Map<String, String> = remember {
|
||||||
|
mapOf(
|
||||||
|
"System default" to "auto",
|
||||||
|
"Light" to "light",
|
||||||
|
"Dark" to "dark"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val ringtonePickerLauncher = rememberLauncherForActivityResult(
|
val ringtonePickerLauncher = rememberLauncherForActivityResult(
|
||||||
@@ -190,7 +210,7 @@ private fun SettingsScreen(
|
|||||||
putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, alarmSound.toUri())
|
putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, alarmSound.toUri())
|
||||||
}
|
}
|
||||||
|
|
||||||
val switchItems = remember(alarmEnabled, vibrateEnabled) {
|
val switchItems = remember(preferencesState.blackTheme, alarmEnabled, vibrateEnabled) {
|
||||||
listOf(
|
listOf(
|
||||||
SettingsSwitchItem(
|
SettingsSwitchItem(
|
||||||
checked = preferencesState.blackTheme,
|
checked = preferencesState.blackTheme,
|
||||||
@@ -360,33 +380,13 @@ private fun SettingsScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
ListItem(
|
ThemePickerListItem(
|
||||||
leadingContent = {
|
theme = preferencesState.theme,
|
||||||
Icon(
|
themeMap = themeMap,
|
||||||
painter = painterResource(
|
reverseThemeMap = reverseThemeMap,
|
||||||
when (preferencesState.theme) {
|
onThemeChange = onThemeChange,
|
||||||
"dark" -> R.drawable.dark_mode
|
|
||||||
"light" -> R.drawable.light_mode
|
|
||||||
else -> R.drawable.brightness_auto
|
|
||||||
}
|
|
||||||
),
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
},
|
|
||||||
headlineContent = { Text("Theme") },
|
|
||||||
supportingContent = {
|
|
||||||
Text(
|
|
||||||
when (preferencesState.theme) {
|
|
||||||
"dark" -> "Dark"
|
|
||||||
"light" -> "Light"
|
|
||||||
else -> "System default"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
colors = listItemColors,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clip(middleListItemShape)
|
.clip(middleListItemShape)
|
||||||
.clickable(onClick = {})
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
@@ -436,7 +436,7 @@ private fun SettingsScreen(
|
|||||||
Text(
|
Text(
|
||||||
remember(alarmSound) {
|
remember(alarmSound) {
|
||||||
RingtoneManager.getRingtone(context, alarmSound.toUri())
|
RingtoneManager.getRingtone(context, alarmSound.toUri())
|
||||||
.getTitle(context)
|
?.getTitle(context) ?: ""
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -530,9 +530,9 @@ fun SettingsScreenPreview() {
|
|||||||
TomatoTheme {
|
TomatoTheme {
|
||||||
SettingsScreen(
|
SettingsScreen(
|
||||||
preferencesState = PreferencesState(),
|
preferencesState = PreferencesState(),
|
||||||
focusTimeInputFieldState = rememberTextFieldState((25 * 60 * 1000).toString()),
|
focusTimeInputFieldState = rememberTextFieldState((25).toString()),
|
||||||
shortBreakTimeInputFieldState = rememberTextFieldState((5 * 60 * 1000).toString()),
|
shortBreakTimeInputFieldState = rememberTextFieldState((5).toString()),
|
||||||
longBreakTimeInputFieldState = rememberTextFieldState((15 * 60 * 1000).toString()),
|
longBreakTimeInputFieldState = rememberTextFieldState((15).toString()),
|
||||||
sessionsSliderState = rememberSliderState(value = 3f, steps = 3, valueRange = 1f..5f),
|
sessionsSliderState = rememberSliderState(value = 3f, steps = 3, valueRange = 1f..5f),
|
||||||
alarmEnabled = true,
|
alarmEnabled = true,
|
||||||
vibrateEnabled = true,
|
vibrateEnabled = true,
|
||||||
@@ -541,6 +541,7 @@ fun SettingsScreenPreview() {
|
|||||||
onVibrateEnabledChange = {},
|
onVibrateEnabledChange = {},
|
||||||
onBlackThemeChange = {},
|
onBlackThemeChange = {},
|
||||||
onAlarmSoundChanged = {},
|
onAlarmSoundChanged = {},
|
||||||
|
onThemeChange = {},
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Nishant Mishra
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.nsh07.pomodoro.ui.settingsScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.selection.selectable
|
||||||
|
import androidx.compose.foundation.selection.selectableGroup
|
||||||
|
import androidx.compose.material3.AlertDialogDefaults
|
||||||
|
import androidx.compose.material3.BasicAlertDialog
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||||
|
import androidx.compose.material3.MaterialTheme.shapes
|
||||||
|
import androidx.compose.material3.RadioButton
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.semantics.Role
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors
|
||||||
|
import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.bottomListItemShape
|
||||||
|
import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.middleListItemShape
|
||||||
|
import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
|
@Composable
|
||||||
|
fun ThemeDialog(
|
||||||
|
themeMap: Map<String, Pair<Int, String>>,
|
||||||
|
reverseThemeMap: Map<String, String>,
|
||||||
|
theme: String,
|
||||||
|
setShowThemeDialog: (Boolean) -> Unit,
|
||||||
|
onThemeChange: (String) -> Unit
|
||||||
|
) {
|
||||||
|
val selectedOption =
|
||||||
|
remember { mutableStateOf(themeMap[theme]!!.second) }
|
||||||
|
|
||||||
|
BasicAlertDialog(
|
||||||
|
onDismissRequest = { setShowThemeDialog(false) }
|
||||||
|
) {
|
||||||
|
Surface(
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentWidth()
|
||||||
|
.wrapContentHeight(),
|
||||||
|
shape = shapes.extraLarge,
|
||||||
|
color = colorScheme.surfaceContainer,
|
||||||
|
tonalElevation = AlertDialogDefaults.TonalElevation
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier.padding(24.dp)) {
|
||||||
|
Text(
|
||||||
|
text = "Choose theme",
|
||||||
|
style = MaterialTheme.typography.headlineSmall
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||||
|
modifier = Modifier.selectableGroup()
|
||||||
|
) {
|
||||||
|
themeMap.entries.forEachIndexed { index: Int, pair: Map.Entry<String, Pair<Int, String>> ->
|
||||||
|
val text = pair.value.second
|
||||||
|
ListItem(
|
||||||
|
leadingContent = {
|
||||||
|
RadioButton(
|
||||||
|
selected = (text == selectedOption.value),
|
||||||
|
onClick = null // null recommended for accessibility with screenreaders
|
||||||
|
)
|
||||||
|
},
|
||||||
|
headlineContent = {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
colors = listItemColors,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(
|
||||||
|
when (index) {
|
||||||
|
0 -> topListItemShape
|
||||||
|
themeMap.size - 1 -> bottomListItemShape
|
||||||
|
else -> middleListItemShape
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.selectable(
|
||||||
|
selected = (text == selectedOption.value),
|
||||||
|
onClick = {
|
||||||
|
selectedOption.value = text
|
||||||
|
onThemeChange(reverseThemeMap[selectedOption.value]!!)
|
||||||
|
},
|
||||||
|
role = Role.RadioButton
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
TextButton(
|
||||||
|
shapes = ButtonDefaults.shapes(),
|
||||||
|
onClick = { setShowThemeDialog(false) },
|
||||||
|
modifier = Modifier.align(Alignment.End)
|
||||||
|
) {
|
||||||
|
Text("Ok")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Nishant Mishra
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.nsh07.pomodoro.ui.settingsScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ThemePickerListItem(
|
||||||
|
theme: String,
|
||||||
|
themeMap: Map<String, Pair<Int, String>>,
|
||||||
|
reverseThemeMap: Map<String, String>,
|
||||||
|
onThemeChange: (String) -> Unit,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
var showDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
|
if (showDialog) {
|
||||||
|
ThemeDialog(
|
||||||
|
themeMap = themeMap,
|
||||||
|
reverseThemeMap = reverseThemeMap,
|
||||||
|
theme = theme,
|
||||||
|
setShowThemeDialog = { showDialog = it },
|
||||||
|
onThemeChange = onThemeChange
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ListItem(
|
||||||
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(themeMap[theme]!!.first),
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
},
|
||||||
|
headlineContent = { Text("Theme") },
|
||||||
|
supportingContent = {
|
||||||
|
Text(themeMap[theme]!!.second)
|
||||||
|
},
|
||||||
|
colors = listItemColors,
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { showDialog = true }
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class PreferencesState(
|
data class PreferencesState(
|
||||||
val theme: String = "system",
|
val theme: String = "auto",
|
||||||
val colorScheme: String = Color.White.toString(),
|
val colorScheme: String = Color.White.toString(),
|
||||||
val blackTheme: Boolean = false
|
val blackTheme: Boolean = false
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class SettingsViewModel(
|
|||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val theme = preferenceRepository.getStringPreference("theme")
|
val theme = preferenceRepository.getStringPreference("theme")
|
||||||
?: preferenceRepository.saveStringPreference("theme", "system")
|
?: preferenceRepository.saveStringPreference("theme", "auto")
|
||||||
val colorScheme = preferenceRepository.getStringPreference("color_scheme")
|
val colorScheme = preferenceRepository.getStringPreference("color_scheme")
|
||||||
?: preferenceRepository.saveStringPreference("color_scheme", Color.White.toString())
|
?: preferenceRepository.saveStringPreference("color_scheme", Color.White.toString())
|
||||||
val blackTheme = preferenceRepository.getBooleanPreference("black_theme")
|
val blackTheme = preferenceRepository.getBooleanPreference("black_theme")
|
||||||
@@ -128,50 +128,50 @@ class SettingsViewModel(
|
|||||||
|
|
||||||
fun saveAlarmEnabled(enabled: Boolean) {
|
fun saveAlarmEnabled(enabled: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
preferenceRepository.saveBooleanPreference("alarm_enabled", enabled)
|
|
||||||
timerRepository.alarmEnabled = enabled
|
timerRepository.alarmEnabled = enabled
|
||||||
|
preferenceRepository.saveBooleanPreference("alarm_enabled", enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveVibrateEnabled(enabled: Boolean) {
|
fun saveVibrateEnabled(enabled: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
preferenceRepository.saveBooleanPreference("vibrate_enabled", enabled)
|
|
||||||
timerRepository.vibrateEnabled = enabled
|
timerRepository.vibrateEnabled = enabled
|
||||||
|
preferenceRepository.saveBooleanPreference("vibrate_enabled", enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveAlarmSound(uri: Uri?) {
|
fun saveAlarmSound(uri: Uri?) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
timerRepository.alarmSoundUri = uri
|
||||||
preferenceRepository.saveStringPreference("alarm_sound", uri.toString())
|
preferenceRepository.saveStringPreference("alarm_sound", uri.toString())
|
||||||
}
|
}
|
||||||
timerRepository.alarmSoundUri = uri
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveColorScheme(colorScheme: Color) {
|
fun saveColorScheme(colorScheme: Color) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
_preferencesState.update { currentState ->
|
||||||
|
currentState.copy(colorScheme = colorScheme.toString())
|
||||||
|
}
|
||||||
preferenceRepository.saveStringPreference("color_scheme", colorScheme.toString())
|
preferenceRepository.saveStringPreference("color_scheme", colorScheme.toString())
|
||||||
}
|
}
|
||||||
_preferencesState.update { currentState ->
|
|
||||||
currentState.copy(colorScheme = colorScheme.toString())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveTheme(theme: String) {
|
fun saveTheme(theme: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
_preferencesState.update { currentState ->
|
||||||
|
currentState.copy(theme = theme)
|
||||||
|
}
|
||||||
preferenceRepository.saveStringPreference("theme", theme)
|
preferenceRepository.saveStringPreference("theme", theme)
|
||||||
}
|
}
|
||||||
_preferencesState.update { currentState ->
|
|
||||||
currentState.copy(theme = theme)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveBlackTheme(blackTheme: Boolean) {
|
fun saveBlackTheme(blackTheme: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
_preferencesState.update { currentState ->
|
||||||
|
currentState.copy(blackTheme = blackTheme)
|
||||||
|
}
|
||||||
preferenceRepository.saveBooleanPreference("black_theme", blackTheme)
|
preferenceRepository.saveBooleanPreference("black_theme", blackTheme)
|
||||||
}
|
}
|
||||||
_preferencesState.update { currentState ->
|
|
||||||
currentState.copy(blackTheme = blackTheme)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -18,15 +18,17 @@ val PurpleGrey40 = Color(0xFF625b71)
|
|||||||
val Pink40 = Color(0xFF7D5260)
|
val Pink40 = Color(0xFF7D5260)
|
||||||
|
|
||||||
object CustomColors {
|
object CustomColors {
|
||||||
|
var black = false
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
val topBarColors: TopAppBarColors
|
val topBarColors: TopAppBarColors
|
||||||
@Composable get() {
|
@Composable get() =
|
||||||
return TopAppBarDefaults.topAppBarColors(
|
TopAppBarDefaults.topAppBarColors(
|
||||||
containerColor = colorScheme.surfaceContainer,
|
containerColor = if (!black) colorScheme.surfaceContainer else colorScheme.surface,
|
||||||
scrolledContainerColor = colorScheme.surfaceContainer
|
scrolledContainerColor = if (!black) colorScheme.surfaceContainer else colorScheme.surface
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
val listItemColors: ListItemColors
|
val listItemColors: ListItemColors
|
||||||
@Composable get() = ListItemDefaults.colors(containerColor = colorScheme.surfaceBright)
|
@Composable get() =
|
||||||
|
ListItemDefaults.colors(containerColor = if (!black) colorScheme.surfaceBright else colorScheme.surfaceContainer)
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.nsh07.pomodoro.ui.theme
|
package org.nsh07.pomodoro.ui.theme
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
@@ -10,8 +11,11 @@ import androidx.compose.material3.dynamicDarkColorScheme
|
|||||||
import androidx.compose.material3.dynamicLightColorScheme
|
import androidx.compose.material3.dynamicLightColorScheme
|
||||||
import androidx.compose.material3.lightColorScheme
|
import androidx.compose.material3.lightColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
import com.materialkolor.dynamiccolor.ColorSpec
|
import com.materialkolor.dynamiccolor.ColorSpec
|
||||||
import com.materialkolor.rememberDynamicColorScheme
|
import com.materialkolor.rememberDynamicColorScheme
|
||||||
|
|
||||||
@@ -56,6 +60,15 @@ fun TomatoTheme(
|
|||||||
else -> LightColorScheme
|
else -> LightColorScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val view = LocalView.current
|
||||||
|
if (!view.isInEditMode) {
|
||||||
|
SideEffect {
|
||||||
|
val window = (view.context as Activity).window
|
||||||
|
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CustomColors.black = blackTheme && darkTheme
|
||||||
|
|
||||||
val dynamicColorScheme = rememberDynamicColorScheme(
|
val dynamicColorScheme = rememberDynamicColorScheme(
|
||||||
seedColor = when (seedColor) {
|
seedColor = when (seedColor) {
|
||||||
Color.White -> colorScheme.primary
|
Color.White -> colorScheme.primary
|
||||||
|
|||||||
Reference in New Issue
Block a user