fix: Fix some major bugs with the URI to string (and vice versa) conversion
This commit is contained in:
@@ -11,6 +11,7 @@ import androidx.room.Dao
|
|||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy.Companion.REPLACE
|
import androidx.room.OnConflictStrategy.Companion.REPLACE
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface PreferenceDao {
|
interface PreferenceDao {
|
||||||
@@ -38,6 +39,12 @@ interface PreferenceDao {
|
|||||||
@Query("SELECT value FROM boolean_preference WHERE `key` = :key")
|
@Query("SELECT value FROM boolean_preference WHERE `key` = :key")
|
||||||
suspend fun getBooleanPreference(key: String): Boolean?
|
suspend fun getBooleanPreference(key: String): Boolean?
|
||||||
|
|
||||||
|
@Query("SELECT value FROM boolean_preference WHERE `key` = :key")
|
||||||
|
fun getBooleanPreferenceFlow(key: String): Flow<Boolean>
|
||||||
|
|
||||||
@Query("SELECT value FROM string_preference WHERE `key` = :key")
|
@Query("SELECT value FROM string_preference WHERE `key` = :key")
|
||||||
suspend fun getStringPreference(key: String): String?
|
suspend fun getStringPreference(key: String): String?
|
||||||
|
|
||||||
|
@Query("SELECT value FROM string_preference WHERE `key` = :key")
|
||||||
|
fun getStringPreferenceFlow(key: String): Flow<String>
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ package org.nsh07.pomodoro.data
|
|||||||
|
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,11 +43,21 @@ interface PreferenceRepository {
|
|||||||
*/
|
*/
|
||||||
suspend fun getBooleanPreference(key: String): Boolean?
|
suspend fun getBooleanPreference(key: String): Boolean?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a boolean preference key-value pair as a flow from the database.
|
||||||
|
*/
|
||||||
|
fun getBooleanPreferenceFlow(key: String): Flow<Boolean>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a string preference key-value pair from the database.
|
* Retrieves a string preference key-value pair from the database.
|
||||||
*/
|
*/
|
||||||
suspend fun getStringPreference(key: String): String?
|
suspend fun getStringPreference(key: String): String?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a string preference key-value pair as a flow from the database.
|
||||||
|
*/
|
||||||
|
fun getStringPreferenceFlow(key: String): Flow<String>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erases all integer preference key-value pairs in the database. Do note that the default values
|
* Erases all integer preference key-value pairs in the database. Do note that the default values
|
||||||
* will need to be rewritten manually
|
* will need to be rewritten manually
|
||||||
@@ -87,10 +98,16 @@ class AppPreferenceRepository(
|
|||||||
preferenceDao.getBooleanPreference(key)
|
preferenceDao.getBooleanPreference(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getBooleanPreferenceFlow(key: String): Flow<Boolean> =
|
||||||
|
preferenceDao.getBooleanPreferenceFlow(key)
|
||||||
|
|
||||||
override suspend fun getStringPreference(key: String): String? = withContext(ioDispatcher) {
|
override suspend fun getStringPreference(key: String): String? = withContext(ioDispatcher) {
|
||||||
preferenceDao.getStringPreference(key)
|
preferenceDao.getStringPreference(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getStringPreferenceFlow(key: String): Flow<String> =
|
||||||
|
preferenceDao.getStringPreferenceFlow(key)
|
||||||
|
|
||||||
override suspend fun resetSettings() = withContext(ioDispatcher) {
|
override suspend fun resetSettings() = withContext(ioDispatcher) {
|
||||||
preferenceDao.resetIntPreferences()
|
preferenceDao.resetIntPreferences()
|
||||||
preferenceDao.resetBooleanPreferences()
|
preferenceDao.resetBooleanPreferences()
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ import androidx.compose.ui.tooling.preview.Devices
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.core.net.toUri
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import org.nsh07.pomodoro.R
|
import org.nsh07.pomodoro.R
|
||||||
@@ -101,9 +102,9 @@ fun SettingsScreenRoot(
|
|||||||
viewModel.longBreakTimeTextFieldState
|
viewModel.longBreakTimeTextFieldState
|
||||||
}
|
}
|
||||||
|
|
||||||
val alarmEnabled by viewModel.alarmEnabled.collectAsStateWithLifecycle()
|
val alarmEnabled by viewModel.alarmEnabled.collectAsStateWithLifecycle(true)
|
||||||
val vibrateEnabled by viewModel.vibrateEnabled.collectAsStateWithLifecycle()
|
val vibrateEnabled by viewModel.vibrateEnabled.collectAsStateWithLifecycle(true)
|
||||||
val alarmSound by viewModel.alarmSound.collectAsStateWithLifecycle()
|
val alarmSound by viewModel.alarmSound.collectAsStateWithLifecycle("")
|
||||||
|
|
||||||
val sessionsSliderState = rememberSaveable(
|
val sessionsSliderState = rememberSaveable(
|
||||||
saver = SliderState.Saver(
|
saver = SliderState.Saver(
|
||||||
@@ -144,7 +145,7 @@ private fun SettingsScreen(
|
|||||||
sessionsSliderState: SliderState,
|
sessionsSliderState: SliderState,
|
||||||
alarmEnabled: Boolean,
|
alarmEnabled: Boolean,
|
||||||
vibrateEnabled: Boolean,
|
vibrateEnabled: Boolean,
|
||||||
alarmSound: Uri?,
|
alarmSound: String,
|
||||||
onAlarmEnabledChange: (Boolean) -> Unit,
|
onAlarmEnabledChange: (Boolean) -> Unit,
|
||||||
onVibrateEnabledChange: (Boolean) -> Unit,
|
onVibrateEnabledChange: (Boolean) -> Unit,
|
||||||
onAlarmSoundChanged: (Uri?) -> Unit,
|
onAlarmSoundChanged: (Uri?) -> Unit,
|
||||||
@@ -155,7 +156,7 @@ private fun SettingsScreen(
|
|||||||
checkedIconColor = colorScheme.primary,
|
checkedIconColor = colorScheme.primary,
|
||||||
)
|
)
|
||||||
|
|
||||||
var selectedSoundUri by remember { mutableStateOf(alarmSound) }
|
var selectedSoundUri by remember(alarmSound) { mutableStateOf(alarmSound.toUri()) }
|
||||||
var selectedSoundName by remember { mutableStateOf("...") }
|
var selectedSoundName by remember { mutableStateOf("...") }
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
@@ -173,7 +174,6 @@ private fun SettingsScreen(
|
|||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
result.data?.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
|
result.data?.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
|
||||||
}
|
}
|
||||||
selectedSoundUri = uri
|
|
||||||
onAlarmSoundChanged(uri)
|
onAlarmSoundChanged(uri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,7 +436,7 @@ fun SettingsScreenPreview() {
|
|||||||
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,
|
||||||
alarmSound = Settings.System.DEFAULT_ALARM_ALERT_URI,
|
alarmSound = Settings.System.DEFAULT_ALARM_ALERT_URI.toString(),
|
||||||
onAlarmEnabledChange = {},
|
onAlarmEnabledChange = {},
|
||||||
onVibrateEnabledChange = {},
|
onVibrateEnabledChange = {},
|
||||||
onAlarmSoundChanged = {},
|
onAlarmSoundChanged = {},
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ import androidx.lifecycle.viewmodel.initializer
|
|||||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.FlowPreview
|
import kotlinx.coroutines.FlowPreview
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import kotlinx.coroutines.flow.debounce
|
import kotlinx.coroutines.flow.debounce
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.nsh07.pomodoro.TomatoApplication
|
import org.nsh07.pomodoro.TomatoApplication
|
||||||
import org.nsh07.pomodoro.data.AppPreferenceRepository
|
import org.nsh07.pomodoro.data.AppPreferenceRepository
|
||||||
@@ -48,16 +46,12 @@ class SettingsViewModel(
|
|||||||
onValueChangeFinished = ::updateSessionLength
|
onValueChangeFinished = ::updateSessionLength
|
||||||
)
|
)
|
||||||
|
|
||||||
private val _alarmSound = MutableStateFlow(timerRepository.alarmSoundUri)
|
val alarmSound =
|
||||||
val alarmSound: StateFlow<Uri?> = _alarmSound.asStateFlow()
|
preferenceRepository.getStringPreferenceFlow("alarm_sound").distinctUntilChanged()
|
||||||
|
val alarmEnabled =
|
||||||
private val _alarmEnabled: MutableStateFlow<Boolean> =
|
preferenceRepository.getBooleanPreferenceFlow("alarm_enabled").distinctUntilChanged()
|
||||||
MutableStateFlow(timerRepository.alarmEnabled)
|
val vibrateEnabled =
|
||||||
val alarmEnabled: StateFlow<Boolean> = _alarmEnabled.asStateFlow()
|
preferenceRepository.getBooleanPreferenceFlow("vibrate_enabled").distinctUntilChanged()
|
||||||
|
|
||||||
private val _vibrateEnabled: MutableStateFlow<Boolean> =
|
|
||||||
MutableStateFlow(timerRepository.alarmEnabled)
|
|
||||||
val vibrateEnabled: StateFlow<Boolean> = _vibrateEnabled.asStateFlow()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
@@ -109,17 +103,15 @@ class SettingsViewModel(
|
|||||||
|
|
||||||
fun saveAlarmEnabled(enabled: Boolean) {
|
fun saveAlarmEnabled(enabled: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
timerRepository.alarmEnabled = preferenceRepository
|
preferenceRepository.saveBooleanPreference("alarm_enabled", enabled)
|
||||||
.saveBooleanPreference("alarm_enabled", enabled)
|
timerRepository.alarmEnabled = enabled
|
||||||
_alarmEnabled.value = enabled
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveVibrateEnabled(enabled: Boolean) {
|
fun saveVibrateEnabled(enabled: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
timerRepository.vibrateEnabled = preferenceRepository
|
preferenceRepository.saveBooleanPreference("vibrate_enabled", enabled)
|
||||||
.saveBooleanPreference("vibrate_enabled", enabled)
|
timerRepository.vibrateEnabled = enabled
|
||||||
_vibrateEnabled.value = enabled
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +119,6 @@ class SettingsViewModel(
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
preferenceRepository.saveStringPreference("alarm_sound", uri.toString())
|
preferenceRepository.saveStringPreference("alarm_sound", uri.toString())
|
||||||
timerRepository.alarmSoundUri = uri
|
timerRepository.alarmSoundUri = uri
|
||||||
_alarmSound.value = uri
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user