Skip to content

Commit e1fa6c2

Browse files
committed
refactor(settings): move state variables to single state class
#117
1 parent 538c984 commit e1fa6c2

File tree

9 files changed

+59
-91
lines changed

9 files changed

+59
-91
lines changed

app/src/foss/java/org/nsh07/pomodoro/billing/FossBillingManager.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import kotlinx.coroutines.flow.asStateFlow
2525
*/
2626
class FossBillingManager : BillingManager {
2727
override val isPlus = MutableStateFlow(true).asStateFlow()
28-
override val isLoaded = MutableStateFlow(true).asStateFlow()
2928
}
3029

3130
object BillingManagerProvider {

app/src/main/java/org/nsh07/pomodoro/MainActivity.kt

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,6 @@ class MainActivity : ComponentActivity() {
6161
val seed = settingsState.colorScheme.toColor()
6262

6363
val isPlus by settingsViewModel.isPlus.collectAsStateWithLifecycle()
64-
val isPurchaseStateLoaded by settingsViewModel.isPurchaseStateLoaded.collectAsStateWithLifecycle()
65-
val isSettingsLoaded by settingsViewModel.isSettingsLoaded.collectAsStateWithLifecycle()
66-
67-
LaunchedEffect(isPurchaseStateLoaded, isPlus, isSettingsLoaded) {
68-
if (isPurchaseStateLoaded && isSettingsLoaded) {
69-
if (!isPlus) {
70-
settingsViewModel.resetPaywalledSettings()
71-
} else {
72-
settingsViewModel.reloadSettings()
73-
}
74-
}
75-
}
7664

7765
TomatoTheme(
7866
darkTheme = darkTheme,

app/src/main/java/org/nsh07/pomodoro/billing/BillingManager.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,4 @@ import kotlinx.coroutines.flow.StateFlow
2121

2222
interface BillingManager {
2323
val isPlus: StateFlow<Boolean>
24-
val isLoaded: StateFlow<Boolean>
2524
}

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

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,6 @@ fun SettingsScreenRoot(
101101
val longBreakTimeInputFieldState = viewModel.longBreakTimeTextFieldState
102102

103103
val isPlus by viewModel.isPlus.collectAsStateWithLifecycle()
104-
val alarmEnabled by viewModel.alarmEnabled.collectAsStateWithLifecycle(true)
105-
val vibrateEnabled by viewModel.vibrateEnabled.collectAsStateWithLifecycle(true)
106-
val dndEnabled by viewModel.dndEnabled.collectAsStateWithLifecycle(false)
107-
val alarmSound by viewModel.alarmSound.collectAsStateWithLifecycle(viewModel.currentAlarmSound)
108104

109105
val settingsState by viewModel.settingsState.collectAsStateWithLifecycle()
110106

@@ -125,10 +121,6 @@ fun SettingsScreenRoot(
125121
shortBreakTimeInputFieldState = shortBreakTimeInputFieldState,
126122
longBreakTimeInputFieldState = longBreakTimeInputFieldState,
127123
sessionsSliderState = sessionsSliderState,
128-
alarmEnabled = alarmEnabled,
129-
vibrateEnabled = vibrateEnabled,
130-
dndEnabled = dndEnabled,
131-
alarmSound = alarmSound,
132124
onAction = viewModel::onAction,
133125
setShowPaywall = setShowPaywall,
134126
modifier = modifier
@@ -146,10 +138,6 @@ private fun SettingsScreen(
146138
shortBreakTimeInputFieldState: TextFieldState,
147139
longBreakTimeInputFieldState: TextFieldState,
148140
sessionsSliderState: SliderState,
149-
alarmEnabled: Boolean,
150-
vibrateEnabled: Boolean,
151-
dndEnabled: Boolean,
152-
alarmSound: String,
153141
onAction: (SettingsAction) -> Unit,
154142
setShowPaywall: (Boolean) -> Unit,
155143
modifier: Modifier = Modifier
@@ -288,9 +276,6 @@ private fun SettingsScreen(
288276
entry<Screen.Settings.Alarm> {
289277
AlarmSettings(
290278
settingsState = settingsState,
291-
alarmEnabled = alarmEnabled,
292-
vibrateEnabled = vibrateEnabled,
293-
alarmSound = alarmSound,
294279
onAction = onAction,
295280
onBack = backStack::removeLastOrNull
296281
)
@@ -307,8 +292,7 @@ private fun SettingsScreen(
307292
entry<Screen.Settings.Timer> {
308293
TimerSettings(
309294
isPlus = isPlus,
310-
aodEnabled = settingsState.aodEnabled,
311-
dndEnabled = dndEnabled,
295+
settingsState = settingsState,
312296
focusTimeInputFieldState = focusTimeInputFieldState,
313297
shortBreakTimeInputFieldState = shortBreakTimeInputFieldState,
314298
longBreakTimeInputFieldState = longBreakTimeInputFieldState,

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

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape
7979
@Composable
8080
fun AlarmSettings(
8181
settingsState: SettingsState,
82-
alarmEnabled: Boolean,
83-
vibrateEnabled: Boolean,
84-
alarmSound: String,
8582
onAction: (SettingsAction) -> Unit,
8683
onBack: () -> Unit,
8784
modifier: Modifier = Modifier
@@ -91,10 +88,11 @@ fun AlarmSettings(
9188

9289
var alarmName by remember { mutableStateOf("...") }
9390

94-
LaunchedEffect(alarmSound) {
91+
LaunchedEffect(settingsState.alarmSound) {
9592
withContext(Dispatchers.IO) {
9693
alarmName =
97-
RingtoneManager.getRingtone(context, alarmSound.toUri())?.getTitle(context) ?: ""
94+
RingtoneManager.getRingtone(context, settingsState.alarmSound.toUri())
95+
?.getTitle(context) ?: ""
9896
}
9997
}
10098

@@ -117,30 +115,30 @@ fun AlarmSettings(
117115
}
118116

119117
@SuppressLint("LocalContextGetResourceValueCall")
120-
val ringtonePickerIntent = remember(alarmSound) {
118+
val ringtonePickerIntent = remember(settingsState.alarmSound) {
121119
Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply {
122120
putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM)
123121
putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, context.getString(R.string.alarm_sound))
124-
putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, alarmSound.toUri())
122+
putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, settingsState.alarmSound.toUri())
125123
}
126124
}
127125

128126
val switchItems = remember(
129127
settingsState.blackTheme,
130128
settingsState.aodEnabled,
131-
alarmEnabled,
132-
vibrateEnabled
129+
settingsState.alarmEnabled,
130+
settingsState.vibrateEnabled
133131
) {
134132
listOf(
135133
SettingsSwitchItem(
136-
checked = alarmEnabled,
134+
checked = settingsState.alarmEnabled,
137135
icon = R.drawable.alarm_on,
138136
label = R.string.sound,
139137
description = R.string.alarm_desc,
140138
onClick = { onAction(SettingsAction.SaveAlarmEnabled(it)) }
141139
),
142140
SettingsSwitchItem(
143-
checked = vibrateEnabled,
141+
checked = settingsState.vibrateEnabled,
144142
icon = R.drawable.mobile_vibrate,
145143
label = R.string.vibrate,
146144
description = R.string.vibrate_desc,
@@ -245,9 +243,7 @@ fun AlarmSettingsPreview() {
245243
val settingsState = SettingsState()
246244
AlarmSettings(
247245
settingsState = settingsState,
248-
alarmEnabled = true,
249-
vibrateEnabled = false,
250-
alarmSound = "",
251246
onAction = {},
252-
onBack = {})
247+
onBack = {}
248+
)
253249
}

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import androidx.compose.foundation.lazy.itemsIndexed
4141
import androidx.compose.foundation.rememberScrollState
4242
import androidx.compose.foundation.shape.RoundedCornerShape
4343
import androidx.compose.foundation.text.input.TextFieldState
44+
import androidx.compose.foundation.text.input.rememberTextFieldState
4445
import androidx.compose.material3.ExperimentalMaterial3Api
4546
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
4647
import androidx.compose.material3.FilledTonalIconToggleButton
@@ -57,6 +58,7 @@ import androidx.compose.material3.Switch
5758
import androidx.compose.material3.SwitchDefaults
5859
import androidx.compose.material3.Text
5960
import androidx.compose.material3.TopAppBarDefaults
61+
import androidx.compose.material3.rememberSliderState
6062
import androidx.compose.runtime.Composable
6163
import androidx.compose.runtime.LaunchedEffect
6264
import androidx.compose.runtime.getValue
@@ -78,6 +80,7 @@ import org.nsh07.pomodoro.ui.settingsScreen.SettingsSwitchItem
7880
import org.nsh07.pomodoro.ui.settingsScreen.components.MinuteInputField
7981
import org.nsh07.pomodoro.ui.settingsScreen.components.PlusDivider
8082
import org.nsh07.pomodoro.ui.settingsScreen.viewModel.SettingsAction
83+
import org.nsh07.pomodoro.ui.settingsScreen.viewModel.SettingsState
8184
import org.nsh07.pomodoro.ui.theme.AppFonts.robotoFlexTopBar
8285
import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors
8386
import org.nsh07.pomodoro.ui.theme.CustomColors.switchColors
@@ -92,14 +95,13 @@ import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape
9295
@Composable
9396
fun TimerSettings(
9497
isPlus: Boolean,
95-
aodEnabled: Boolean,
96-
dndEnabled: Boolean,
98+
settingsState: SettingsState,
9799
focusTimeInputFieldState: TextFieldState,
98100
shortBreakTimeInputFieldState: TextFieldState,
99101
longBreakTimeInputFieldState: TextFieldState,
100102
sessionsSliderState: SliderState,
101-
setShowPaywall: (Boolean) -> Unit,
102103
onAction: (SettingsAction) -> Unit,
104+
setShowPaywall: (Boolean) -> Unit,
103105
onBack: () -> Unit,
104106
modifier: Modifier = Modifier
105107
) {
@@ -116,7 +118,7 @@ fun TimerSettings(
116118

117119
val switchItems = listOf(
118120
SettingsSwitchItem(
119-
checked = dndEnabled,
121+
checked = settingsState.dndEnabled,
120122
icon = R.drawable.dnd,
121123
label = R.string.dnd,
122124
description = R.string.dnd_desc,
@@ -133,7 +135,7 @@ fun TimerSettings(
133135
}
134136
),
135137
SettingsSwitchItem(
136-
checked = aodEnabled,
138+
checked = settingsState.aodEnabled,
137139
icon = R.drawable.aod,
138140
label = R.string.always_on_display,
139141
description = R.string.always_on_display_desc,
@@ -393,18 +395,17 @@ fun TimerSettings(
393395
@Preview
394396
@Composable
395397
private fun TimerSettingsPreview() {
396-
val focusTimeInputFieldState = TextFieldState("25")
397-
val shortBreakTimeInputFieldState = TextFieldState("5")
398-
val longBreakTimeInputFieldState = TextFieldState("15")
399-
val sessionsSliderState = SliderState(
398+
val focusTimeInputFieldState = rememberTextFieldState("25")
399+
val shortBreakTimeInputFieldState = rememberTextFieldState("5")
400+
val longBreakTimeInputFieldState = rememberTextFieldState("15")
401+
val sessionsSliderState = rememberSliderState(
400402
value = 4f,
401403
valueRange = 1f..8f,
402404
steps = 6
403405
)
404406
TimerSettings(
405407
isPlus = false,
406-
aodEnabled = true,
407-
dndEnabled = false,
408+
settingsState = remember { SettingsState() },
408409
focusTimeInputFieldState = focusTimeInputFieldState,
409410
shortBreakTimeInputFieldState = shortBreakTimeInputFieldState,
410411
longBreakTimeInputFieldState = longBreakTimeInputFieldState,

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ import androidx.compose.ui.graphics.Color
2323
@Immutable
2424
data class SettingsState(
2525
val theme: String = "auto",
26+
val alarmSound: String = "",
2627
val colorScheme: String = Color.White.toString(),
2728
val blackTheme: Boolean = false,
28-
val aodEnabled: Boolean = false
29+
val aodEnabled: Boolean = false,
30+
val alarmEnabled: Boolean = true,
31+
val vibrateEnabled: Boolean = true,
32+
val dndEnabled: Boolean = false
2933
)

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

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.nsh07.pomodoro.ui.settingsScreen.viewModel
1919

2020
import android.net.Uri
21+
import android.provider.Settings
2122
import androidx.compose.foundation.text.input.TextFieldState
2223
import androidx.compose.material3.ExperimentalMaterial3Api
2324
import androidx.compose.material3.SliderState
@@ -36,7 +37,6 @@ import kotlinx.coroutines.Job
3637
import kotlinx.coroutines.flow.MutableStateFlow
3738
import kotlinx.coroutines.flow.asStateFlow
3839
import kotlinx.coroutines.flow.debounce
39-
import kotlinx.coroutines.flow.distinctUntilChanged
4040
import kotlinx.coroutines.flow.update
4141
import kotlinx.coroutines.launch
4242
import org.nsh07.pomodoro.TomatoApplication
@@ -54,10 +54,6 @@ class SettingsViewModel(
5454
val backStack = mutableStateListOf<Screen.Settings>(Screen.Settings.Main)
5555

5656
val isPlus = billingManager.isPlus
57-
val isPurchaseStateLoaded = billingManager.isLoaded
58-
59-
private val _isSettingsLoaded = MutableStateFlow(false)
60-
val isSettingsLoaded = _isSettingsLoaded.asStateFlow()
6157

6258
private val _settingsState = MutableStateFlow(SettingsState())
6359
val settingsState = _settingsState.asStateFlow()
@@ -81,25 +77,13 @@ class SettingsViewModel(
8177
)
8278
}
8379

84-
val currentAlarmSound = timerRepository.alarmSoundUri.toString()
85-
8680
private var focusFlowCollectionJob: Job? = null
8781
private var shortBreakFlowCollectionJob: Job? = null
8882
private var longBreakFlowCollectionJob: Job? = null
8983

90-
val alarmSound =
91-
preferenceRepository.getStringPreferenceFlow("alarm_sound").distinctUntilChanged()
92-
val alarmEnabled =
93-
preferenceRepository.getBooleanPreferenceFlow("alarm_enabled").distinctUntilChanged()
94-
val vibrateEnabled =
95-
preferenceRepository.getBooleanPreferenceFlow("vibrate_enabled").distinctUntilChanged()
96-
val dndEnabled =
97-
preferenceRepository.getBooleanPreferenceFlow("dnd_enabled").distinctUntilChanged()
98-
9984
init {
10085
viewModelScope.launch {
10186
reloadSettings()
102-
_isSettingsLoaded.value = true
10387
}
10488
}
10589

@@ -176,27 +160,39 @@ class SettingsViewModel(
176160
private fun saveAlarmEnabled(enabled: Boolean) {
177161
viewModelScope.launch {
178162
timerRepository.alarmEnabled = enabled
163+
_settingsState.update { currentState ->
164+
currentState.copy(alarmEnabled = enabled)
165+
}
179166
preferenceRepository.saveBooleanPreference("alarm_enabled", enabled)
180167
}
181168
}
182169

183170
private fun saveVibrateEnabled(enabled: Boolean) {
184171
viewModelScope.launch {
185172
timerRepository.vibrateEnabled = enabled
173+
_settingsState.update { currentState ->
174+
currentState.copy(vibrateEnabled = enabled)
175+
}
186176
preferenceRepository.saveBooleanPreference("vibrate_enabled", enabled)
187177
}
188178
}
189179

190180
private fun saveDndEnabled(enabled: Boolean) {
191181
viewModelScope.launch {
192182
timerRepository.dndEnabled = enabled
183+
_settingsState.update { currentState ->
184+
currentState.copy(dndEnabled = enabled)
185+
}
193186
preferenceRepository.saveBooleanPreference("dnd_enabled", enabled)
194187
}
195188
}
196189

197190
private fun saveAlarmSound(uri: Uri?) {
198191
viewModelScope.launch {
199192
timerRepository.alarmSoundUri = uri
193+
_settingsState.update { currentState ->
194+
currentState.copy(alarmSound = uri.toString())
195+
}
200196
preferenceRepository.saveStringPreference("alarm_sound", uri.toString())
201197
}
202198
}
@@ -237,16 +233,6 @@ class SettingsViewModel(
237233
}
238234
}
239235

240-
fun resetPaywalledSettings() {
241-
_settingsState.update { currentState ->
242-
currentState.copy(
243-
aodEnabled = false,
244-
blackTheme = false,
245-
colorScheme = Color.White.toString()
246-
)
247-
}
248-
}
249-
250236
suspend fun reloadSettings() {
251237
val theme = preferenceRepository.getStringPreference("theme")
252238
?: preferenceRepository.saveStringPreference("theme", "auto")
@@ -256,13 +242,29 @@ class SettingsViewModel(
256242
?: preferenceRepository.saveBooleanPreference("black_theme", false)
257243
val aodEnabled = preferenceRepository.getBooleanPreference("aod_enabled")
258244
?: preferenceRepository.saveBooleanPreference("aod_enabled", false)
245+
val alarmSound = preferenceRepository.getStringPreference("alarm_sound")
246+
?: preferenceRepository.saveStringPreference(
247+
"alarm_sound",
248+
(Settings.System.DEFAULT_ALARM_ALERT_URI
249+
?: Settings.System.DEFAULT_RINGTONE_URI).toString()
250+
)
251+
val alarmEnabled = preferenceRepository.getBooleanPreference("alarm_enabled")
252+
?: preferenceRepository.saveBooleanPreference("alarm_enabled", true)
253+
val vibrateEnabled = preferenceRepository.getBooleanPreference("vibrate_enabled")
254+
?: preferenceRepository.saveBooleanPreference("vibrate_enabled", true)
255+
val dndEnabled = preferenceRepository.getBooleanPreference("dnd_enabled")
256+
?: preferenceRepository.saveBooleanPreference("dnd_enabled", false)
259257

260258
_settingsState.update { currentState ->
261259
currentState.copy(
262260
theme = theme,
263261
colorScheme = colorScheme,
262+
alarmSound = alarmSound,
264263
blackTheme = blackTheme,
265-
aodEnabled = aodEnabled
264+
aodEnabled = aodEnabled,
265+
alarmEnabled = alarmEnabled,
266+
vibrateEnabled = vibrateEnabled,
267+
dndEnabled = dndEnabled
266268
)
267269
}
268270
}

0 commit comments

Comments
 (0)