feat: datastore for settings with repository

This commit is contained in:
Emma Vandewalle 2024-07-23 19:05:56 +00:00 committed by Robin Meersman
parent bfd19884a7
commit 0016931726
8 changed files with 274 additions and 0 deletions

View file

@ -0,0 +1,31 @@
package be.re.writand.data.local
import androidx.datastore.core.CorruptionException
import androidx.datastore.core.Serializer
import be.re.writand.ProtoSettings
import com.google.protobuf.InvalidProtocolBufferException
import java.io.InputStream
import java.io.OutputStream
import javax.inject.Inject
/**
* Serializer that helps with storing and transferring the data of the UserSettings DataStore.
*/
class SettingsSerializer @Inject constructor() : Serializer<ProtoSettings> {
override val defaultValue: ProtoSettings = ProtoSettings.getDefaultInstance()
override suspend fun readFrom(input: InputStream): ProtoSettings {
try {
return ProtoSettings.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception)
}
}
override suspend fun writeTo(
t: ProtoSettings,
output: OutputStream
) = t.writeTo(output)
}

View file

@ -0,0 +1,35 @@
package be.re.writand.data.local.models
/**
* Enum class containing the possible languages supported by the app.
*/
enum class UserLanguage {
ENGLISH,
DUTCH
}
/**
* Enum class containing the possible themes supported by the app.
*/
enum class UserTheme {
DARK,
LIGHT
}
/**
* Data class that stores all the information of the user settings.
* @param[userLanguage] the language used in the app, by default English.
* @param[userTheme] the theme that is currently used by the user or the default dark theme.
* @param[maxSavedProjects] the amount of different projects to save extra information
* on the local device such as UserSettings and ProjectEntity.
* @param[maxSavedFiles] the amount of open files to be saved per project in local storage
* for when the project is opened again.
* @param[fontSize] font size used in the GUI.
*/
data class UserSettings(
var userLanguage: UserLanguage = UserLanguage.ENGLISH,
var userTheme: UserTheme = UserTheme.DARK,
var maxSavedProjects: Int = 3,
var maxSavedFiles: Int = 5,
var fontSize: Int = 10
)

View file

@ -0,0 +1,23 @@
package be.re.writand.data.repos.settings
import be.re.writand.data.local.models.UserLanguage
import be.re.writand.data.local.models.UserSettings
import be.re.writand.data.local.models.UserTheme
/**
* Repository containing getters and setters to interact with all of the user settings
*/
interface IUserSettingsRepository {
suspend fun getUserSettings(): UserSettings
suspend fun setLanguage(userLanguage: UserLanguage)
suspend fun setTheme(userTheme: UserTheme)
suspend fun setMaxSavedProjects(maxSaved: Int)
suspend fun setMaxSavedFiles(maxSaved: Int)
suspend fun setFontSize(size: Int)
}

View file

@ -0,0 +1,72 @@
package be.re.writand.data.repos.settings
import androidx.datastore.core.DataStore
import be.re.writand.ProtoSettings
import be.re.writand.data.local.models.UserLanguage
import be.re.writand.data.local.models.UserSettings
import be.re.writand.data.local.models.UserTheme
import be.re.writand.utils.toProtoLanguage
import be.re.writand.utils.toProtoTheme
import be.re.writand.utils.toUserLanguage
import be.re.writand.utils.toUserTheme
import kotlinx.coroutines.flow.first
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class UserSettingsRepository @Inject constructor(
private val store: DataStore<ProtoSettings>
) : IUserSettingsRepository {
private val userSettings = store.data
override suspend fun getUserSettings(): UserSettings {
return UserSettings(
userLanguage = userSettings.first().language.toUserLanguage(),
userTheme = userSettings.first().theme.toUserTheme(),
maxSavedProjects = userSettings.first().maxSavedProjects,
maxSavedFiles = userSettings.first().maxSavedFiles,
fontSize = userSettings.first().fontSize
)
}
override suspend fun setLanguage(userLanguage: UserLanguage) {
store.updateData {
val builder = it.toBuilder()
builder.setLanguage(userLanguage.toProtoLanguage())
builder.build()
}
}
override suspend fun setTheme(userTheme: UserTheme) {
store.updateData {
val builder = it.toBuilder()
builder.setTheme(userTheme.toProtoTheme())
builder.build()
}
}
override suspend fun setMaxSavedProjects(maxSaved: Int) {
store.updateData {
val builder = it.toBuilder()
builder.setMaxSavedProjects(maxSaved)
builder.build()
}
}
override suspend fun setMaxSavedFiles(maxSaved: Int) {
store.updateData {
val builder = it.toBuilder()
builder.setMaxSavedFiles(maxSaved)
builder.build()
}
}
override suspend fun setFontSize(size: Int) {
store.updateData {
val builder = it.toBuilder()
builder.setFontSize(size)
builder.build()
}
}
}

