feat: Implement persistent storage of chosen alarm sound

#36
This commit is contained in:
Nishant Mishra
2025-09-15 23:41:58 +05:30
parent 9c33406151
commit 37c74dc844
7 changed files with 243 additions and 20 deletions

View File

@@ -0,0 +1,133 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "4691d636a1c16c8cd33dc1bf0602190c",
"entities": [
{
"tableName": "int_preference",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` INTEGER NOT NULL, PRIMARY KEY(`key`))",
"fields": [
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"key"
]
}
},
{
"tableName": "boolean_preference",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` INTEGER NOT NULL, PRIMARY KEY(`key`))",
"fields": [
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"key"
]
}
},
{
"tableName": "string_preference",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` TEXT NOT NULL, PRIMARY KEY(`key`))",
"fields": [
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"key"
]
}
},
{
"tableName": "stat",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`date` TEXT NOT NULL, `focusTimeQ1` INTEGER NOT NULL, `focusTimeQ2` INTEGER NOT NULL, `focusTimeQ3` INTEGER NOT NULL, `focusTimeQ4` INTEGER NOT NULL, `breakTime` INTEGER NOT NULL, PRIMARY KEY(`date`))",
"fields": [
{
"fieldPath": "date",
"columnName": "date",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "focusTimeQ1",
"columnName": "focusTimeQ1",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "focusTimeQ2",
"columnName": "focusTimeQ2",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "focusTimeQ3",
"columnName": "focusTimeQ3",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "focusTimeQ4",
"columnName": "focusTimeQ4",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "breakTime",
"columnName": "breakTime",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"date"
]
}
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '4691d636a1c16c8cd33dc1bf0602190c')"
]
}
}

View File

@@ -8,14 +8,18 @@
package org.nsh07.pomodoro.data
import android.content.Context
import androidx.room.AutoMigration
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
@Database(
entities = [IntPreference::class, Stat::class],
version = 1
entities = [IntPreference::class, BooleanPreference::class, StringPreference::class, Stat::class],
version = 2,
autoMigrations = [
AutoMigration(from = 1, to = 2)
]
)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {

View File

@@ -11,7 +11,17 @@ import androidx.room.Entity
import androidx.room.PrimaryKey
/**
* Class for storing app preferences (settings) in the app's database
* Class for storing boolean preferences in the app's database
*/
@Entity(tableName = "boolean_preference")
data class BooleanPreference(
@PrimaryKey
val key: String,
val value: Boolean
)
/**
* Class for storing integer preferences in the app's database
*/
@Entity(tableName = "int_preference")
data class IntPreference(
@@ -19,3 +29,13 @@ data class IntPreference(
val key: String,
val value: Int
)
/**
* Class for storing string preferences in the app's database
*/
@Entity(tableName = "string_preference")
data class StringPreference(
@PrimaryKey
val key: String,
val value: String
)

View File

@@ -17,9 +17,27 @@ interface PreferenceDao {
@Insert(onConflict = REPLACE)
suspend fun insertIntPreference(preference: IntPreference)
@Insert(onConflict = REPLACE)
suspend fun insertBooleanPreference(preference: BooleanPreference)
@Insert(onConflict = REPLACE)
suspend fun insertStringPreference(preference: StringPreference)
@Query("DELETE FROM int_preference")
suspend fun resetIntPreferences()
@Query("DELETE FROM boolean_preference")
suspend fun resetBooleanPreferences()
@Query("DELETE FROM string_preference")
suspend fun resetStringPreferences()
@Query("SELECT value FROM int_preference WHERE `key` = :key")
suspend fun getIntPreference(key: String): Int?
@Query("SELECT value FROM boolean_preference WHERE `key` = :key")
suspend fun getBooleanPreference(key: String): Boolean?
@Query("SELECT value FROM string_preference WHERE `key` = :key")
suspend fun getStringPreference(key: String): String?
}

View File

@@ -22,11 +22,31 @@ interface PreferenceRepository {
*/
suspend fun saveIntPreference(key: String, value: Int): Int
/**
* Saves a boolean preference key-value pair to the database.
*/
suspend fun saveBooleanPreference(key: String, value: Boolean): Boolean
/**
* Saves a string preference key-value pair to the database.
*/
suspend fun saveStringPreference(key: String, value: String): String
/**
* Retrieves an integer preference key-value pair from the database.
*/
suspend fun getIntPreference(key: String): Int?
/**
* Retrieves a boolean preference key-value pair from the database.
*/
suspend fun getBooleanPreference(key: String): Boolean?
/**
* Retrieves a string preference key-value pair from the database.
*/
suspend fun getStringPreference(key: String): String?
/**
* Erases all integer preference key-value pairs in the database. Do note that the default values
* will need to be rewritten manually
@@ -47,11 +67,33 @@ class AppPreferenceRepository(
value
}
override suspend fun saveBooleanPreference(key: String, value: Boolean): Boolean =
withContext(ioDispatcher) {
preferenceDao.insertBooleanPreference(BooleanPreference(key, value))
value
}
override suspend fun saveStringPreference(key: String, value: String): String =
withContext(ioDispatcher) {
preferenceDao.insertStringPreference(StringPreference(key, value))
value
}
override suspend fun getIntPreference(key: String): Int? = withContext(ioDispatcher) {
preferenceDao.getIntPreference(key)
}
override suspend fun getBooleanPreference(key: String): Boolean? = withContext(ioDispatcher) {
preferenceDao.getBooleanPreference(key)
}
override suspend fun getStringPreference(key: String): String? = withContext(ioDispatcher) {
preferenceDao.getStringPreference(key)
}
override suspend fun resetSettings() = withContext(ioDispatcher) {
preferenceDao.resetIntPreferences()
preferenceDao.resetBooleanPreferences()
preferenceDao.resetStringPreferences()
}
}

View File

@@ -110,7 +110,7 @@ class SettingsViewModel(
fun saveAlarmEnabled(enabled: Boolean) {
viewModelScope.launch {
timerRepository.alarmEnabled = preferenceRepository
.saveIntPreference("alarm_enabled", if (enabled) 1 else 0) == 1
.saveBooleanPreference("alarm_enabled", enabled)
_alarmEnabled.value = enabled
}
}
@@ -118,14 +118,17 @@ class SettingsViewModel(
fun saveVibrateEnabled(enabled: Boolean) {
viewModelScope.launch {
timerRepository.vibrateEnabled = preferenceRepository
.saveIntPreference("vibrate_enabled", if (enabled) 1 else 0) == 1
.saveBooleanPreference("vibrate_enabled", enabled)
_vibrateEnabled.value = enabled
}
}
fun saveAlarmSound(uri: Uri?) {
timerRepository.alarmSoundUri = uri
_alarmSound.value = uri
viewModelScope.launch {
preferenceRepository.saveStringPreference("alarm_sound", uri.toString())
timerRepository.alarmSoundUri = uri
_alarmSound.value = uri
}
}
companion object {

View File

@@ -8,7 +8,9 @@
package org.nsh07.pomodoro.ui.timerScreen.viewModel
import android.app.Application
import android.provider.Settings
import androidx.compose.material3.ColorScheme
import androidx.core.net.toUri
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
@@ -77,20 +79,21 @@ class TimerViewModel(
timerRepository.sessionLength
)
timerRepository.alarmEnabled = (
preferenceRepository.getIntPreference("alarm_enabled")
?: preferenceRepository.saveIntPreference(
"alarm_enabled",
1
timerRepository.alarmEnabled =
preferenceRepository.getBooleanPreference("alarm_enabled")
?: preferenceRepository.saveBooleanPreference("alarm_enabled", true)
timerRepository.vibrateEnabled =
preferenceRepository.getBooleanPreference("vibrate_enabled")
?: preferenceRepository.saveBooleanPreference("vibrate_enabled", true)
timerRepository.alarmSoundUri = (
preferenceRepository.getStringPreference("alarm_sound")
?: preferenceRepository.saveStringPreference(
"alarm_sound",
(Settings.System.DEFAULT_ALARM_ALERT_URI
?: Settings.System.DEFAULT_RINGTONE_URI).toString()
)
) == 1
timerRepository.vibrateEnabled = (
preferenceRepository.getIntPreference("vibrate_enabled")
?: preferenceRepository.saveIntPreference(
"vibrate_enabled",
1
)
) == 1
).toUri()
resetTimer()