feat(settings): disable editing time when service is running, auto reload
when navigating to timer screen
This commit is contained in:
@@ -21,6 +21,7 @@ import android.net.Uri
|
||||
import android.provider.Settings
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
/**
|
||||
* Interface that holds the timer durations for each timer type. This repository maintains a single
|
||||
@@ -43,7 +44,7 @@ interface TimerRepository {
|
||||
|
||||
var alarmSoundUri: Uri?
|
||||
|
||||
var serviceRunning: Boolean
|
||||
var serviceRunning: MutableStateFlow<Boolean>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,5 +62,5 @@ class AppTimerRepository : TimerRepository {
|
||||
override var colorScheme = lightColorScheme()
|
||||
override var alarmSoundUri: Uri? =
|
||||
Settings.System.DEFAULT_ALARM_ALERT_URI ?: Settings.System.DEFAULT_RINGTONE_URI
|
||||
override var serviceRunning = false
|
||||
override var serviceRunning = MutableStateFlow(false)
|
||||
}
|
||||
@@ -98,12 +98,12 @@ class TimerService : Service() {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
timerRepository.serviceRunning = true
|
||||
timerRepository.serviceRunning.update { true }
|
||||
alarm = initializeMediaPlayer()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
timerRepository.serviceRunning = false
|
||||
timerRepository.serviceRunning.update { false }
|
||||
runBlocking {
|
||||
job.cancel()
|
||||
saveTimeToDb()
|
||||
|
||||
@@ -101,6 +101,7 @@ fun SettingsScreenRoot(
|
||||
val longBreakTimeInputFieldState = viewModel.longBreakTimeTextFieldState
|
||||
|
||||
val isPlus by viewModel.isPlus.collectAsStateWithLifecycle()
|
||||
val serviceRunning by viewModel.serviceRunning.collectAsStateWithLifecycle()
|
||||
|
||||
val settingsState by viewModel.settingsState.collectAsStateWithLifecycle()
|
||||
|
||||
@@ -115,6 +116,7 @@ fun SettingsScreenRoot(
|
||||
|
||||
SettingsScreen(
|
||||
isPlus = isPlus,
|
||||
serviceRunning = serviceRunning,
|
||||
settingsState = settingsState,
|
||||
backStack = backStack,
|
||||
focusTimeInputFieldState = focusTimeInputFieldState,
|
||||
@@ -132,6 +134,7 @@ fun SettingsScreenRoot(
|
||||
@Composable
|
||||
private fun SettingsScreen(
|
||||
isPlus: Boolean,
|
||||
serviceRunning: Boolean,
|
||||
settingsState: SettingsState,
|
||||
backStack: SnapshotStateList<Screen.Settings>,
|
||||
focusTimeInputFieldState: TextFieldState,
|
||||
@@ -292,6 +295,7 @@ private fun SettingsScreen(
|
||||
entry<Screen.Settings.Timer> {
|
||||
TimerSettings(
|
||||
isPlus = isPlus,
|
||||
serviceRunning = serviceRunning,
|
||||
settingsState = settingsState,
|
||||
focusTimeInputFieldState = focusTimeInputFieldState,
|
||||
shortBreakTimeInputFieldState = shortBreakTimeInputFieldState,
|
||||
|
||||
@@ -22,6 +22,7 @@ import androidx.annotation.StringRes
|
||||
|
||||
data class SettingsSwitchItem(
|
||||
val checked: Boolean,
|
||||
val enabled: Boolean = true,
|
||||
@param:DrawableRes val icon: Int,
|
||||
@param:StringRes val label: Int,
|
||||
@param:StringRes val description: Int,
|
||||
|
||||
@@ -46,12 +46,14 @@ import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors
|
||||
@Composable
|
||||
fun MinuteInputField(
|
||||
state: TextFieldState,
|
||||
enabled: Boolean,
|
||||
shape: Shape,
|
||||
modifier: Modifier = Modifier,
|
||||
imeAction: ImeAction = ImeAction.Next
|
||||
) {
|
||||
BasicTextField(
|
||||
state = state,
|
||||
enabled = enabled,
|
||||
lineLimits = TextFieldLineLimits.SingleLine,
|
||||
inputTransformation = MinutesInputTransformation,
|
||||
// outputTransformation = MinutesOutputTransformation,
|
||||
@@ -63,7 +65,7 @@ fun MinuteInputField(
|
||||
fontFamily = interClock,
|
||||
fontSize = 57.sp,
|
||||
letterSpacing = (-2).sp,
|
||||
color = colorScheme.onSurfaceVariant,
|
||||
color = if (enabled) colorScheme.onSurfaceVariant else colorScheme.outlineVariant,
|
||||
textAlign = TextAlign.Center
|
||||
),
|
||||
cursorBrush = SolidColor(colorScheme.onSurface),
|
||||
|
||||
@@ -50,6 +50,7 @@ import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.IconButtonDefaults
|
||||
import androidx.compose.material3.LargeFlexibleTopAppBar
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.Slider
|
||||
@@ -60,7 +61,8 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberSliderState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -76,6 +78,7 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.nsh07.pomodoro.R
|
||||
import org.nsh07.pomodoro.service.TimerService
|
||||
import org.nsh07.pomodoro.ui.settingsScreen.SettingsSwitchItem
|
||||
import org.nsh07.pomodoro.ui.settingsScreen.components.MinuteInputField
|
||||
import org.nsh07.pomodoro.ui.settingsScreen.components.PlusDivider
|
||||
@@ -95,6 +98,7 @@ import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape
|
||||
@Composable
|
||||
fun TimerSettings(
|
||||
isPlus: Boolean,
|
||||
serviceRunning: Boolean,
|
||||
settingsState: SettingsState,
|
||||
focusTimeInputFieldState: TextFieldState,
|
||||
shortBreakTimeInputFieldState: TextFieldState,
|
||||
@@ -111,14 +115,21 @@ fun TimerSettings(
|
||||
val notificationManagerService =
|
||||
remember { context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
if (!notificationManagerService.isNotificationPolicyAccessGranted())
|
||||
onAction(SettingsAction.SaveDndEnabled(false))
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
if (!serviceRunning) {
|
||||
Intent(context, TimerService::class.java).also {
|
||||
it.action = TimerService.Actions.RESET.toString()
|
||||
context.startService(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val switchItems = listOf(
|
||||
SettingsSwitchItem(
|
||||
checked = settingsState.dndEnabled,
|
||||
enabled = !serviceRunning,
|
||||
icon = R.drawable.dnd,
|
||||
label = R.string.dnd,
|
||||
description = R.string.dnd_desc,
|
||||
@@ -171,6 +182,20 @@ fun TimerSettings(
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
item {
|
||||
CompositionLocalProvider(LocalContentColor provides colorScheme.error) {
|
||||
AnimatedVisibility(serviceRunning) {
|
||||
Column {
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Icon(painterResource(R.drawable.info), null)
|
||||
Text("Reset the timer to change settings")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(14.dp))
|
||||
}
|
||||
item {
|
||||
@@ -190,6 +215,7 @@ fun TimerSettings(
|
||||
)
|
||||
MinuteInputField(
|
||||
state = focusTimeInputFieldState,
|
||||
enabled = !serviceRunning,
|
||||
shape = RoundedCornerShape(
|
||||
topStart = topListItemShape.topStart,
|
||||
bottomStart = topListItemShape.topStart,
|
||||
@@ -210,6 +236,7 @@ fun TimerSettings(
|
||||
)
|
||||
MinuteInputField(
|
||||
state = shortBreakTimeInputFieldState,
|
||||
enabled = !serviceRunning,
|
||||
shape = RoundedCornerShape(middleListItemShape.topStart),
|
||||
imeAction = ImeAction.Next
|
||||
)
|
||||
@@ -225,6 +252,7 @@ fun TimerSettings(
|
||||
)
|
||||
MinuteInputField(
|
||||
state = longBreakTimeInputFieldState,
|
||||
enabled = !serviceRunning,
|
||||
shape = RoundedCornerShape(
|
||||
topStart = bottomListItemShape.topStart,
|
||||
bottomStart = bottomListItemShape.topStart,
|
||||
@@ -257,6 +285,7 @@ fun TimerSettings(
|
||||
)
|
||||
Slider(
|
||||
state = sessionsSliderState,
|
||||
enabled = !serviceRunning,
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
)
|
||||
}
|
||||
@@ -281,6 +310,7 @@ fun TimerSettings(
|
||||
trailingContent = {
|
||||
Switch(
|
||||
checked = item.checked,
|
||||
enabled = item.enabled,
|
||||
onCheckedChange = { item.onClick(it) },
|
||||
thumbContent = {
|
||||
if (item.checked) {
|
||||
@@ -405,6 +435,7 @@ private fun TimerSettingsPreview() {
|
||||
)
|
||||
TimerSettings(
|
||||
isPlus = false,
|
||||
serviceRunning = true,
|
||||
settingsState = remember { SettingsState() },
|
||||
focusTimeInputFieldState = focusTimeInputFieldState,
|
||||
shortBreakTimeInputFieldState = shortBreakTimeInputFieldState,
|
||||
|
||||
@@ -54,6 +54,7 @@ class SettingsViewModel(
|
||||
val backStack = mutableStateListOf<Screen.Settings>(Screen.Settings.Main)
|
||||
|
||||
val isPlus = billingManager.isPlus
|
||||
val serviceRunning = timerRepository.serviceRunning.asStateFlow()
|
||||
|
||||
private val _settingsState = MutableStateFlow(SettingsState())
|
||||
val settingsState = _settingsState.asStateFlow()
|
||||
@@ -273,14 +274,14 @@ class SettingsViewModel(
|
||||
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||
initializer {
|
||||
val application = (this[APPLICATION_KEY] as TomatoApplication)
|
||||
val appBillingManager = application.container.billingManager
|
||||
val appPreferenceRepository = application.container.appPreferenceRepository
|
||||
val appTimerRepository = application.container.appTimerRepository
|
||||
val appBillingManager = application.container.billingManager
|
||||
|
||||
SettingsViewModel(
|
||||
billingManager = appBillingManager,
|
||||
preferenceRepository = appPreferenceRepository,
|
||||
timerRepository = appTimerRepository,
|
||||
timerRepository = appTimerRepository
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class TimerViewModel(
|
||||
private var pauseDuration = 0L
|
||||
|
||||
init {
|
||||
if (!timerRepository.serviceRunning)
|
||||
if (!timerRepository.serviceRunning.value)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
timerRepository.focusTime =
|
||||
preferenceRepository.getIntPreference("focus_time")?.toLong()
|
||||
|
||||
Reference in New Issue
Block a user