View file

@ -0,0 +1,31 @@
package be.re.writand.di
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.core.DataStoreFactory
import androidx.datastore.dataStoreFile
import be.re.writand.ProtoSettings
import be.re.writand.data.local.SettingsSerializer
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
/**
* Stores data locally, contains the settings information (see file: settings.proto).
*/
@InstallIn(SingletonComponent::class)
@Module
class DataStoreModule {
@Singleton
@Provides
fun provideDataStore(
@ApplicationContext context: Context,
serializer: SettingsSerializer
): DataStore<ProtoSettings> =
DataStoreFactory.create(serializer = serializer) {
context.dataStoreFile("settings.proto")
}
}

View file

@ -0,0 +1,50 @@
package be.re.writand.utils
import be.re.writand.ProtoLanguage
import be.re.writand.ProtoTheme
import be.re.writand.data.local.models.UserLanguage
import be.re.writand.data.local.models.UserTheme
/**
* Method of ProtoLanguage to get the corresponding UserLanguage.
*/
fun ProtoLanguage.toUserLanguage(): UserLanguage {
return if (this == ProtoLanguage.PROTO_LANGUAGE_ENGLISH) {
UserLanguage.ENGLISH
} else {
UserLanguage.DUTCH
}
}
/**
* Method of UserLanguage to get the corresponding ProtoLanguage.
*/
fun UserLanguage.toProtoLanguage(): ProtoLanguage {
return if (this == UserLanguage.ENGLISH) {
ProtoLanguage.PROTO_LANGUAGE_ENGLISH
} else {
ProtoLanguage.PROTO_LANGUAGE_DUTCH
}
}
/**
* Method of ProtoTheme to get the corresponding UserTheme.
*/
fun ProtoTheme.toUserTheme(): UserTheme {
return if (this == ProtoTheme.PROTO_THEME_DARK) {
UserTheme.DARK
} else {
UserTheme.LIGHT
}
}
/**
* Method of UserTheme to get the corresponding ProtoTheme.
*/
fun UserTheme.toProtoTheme(): ProtoTheme {
return if (this == UserTheme.DARK) {
ProtoTheme.PROTO_THEME_DARK
} else {
ProtoTheme.PROTO_THEME_LIGHT
}
}

View file

@ -0,0 +1,32 @@
syntax = "proto3";
option java_package = "be.re.writand";
option java_multiple_files = true;
/**
* The available languages supported by the app that will be stored locally.
*/
enum ProtoLanguage {
PROTO_LANGUAGE_ENGLISH = 0;
PROTO_LANGUAGE_DUTCH = 1;
}
/**
* The available themes supported by the app that will be stored locally.
*/
enum ProtoTheme {
PROTO_THEME_DARK = 0;
PROTO_THEME_LIGHT = 1;
}
/**
* The structure of what user settings holds, this is stored locally.
* NOTE: the "= x" does not initialize the values of the elements, these are field numbers.
*/
message ProtoSettings {
ProtoLanguage language = 1;
ProtoTheme theme = 2;
uint32 max_saved_projects = 3;
uint32 max_saved_files = 4;
uint32 font_size = 5;
};