feat(settings): add settings management with DataStore integration

This commit is contained in:
2026-05-03 14:16:37 +02:00
parent a41836b925
commit f925ca57ea
5 changed files with 159 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
package hu.bbara.purefin.settings
sealed interface SettingOption<T> {
val key: String
val defaultValue: T
}
data class NumberSetting(
override val key: String,
override val defaultValue: Double
) : SettingOption<Double>
data class BooleanSetting(
override val key: String,
override val defaultValue: Boolean
) : SettingOption<Boolean>
data class StringSetting(
override val key: String,
override val defaultValue: String
) : SettingOption<String>

View File

@@ -0,0 +1,41 @@
package hu.bbara.purefin.settings
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.core.DataStoreFactory
import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
import androidx.datastore.dataStoreFile
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import hu.bbara.purefin.model.Settings
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class SettingsModule {
@Provides
@Singleton
fun provideSettingsDataStore(
@ApplicationContext context: Context
): DataStore<Settings> {
return DataStoreFactory.create(
serializer = SettingsSerializer,
produceFile = { context.dataStoreFile("settings.json") },
corruptionHandler = ReplaceFileCorruptionHandler(
produceNewData = { SettingsSerializer.defaultValue }
)
)
}
@Provides
@Singleton
fun provideSettingsRepository(
settingsDataStore: DataStore<Settings>
): SettingsRepository {
return SettingsRepository(settingsDataStore)
}
}

View File

@@ -0,0 +1,56 @@
package hu.bbara.purefin.settings
import androidx.datastore.core.DataStore
import hu.bbara.purefin.model.Settings
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import javax.inject.Inject
class SettingsRepository @Inject constructor(
private val settingsDataStore: DataStore<Settings>
) {
val settings: Flow<Settings> = settingsDataStore.data
fun value(option: NumberSetting): Flow<Double> {
return settings
.map { it.numberSettings[option.key] ?: option.defaultValue }
.distinctUntilChanged()
}
fun value(option: BooleanSetting): Flow<Boolean> {
return settings
.map { it.booleanSettings[option.key] ?: option.defaultValue }
.distinctUntilChanged()
}
fun value(option: StringSetting): Flow<String> {
return settings
.map { it.stringSettings[option.key] ?: option.defaultValue }
.distinctUntilChanged()
}
suspend fun set(option: NumberSetting, value: Double) {
settingsDataStore.updateData { current ->
current.copy(
numberSettings = current.numberSettings + (option.key to value)
)
}
}
suspend fun set(option: BooleanSetting, value: Boolean) {
settingsDataStore.updateData { current ->
current.copy(
booleanSettings = current.booleanSettings + (option.key to value)
)
}
}
suspend fun set(option: StringSetting, value: String) {
settingsDataStore.updateData { current ->
current.copy(
stringSettings = current.stringSettings + (option.key to value)
)
}
}
}

View File

@@ -0,0 +1,31 @@
package hu.bbara.purefin.settings
import androidx.datastore.core.CorruptionException
import androidx.datastore.core.Serializer
import hu.bbara.purefin.model.Settings
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
import java.io.InputStream
import java.io.OutputStream
object SettingsSerializer : Serializer<Settings> {
override val defaultValue: Settings
get() = Settings()
override suspend fun readFrom(input: InputStream): Settings {
try {
return Json.decodeFromString<Settings>(
input.readBytes().decodeToString()
)
} catch (serialization: SerializationException) {
throw CorruptionException("Unable to read Settings", serialization)
}
}
override suspend fun writeTo(t: Settings, output: OutputStream) {
output.write(
Json.encodeToString(Settings.serializer(), t)
.encodeToByteArray()
)
}
}