Skip to content

Commit 9ec3e68

Browse files
committed
feat(settings): disable editing time when service is running, auto reload
when navigating to timer screen
1 parent f898556 commit 9ec3e68

File tree

8 files changed

+52
-12
lines changed

8 files changed

+52
-12
lines changed

app/src/main/java/org/nsh07/pomodoro/data/TimerRepository.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import android.net.Uri
2121
import android.provider.Settings
2222
import androidx.compose.material3.ColorScheme
2323
import androidx.compose.material3.lightColorScheme
24+
import kotlinx.coroutines.flow.MutableStateFlow
2425

2526
/**
2627
* Interface that holds the timer durations for each timer type. This repository maintains a single
@@ -43,7 +44,7 @@ interface TimerRepository {
4344

4445
var alarmSoundUri: Uri?
4546

46-
var serviceRunning: Boolean
47+
var serviceRunning: MutableStateFlow<Boolean>
4748
}
4849

4950
/**
@@ -61,5 +62,5 @@ class AppTimerRepository : TimerRepository {
6162
override var colorScheme = lightColorScheme()
6263
override var alarmSoundUri: Uri? =
6364
Settings.System.DEFAULT_ALARM_ALERT_URI ?: Settings.System.DEFAULT_RINGTONE_URI
64-
override var serviceRunning = false
65+
override var serviceRunning = MutableStateFlow(false)
6566
}

app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,12 @@ class TimerService : Service() {
9898

9999
override fun onCreate() {
100100
super.onCreate()
101-
timerRepository.serviceRunning = true
101+
timerRepository.serviceRunning.update { true }
102102
alarm = initializeMediaPlayer()
103103
}
104104

105105
override fun onDestroy() {
106-
timerRepository.serviceRunning = false
106+
timerRepository.serviceRunning.update { false }
107107
runBlocking {
108108
job.cancel()
109109
saveTimeToDb()

app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ fun SettingsScreenRoot(
101101
val longBreakTimeInputFieldState = viewModel.longBreakTimeTextFieldState
102102

103103
val isPlus by viewModel.isPlus.collectAsStateWithLifecycle()
104+
val serviceRunning by viewModel.serviceRunning.collectAsStateWithLifecycle()
104105

105106
val settingsState by viewModel.settingsState.collectAsStateWithLifecycle()
106107

@@ -115,6 +116,7 @@ fun SettingsScreenRoot(
115116

116117
SettingsScreen(
117118
isPlus = isPlus,
119+
serviceRunning = serviceRunning,
118120
settingsState = settingsState,
119121
backStack = backStack,
120122
focusTimeInputFieldState = focusTimeInputFieldState,
@@ -132,6 +134,7 @@ fun SettingsScreenRoot(
132134
@Composable
133135
private fun SettingsScreen(
134136
isPlus: Boolean,
137+
serviceRunning: Boolean,
135138
settingsState: SettingsState,
136139
backStack: SnapshotStateList<Screen.Settings>,
137140
focusTimeInputFieldState: TextFieldState,
@@ -292,6 +295,7 @@ private fun SettingsScreen(
292295
entry<Screen.Settings.Timer> {
293296
TimerSettings(
294297
isPlus = isPlus,
298+
serviceRunning = serviceRunning,
295299
settingsState = settingsState,
296300
focusTimeInputFieldState = focusTimeInputFieldState,
297301
shortBreakTimeInputFieldState = shortBreakTimeInputFieldState,

app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsSwitchItem.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import androidx.annotation.StringRes
2222

2323
data class SettingsSwitchItem(
2424
val checked: Boolean,
25+
val enabled: Boolean = true,
2526
@param:DrawableRes val icon: Int,
2627
@param:StringRes val label: Int,
2728
@param:StringRes val description: Int,

app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/MinuteInputField.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,14 @@ import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors
4646
@Composable
4747
fun MinuteInputField(
4848
state: TextFieldState,
49+
enabled: Boolean,
4950
shape: Shape,
5051
modifier: Modifier = Modifier,
5152
imeAction: ImeAction = ImeAction.Next
5253
) {
5354
BasicTextField(
5455
state = state,
56+
enabled = enabled,
5557
lineLimits = TextFieldLineLimits.SingleLine,
5658
inputTransformation = MinutesInputTransformation,
5759
// outputTransformation = MinutesOutputTransformation,
@@ -63,7 +65,7 @@ fun MinuteInputField(
6365
fontFamily = interClock,
6466
fontSize = 57.sp,
6567
letterSpacing = (-2).sp,
66-
color = colorScheme.onSurfaceVariant,
68+
color = if (enabled) colorScheme.onSurfaceVariant else colorScheme.outlineVariant,
6769
textAlign = TextAlign.Center
6870
),
6971
cursorBrush = SolidColor(colorScheme.onSurface),

app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import androidx.compose.material3.IconButton
5050
import androidx.compose.material3.IconButtonDefaults
5151
import androidx.compose.material3.LargeFlexibleTopAppBar
5252
import androidx.compose.material3.ListItem
53+
import androidx.compose.material3.LocalContentColor
5354
import androidx.compose.material3.MaterialTheme.colorScheme
5455
import androidx.compose.material3.MaterialTheme.typography
5556
import androidx.compose.material3.Slider
@@ -60,7 +61,8 @@ import androidx.compose.material3.Text
6061
import androidx.compose.material3.TopAppBarDefaults
6162
import androidx.compose.material3.rememberSliderState
6263
import androidx.compose.runtime.Composable
63-
import androidx.compose.runtime.LaunchedEffect
64+
import androidx.compose.runtime.CompositionLocalProvider
65+
import androidx.compose.runtime.DisposableEffect
6466
import androidx.compose.runtime.getValue
6567
import androidx.compose.runtime.mutableStateOf
6668
import androidx.compose.runtime.remember
@@ -76,6 +78,7 @@ import androidx.compose.ui.text.input.ImeAction
7678
import androidx.compose.ui.tooling.preview.Preview
7779
import androidx.compose.ui.unit.dp
7880
import org.nsh07.pomodoro.R
81+
import org.nsh07.pomodoro.service.TimerService
7982
import org.nsh07.pomodoro.ui.settingsScreen.SettingsSwitchItem
8083
import org.nsh07.pomodoro.ui.settingsScreen.components.MinuteInputField
8184
import org.nsh07.pomodoro.ui.settingsScreen.components.PlusDivider
@@ -95,6 +98,7 @@ import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape
9598
@Composable
9699
fun TimerSettings(
97100
isPlus: Boolean,
101+
serviceRunning: Boolean,
98102
settingsState: SettingsState,
99103
focusTimeInputFieldState: TextFieldState,
100104
shortBreakTimeInputFieldState: TextFieldState,
@@ -111,14 +115,21 @@ fun TimerSettings(
111115
val notificationManagerService =
112116
remember { context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager }
113117

114-
LaunchedEffect(Unit) {
115-
if (!notificationManagerService.isNotificationPolicyAccessGranted())
116-
onAction(SettingsAction.SaveDndEnabled(false))
118+
DisposableEffect(Unit) {
119+
onDispose {
120+
if (!serviceRunning) {
121+
Intent(context, TimerService::class.java).also {
122+
it.action = TimerService.Actions.RESET.toString()
123+
context.startService(it)
124+
}
125+
}
126+
}
117127
}
118128

119129
val switchItems = listOf(
120130
SettingsSwitchItem(
121131
checked = settingsState.dndEnabled,
132+
enabled = !serviceRunning,
122133
icon = R.drawable.dnd,
123134
label = R.string.dnd,
124135
description = R.string.dnd_desc,
@@ -171,6 +182,20 @@ fun TimerSettings(
171182
.padding(horizontal = 16.dp)
172183
) {
173184
item {
185+
CompositionLocalProvider(LocalContentColor provides colorScheme.error) {
186+
AnimatedVisibility(serviceRunning) {
187+
Column {
188+
Spacer(Modifier.height(8.dp))
189+
Row(
190+
verticalAlignment = Alignment.CenterVertically,
191+
horizontalArrangement = Arrangement.spacedBy(8.dp)
192+
) {
193+
Icon(painterResource(R.drawable.info), null)
194+
Text("Reset the timer to change settings")
195+
}
196+
}
197+
}
198+
}
174199
Spacer(Modifier.height(14.dp))
175200
}
176201
item {
@@ -190,6 +215,7 @@ fun TimerSettings(
190215
)
191216
MinuteInputField(
192217
state = focusTimeInputFieldState,
218+
enabled = !serviceRunning,
193219
shape = RoundedCornerShape(
194220
topStart = topListItemShape.topStart,
195221
bottomStart = topListItemShape.topStart,
@@ -210,6 +236,7 @@ fun TimerSettings(
210236
)
211237
MinuteInputField(
212238
state = shortBreakTimeInputFieldState,
239+
enabled = !serviceRunning,
213240
shape = RoundedCornerShape(middleListItemShape.topStart),
214241
imeAction = ImeAction.Next
215242
)
@@ -225,6 +252,7 @@ fun TimerSettings(
225252
)
226253
MinuteInputField(
227254
state = longBreakTimeInputFieldState,
255+
enabled = !serviceRunning,
228256
shape = RoundedCornerShape(
229257
topStart = bottomListItemShape.topStart,
230258
bottomStart = bottomListItemShape.topStart,
@@ -257,6 +285,7 @@ fun TimerSettings(
257285
)
258286
Slider(
259287
state = sessionsSliderState,
288+
enabled = !serviceRunning,
260289
modifier = Modifier.padding(vertical = 4.dp)
261290
)
262291
}
@@ -281,6 +310,7 @@ fun TimerSettings(
281310
trailingContent = {
282311
Switch(
283312
checked = item.checked,
313+
enabled = item.enabled,
284314
onCheckedChange = { item.onClick(it) },
285315
thumbContent = {
286316
if (item.checked) {
@@ -405,6 +435,7 @@ private fun TimerSettingsPreview() {
405435
)
406436
TimerSettings(
407437
isPlus = false,
438+
serviceRunning = true,
408439
settingsState = remember { SettingsState() },
409440
focusTimeInputFieldState = focusTimeInputFieldState,
410441
shortBreakTimeInputFieldState = shortBreakTimeInputFieldState,

app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class SettingsViewModel(
5454
val backStack = mutableStateListOf<Screen.Settings>(Screen.Settings.Main)
5555

5656
val isPlus = billingManager.isPlus
57+
val serviceRunning = timerRepository.serviceRunning.asStateFlow()
5758

5859
private val _settingsState = MutableStateFlow(SettingsState())
5960
val settingsState = _settingsState.asStateFlow()
@@ -273,14 +274,14 @@ class SettingsViewModel(
273274
val Factory: ViewModelProvider.Factory = viewModelFactory {
274275
initializer {
275276
val application = (this[APPLICATION_KEY] as TomatoApplication)
277+
val appBillingManager = application.container.billingManager
276278
val appPreferenceRepository = application.container.appPreferenceRepository
277279
val appTimerRepository = application.container.appTimerRepository
278-
val appBillingManager = application.container.billingManager
279280

280281
SettingsViewModel(
281282
billingManager = appBillingManager,
282283
preferenceRepository = appPreferenceRepository,
283-
timerRepository = appTimerRepository,
284+
timerRepository = appTimerRepository
284285
)
285286
}
286287
}

app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/viewModel/TimerViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class TimerViewModel(
7070
private var pauseDuration = 0L
7171

7272
init {
73-
if (!timerRepository.serviceRunning)
73+
if (!timerRepository.serviceRunning.value)
7474
viewModelScope.launch(Dispatchers.IO) {
7575
timerRepository.focusTime =
7676
preferenceRepository.getIntPreference("focus_time")?.toLong()

0 commit comments

Comments
 (0)