diff --git a/core-model/src/main/java/hu/bbara/purefin/model/Settings.kt b/core-model/src/main/java/hu/bbara/purefin/model/Settings.kt new file mode 100644 index 00000000..92d3c61f --- /dev/null +++ b/core-model/src/main/java/hu/bbara/purefin/model/Settings.kt @@ -0,0 +1,10 @@ +package hu.bbara.purefin.model + +import kotlinx.serialization.Serializable + +@Serializable +data class Settings( + val numberSettings: Map = emptyMap(), + val booleanSettings: Map = emptyMap(), + val stringSettings: Map = emptyMap() +) diff --git a/core/src/main/java/hu/bbara/purefin/settings/SettingOption.kt b/core/src/main/java/hu/bbara/purefin/settings/SettingOption.kt new file mode 100644 index 00000000..61464a6d --- /dev/null +++ b/core/src/main/java/hu/bbara/purefin/settings/SettingOption.kt @@ -0,0 +1,21 @@ +package hu.bbara.purefin.settings + +sealed interface SettingOption { + val key: String + val defaultValue: T +} + +data class NumberSetting( + override val key: String, + override val defaultValue: Double +) : SettingOption + +data class BooleanSetting( + override val key: String, + override val defaultValue: Boolean +) : SettingOption + +data class StringSetting( + override val key: String, + override val defaultValue: String +) : SettingOption diff --git a/core/src/main/java/hu/bbara/purefin/settings/SettingsModule.kt b/core/src/main/java/hu/bbara/purefin/settings/SettingsModule.kt new file mode 100644 index 00000000..eb8f25bf --- /dev/null +++ b/core/src/main/java/hu/bbara/purefin/settings/SettingsModule.kt @@ -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 { + return DataStoreFactory.create( + serializer = SettingsSerializer, + produceFile = { context.dataStoreFile("settings.json") }, + corruptionHandler = ReplaceFileCorruptionHandler( + produceNewData = { SettingsSerializer.defaultValue } + ) + ) + } + + @Provides + @Singleton + fun provideSettingsRepository( + settingsDataStore: DataStore + ): SettingsRepository { + return SettingsRepository(settingsDataStore) + } +} diff --git a/core/src/main/java/hu/bbara/purefin/settings/SettingsRepository.kt b/core/src/main/java/hu/bbara/purefin/settings/SettingsRepository.kt new file mode 100644 index 00000000..df541c1c --- /dev/null +++ b/core/src/main/java/hu/bbara/purefin/settings/SettingsRepository.kt @@ -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 +) { + val settings: Flow = settingsDataStore.data + + fun value(option: NumberSetting): Flow { + return settings + .map { it.numberSettings[option.key] ?: option.defaultValue } + .distinctUntilChanged() + } + + fun value(option: BooleanSetting): Flow { + return settings + .map { it.booleanSettings[option.key] ?: option.defaultValue } + .distinctUntilChanged() + } + + fun value(option: StringSetting): Flow { + 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) + ) + } + } +} diff --git a/core/src/main/java/hu/bbara/purefin/settings/SettingsSerializer.kt b/core/src/main/java/hu/bbara/purefin/settings/SettingsSerializer.kt new file mode 100644 index 00000000..98655dbf --- /dev/null +++ b/core/src/main/java/hu/bbara/purefin/settings/SettingsSerializer.kt @@ -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 { + override val defaultValue: Settings + get() = Settings() + + override suspend fun readFrom(input: InputStream): Settings { + try { + return Json.decodeFromString( + 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() + ) + } +}