Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ dependencies {
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${versions.lifecycle}")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:${versions.lifecycle}")

implementation("androidx.datastore:datastore-preferences:${versions.datastore}")

implementation "dk.nodes.nstack:nstack-kotlin:${versions.nodes_nstack_kotlin}"
implementation "com.jakewharton.timber:timber:${versions.timber}"

Expand Down
8 changes: 4 additions & 4 deletions app/src/main/java/com/monstarlab/arch/data/DataSource.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.monstarlab.arch.data

interface DataSource<T> {
fun getAll(): List<T>
fun add(item: T)
fun addAll(items: List<T>)
fun clear()
suspend fun getAll(): List<T>
suspend fun add(item: T)
suspend fun addAll(items: List<T>)
suspend fun clear()
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,49 @@
package com.monstarlab.arch.data

import android.content.SharedPreferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerializationException
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json

abstract class SharedPreferenceDataStore<T> constructor(
private val sharedPreferences: SharedPreferences,
private val dataStore: DataStore<Preferences>,
private val serializer: KSerializer<T>
) : DataSource<T> {

private val key = this.javaClass.simpleName
private val key = stringPreferencesKey(this.javaClass.simpleName)

override suspend fun getAll(): List<T> {
return try {
val json = dataStore.data.map { it[key] ?: "" }.first()
Json.decodeFromString(ListSerializer(serializer), json)
} catch (e: SerializationException) {
emptyList<T>()
}

override fun getAll(): List<T> {
val json = sharedPreferences.getString(key, "") ?: ""
return Json.decodeFromString(ListSerializer(serializer), json)
}

override fun add(item: T) {
override suspend fun add(item: T) {
val list = getAll().toMutableList()
list.add(item)
addAll(list)
}

override fun addAll(items: List<T>) {
override suspend fun addAll(items: List<T>) {
val json = Json.encodeToString(ListSerializer(serializer), items)
sharedPreferences.edit().putString(key, json).apply()
dataStore.edit {
it[key] = json
}
}

override fun clear() {
sharedPreferences.edit().remove(key).apply()
override suspend fun clear() {
dataStore.edit {
it[key] = ""
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.monstarlab.arch.data

interface SingleDataSource<T> {
fun get(): T?
fun add(item: T)
fun clear()
suspend fun get(): T?
suspend fun add(item: T)
suspend fun clear()
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,45 @@
package com.monstarlab.arch.data

import android.content.SharedPreferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
import timber.log.Timber
import java.io.IOException

abstract class SingleSharedPreferenceDataStore<T> constructor(
private val sharedPreferences: SharedPreferences,
private val dataStore: DataStore<Preferences>,
private val serializer: KSerializer<T>
) : SingleDataSource<T> {

private val key = this.javaClass.simpleName
private val key = stringPreferencesKey(this.javaClass.simpleName)

override fun get(): T? {
override suspend fun get(): T? {
return try {
val json = sharedPreferences.getString(key, "") ?: ""
val json = dataStore.data.map { it[key] ?: "" }.first()
val entries = Json.decodeFromString(serializer, json)
entries
} catch (e: SerializationException) {
null
}
}

override fun add(item: T) {
override suspend fun add(item: T) {
try {
val json = Json.encodeToString(serializer, item)
sharedPreferences.edit().putString(key, json).apply()
dataStore.edit {
it[key] = json
}
} catch (e: SerializationException) {
Timber.e(e)
}
}

override fun clear() {
sharedPreferences.edit().remove(key).apply()
override suspend fun clear() {
dataStore.edit { it[key] = "" }
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.monstarlab.core.data.storage

import android.content.SharedPreferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import com.monstarlab.arch.data.SharedPreferenceDataStore
import com.monstarlab.core.domain.model.Post
import javax.inject.Inject

class PostPreferenceStore @Inject constructor(
sharedPreferences: SharedPreferences
) : SharedPreferenceDataStore<Post>(sharedPreferences, Post.serializer())
dataStore: DataStore<Preferences>
) : SharedPreferenceDataStore<Post>(dataStore, Post.serializer())
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.monstarlab.core.data.storage

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import com.monstarlab.core.data.storage.PreferenceDataStore.PreferencesKeys.PREF_LOGGED_IN
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class PreferenceDataStore @Inject constructor(
private val dataStore: DataStore<Preferences>
) {
companion object {
// todo change the name accordingly
const val PREFS_NAME = "app_prefs"
}

object PreferencesKeys {
val PREF_LOGGED_IN = booleanPreferencesKey("pref_logged_in")
}

suspend fun completeLogin(complete: Boolean) {
dataStore.edit {
it[PREF_LOGGED_IN] = complete
}
}

val isLoggedIn: Flow<Boolean> =
dataStore.data.map { it[PREF_LOGGED_IN] ?: false }

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.monstarlab.core.data.storage

import android.content.SharedPreferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import com.monstarlab.arch.data.SharedPreferenceDataStore
import com.monstarlab.core.domain.model.Resource
import javax.inject.Inject

class ResourcePreferenceStore @Inject constructor(
sharedPreferences: SharedPreferences
) : SharedPreferenceDataStore<Resource>(sharedPreferences, Resource.serializer())
dataStore: DataStore<Preferences>
) : SharedPreferenceDataStore<Resource>(dataStore, Resource.serializer())
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.monstarlab.core.data.storage

import android.content.SharedPreferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import com.monstarlab.arch.data.SingleSharedPreferenceDataStore
import com.monstarlab.core.domain.model.User
import javax.inject.Inject

class UserPreferenceStore @Inject constructor(
sharedPreferences: SharedPreferences
) : SingleSharedPreferenceDataStore<User>(sharedPreferences, User.serializer())
dataStore: DataStore<Preferences>
) : SingleSharedPreferenceDataStore<User>(dataStore, User.serializer())
30 changes: 26 additions & 4 deletions app/src/main/java/com/monstarlab/injection/modules/DataModule.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.monstarlab.injection.modules

import android.content.Context
import android.content.SharedPreferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.SharedPreferencesMigration
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStore
import com.monstarlab.core.data.storage.PreferenceDataStore
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -13,9 +17,27 @@ import javax.inject.Singleton
@Module
class DataModule {

private val Context.dataStore by preferencesDataStore(
name = PreferenceDataStore.PREFS_NAME,
produceMigrations = { context ->
listOf(
SharedPreferencesMigration(
context,
PreferenceDataStore.PREFS_NAME
)
)
}
)

@Singleton
@Provides
fun provideDataStore(@ApplicationContext context: Context): DataStore<Preferences> =
context.dataStore

@Singleton
@Provides
fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences {
return context.applicationContext.getSharedPreferences("app_prefs", Context.MODE_PRIVATE)
}
fun providePreferenceStorage(@ApplicationContext context: Context): PreferenceDataStore =
PreferenceDataStore(context.dataStore)


}
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ buildscript {
desugaring : '1.0.9',
nodes_nstack_kotlin : '3.2.5',
nstack_gradle_plugin: '3.2.5',
datastore : '1.0.0',
]

ext.keys = [
Expand Down