Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate shared preferences to datastore preferences #14

Merged
merged 1 commit into from
Jul 4, 2024
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
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ dependencies {
implementation(libs.coil.compose)
implementation(libs.lottie.compose)

// Datastore
implementation(libs.datastore.preferences)

// Unit Test
testImplementation(libs.junit)
testImplementation(libs.mockk)
Expand Down
14 changes: 10 additions & 4 deletions app/src/main/kotlin/com/whereismymotivation/WimmApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import com.whereismymotivation.init.FirebaseInit
import com.whereismymotivation.init.MetricInit
import com.whereismymotivation.init.WorkInit
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltAndroidApp
Expand Down Expand Up @@ -42,12 +45,15 @@ class WimmApplication : Application(), Configuration.Provider {
.setWorkerFactory(workerFactory)
.build()

@OptIn(DelicateCoroutinesApi::class)
override fun onCreate() {
super.onCreate()
tracker.trackAppOpen()
metricInit.init()
workInit.init()
firebaseInit.init()
coilInit.init()
GlobalScope.launch {
metricInit.init()
workInit.init()
firebaseInit.init()
coilInit.init()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,48 +1,52 @@
package com.whereismymotivation.data.local.prefs

import android.content.SharedPreferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class AppMetricPreferences @Inject constructor(private val prefs: SharedPreferences) {
class AppMetricPreferences @Inject constructor(private val dataStore: DataStore<Preferences>) {

companion object {

private const val CURRENT_APP_VERSION = "PREF_KEY_CURRENT_APP_VERSION"

private const val DAILY_RECORD_ALARM_TIME_HOUR = "PREF_KEY_DAILY_RECORD_ALARM_TIME_HOUR"
private const val DAILY_RECORD_ALARM_TIME_MIN = "PREF_KEY_DAILY_RECORD_ALARM_TIME_MIN"
private const val DAILY_RECORD_ALARM_TIME_SEC = "PREF_KEY_DAILY_RECORD_ALARM_TIME_SEC"

private const val DAILY_MOOD_RECORDER_NOTIFICATION =
"PREF_KEY_DAILY_MOOD_RECORDER_NOTIFICATION"

private val CURRENT_APP_VERSION = longPreferencesKey("CURRENT_APP_VERSION")
private val DAILY_RECORD_ALARM_TIME_HOUR = intPreferencesKey("DAILY_RECORD_ALARM_TIME_HOUR")
private val DAILY_RECORD_ALARM_TIME_MIN = intPreferencesKey("DAILY_RECORD_ALARM_TIME_MIN")
private val DAILY_RECORD_ALARM_TIME_SEC = intPreferencesKey("DAILY_RECORD_ALARM_TIME_SEC")
private val DAILY_MOOD_RECORDER_NOTIFICATION =
booleanPreferencesKey("DAILY_MOOD_RECORDER_NOTIFICATION")
}

fun setCurrentAppVersion(appVersion: Long) =
prefs.edit().putLong(CURRENT_APP_VERSION, appVersion).apply()
suspend fun setCurrentAppVersion(appVersion: Long) {
dataStore.edit { it[CURRENT_APP_VERSION] = appVersion }
}

fun getCurrentAppVersion(): Long =
prefs.getLong(CURRENT_APP_VERSION, 0)
suspend fun getCurrentAppVersion() =
dataStore.data.map { it[CURRENT_APP_VERSION] ?: 0 }.first()

fun setDailyRecordAlarmTime(hour: Int, min: Int, sec: Int) {
prefs.edit().putInt(DAILY_RECORD_ALARM_TIME_HOUR, hour).apply()
prefs.edit().putInt(DAILY_RECORD_ALARM_TIME_MIN, min).apply()
prefs.edit().putInt(DAILY_RECORD_ALARM_TIME_SEC, sec).apply()
suspend fun setDailyRecordAlarmTime(hour: Int, min: Int, sec: Int) {
dataStore.edit { it[DAILY_RECORD_ALARM_TIME_HOUR] = hour }
dataStore.edit { it[DAILY_RECORD_ALARM_TIME_MIN] = min }
dataStore.edit { it[DAILY_RECORD_ALARM_TIME_SEC] = sec }
}

fun getDailyRecordAlarmTime(): Triple<Int, Int, Int> {
val hour = prefs.getInt(DAILY_RECORD_ALARM_TIME_HOUR, 20) // 8PM
val min = prefs.getInt(DAILY_RECORD_ALARM_TIME_MIN, 0)
val sec = prefs.getInt(DAILY_RECORD_ALARM_TIME_SEC, 0)
suspend fun getDailyRecordAlarmTime(): Triple<Int, Int, Int> {
val hour = dataStore.data.map { it[DAILY_RECORD_ALARM_TIME_HOUR] ?: 22 }.first() // 8PM
val min = dataStore.data.map { it[DAILY_RECORD_ALARM_TIME_MIN] ?: 34 }.first()
val sec = dataStore.data.map { it[DAILY_RECORD_ALARM_TIME_SEC] ?: 0 }.first()
return Triple(hour, min, sec)
}

fun setDailyMoodRecorderNotificationEnable(enable: Boolean) =
prefs.edit().putBoolean(DAILY_MOOD_RECORDER_NOTIFICATION, enable).apply()

fun getDailyMoodRecorderNotificationEnable() =
prefs.getBoolean(DAILY_MOOD_RECORDER_NOTIFICATION, true)
suspend fun setDailyMoodRecorderNotificationEnable(enable: Boolean) {
dataStore.edit { it[DAILY_MOOD_RECORDER_NOTIFICATION] = enable }
}

suspend fun getDailyMoodRecorderNotificationEnable() =
dataStore.data.map { it[DAILY_MOOD_RECORDER_NOTIFICATION] ?: true }.first()
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
package com.whereismymotivation.data.local.prefs

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.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class ContentPreferences @Inject constructor(private val prefs: SharedPreferences) {
class ContentPreferences @Inject constructor(private val dataStore: DataStore<Preferences>) {

companion object {
private const val FEED_NEXT_PAGE_NUMBER = "FEED_NEXT_PAGE_NUMBER"
private const val FEED_LAST_SEEN = "FEED_LAST_SEEN"
private val FEED_NEXT_PAGE_NUMBER = intPreferencesKey("FEED_NEXT_PAGE_NUMBER")
private val FEED_LAST_SEEN = longPreferencesKey("FEED_LAST_SEEN")
}

fun getFeedNextPageNumber(): Int =
prefs.getInt(FEED_NEXT_PAGE_NUMBER, 1)
suspend fun getFeedNextPageNumber() =
dataStore.data.map { it[FEED_NEXT_PAGE_NUMBER] ?: 1 }.first()

fun setFeedNextPageNumber(pageNumber: Int) =
prefs.edit().putInt(FEED_NEXT_PAGE_NUMBER, pageNumber).apply()
suspend fun setFeedNextPageNumber(pageNumber: Int) {
dataStore.edit { it[FEED_NEXT_PAGE_NUMBER] = pageNumber }
}

fun getFeedLastSeen(): Long =
prefs.getLong(FEED_LAST_SEEN, System.currentTimeMillis())
suspend fun getFeedLastSeen() =
dataStore.data.map { it[FEED_LAST_SEEN] ?: System.currentTimeMillis() }.first()

fun setFeedLastSeen(time: Long) =
prefs.edit().putLong(FEED_LAST_SEEN, time).apply()
suspend fun setFeedLastSeen(time: Long) {
dataStore.edit { it[FEED_LAST_SEEN] = time }
}
}
Original file line number Diff line number Diff line change
@@ -1,114 +1,136 @@
package com.whereismymotivation.data.local.prefs

import android.content.SharedPreferences
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class UserPreferences @Inject constructor(private val prefs: SharedPreferences) {
class UserPreferences @Inject constructor(private val dataStore: DataStore<Preferences>) {

companion object {
private const val ON_BOARDING_COMPLETED = "PREF_KEY_USER_ON_BOARDING_COMPLETED"
private const val USER_ID = "PREF_KEY_USER_ID"
private const val USER_NAME = "PREF_KEY_USER_NAME"
private const val USER_EMAIL = "PREF_KEY_USER_EMAIL"
private const val USER_PROFILE_PIC_URL = "USER_PROFILE_PIC_URL"
private const val ACCESS_TOKEN = "PREF_KEY_ACCESS_TOKEN"
private const val REFRESH_TOKEN = "PREF_KEY_REFRESH_TOKEN"
private const val DEVICE_ID = "PREF_KEY_DEVICE_ID"
private const val USER_ROLES = "PREF_KEY_USER_ROLES"
private const val FIREBASE_TOKEN = "FIREBASE_TOKEN"
private const val FIREBASE_TOKEN_SENT = "FIREBASE_TOKEN_SENT"
private val ON_BOARDING_COMPLETED = booleanPreferencesKey("ON_BOARDING_COMPLETED")
private val USER_ID = stringPreferencesKey("USER_ID")
private val USER_NAME = stringPreferencesKey("USER_NAME")
private val USER_EMAIL = stringPreferencesKey("USER_EMAIL")
private val USER_PROFILE_PIC_URL = stringPreferencesKey("USER_PROFILE_PIC_URL")
private val ACCESS_TOKEN = stringPreferencesKey("ACCESS_TOKEN")
private val REFRESH_TOKEN = stringPreferencesKey("REFRESH_TOKEN")
private val DEVICE_ID = stringPreferencesKey("DEVICE_ID")
private val USER_ROLES = stringPreferencesKey("USER_ROLES")
private val FIREBASE_TOKEN = stringPreferencesKey("FIREBASE_TOKEN")
private val FIREBASE_TOKEN_SENT = booleanPreferencesKey("FIREBASE_TOKEN_SENT")
}

fun getUserId(): String? =
prefs.getString(USER_ID, null)
suspend fun getUserId() = dataStore.data.map { it[USER_ID] }.first()

fun setUserId(userId: String) =
prefs.edit().putString(USER_ID, userId).apply()
suspend fun setUserId(userId: String) {
dataStore.edit { it[USER_ID] = userId }
}

fun removeUserId() =
prefs.edit().remove(USER_ID).apply()
suspend fun removeUserId() {
dataStore.edit { it.remove(USER_ID) }
}

fun getUserName(): String? =
prefs.getString(USER_NAME, null)
suspend fun getUserName() = dataStore.data.map { it[USER_NAME] }.first()

fun setUserName(userName: String) =
prefs.edit().putString(USER_NAME, userName).apply()
suspend fun setUserName(userName: String) {
dataStore.edit { it[USER_NAME] = userName }
}

fun removeUserName() =
prefs.edit().remove(USER_NAME).apply()
suspend fun removeUserName() {
dataStore.edit { it.remove(USER_NAME) }
}

fun getUserEmail(): String? =
prefs.getString(USER_EMAIL, null)
suspend fun getUserEmail() = dataStore.data.map { it[USER_EMAIL] }.first()

fun setUserEmail(email: String) =
prefs.edit().putString(USER_EMAIL, email).apply()
suspend fun setUserEmail(email: String) {
dataStore.edit { it[USER_EMAIL] = email }
}

fun removeUserEmail() =
prefs.edit().remove(USER_EMAIL).apply()
suspend fun removeUserEmail() {
dataStore.edit { it.remove(USER_EMAIL) }
}

fun getUserProfilePicUrlUrl(): String? =
prefs.getString(USER_PROFILE_PIC_URL, null)
suspend fun getUserProfilePicUrlUrl() = dataStore.data.map { it[USER_PROFILE_PIC_URL] }.first()

fun setUserProfileProfilePicUrl(url: String?) =
prefs.edit().putString(USER_PROFILE_PIC_URL, url).apply()
suspend fun setUserProfileProfilePicUrl(url: String?) {
url?.let {
dataStore.edit { it[USER_PROFILE_PIC_URL] = url }
} ?: removeUserProfilePicUrl()
}

fun removeUserProfilePicUrl() =
prefs.edit().remove(USER_PROFILE_PIC_URL).apply()
suspend fun removeUserProfilePicUrl() {
dataStore.edit { it.remove(USER_PROFILE_PIC_URL) }
}

fun getAccessToken(): String? =
prefs.getString(ACCESS_TOKEN, null)
suspend fun getAccessToken() = dataStore.data.map { it[ACCESS_TOKEN] }.first()

fun setAccessToken(token: String) =
prefs.edit().putString(ACCESS_TOKEN, token).apply()
suspend fun setAccessToken(token: String) {
dataStore.edit { it[ACCESS_TOKEN] = token }
}

fun removeAccessToken() =
prefs.edit().remove(ACCESS_TOKEN).apply()
suspend fun removeAccessToken() {
dataStore.edit { it.remove(ACCESS_TOKEN) }
}

fun getRefreshToken(): String? =
prefs.getString(REFRESH_TOKEN, null)
suspend fun getRefreshToken() = dataStore.data.map { it[REFRESH_TOKEN] }.first()

fun setRefreshToken(token: String) =
prefs.edit().putString(REFRESH_TOKEN, token).apply()
suspend fun setRefreshToken(token: String) {
dataStore.edit { it[REFRESH_TOKEN] = token }
}

fun removeRefreshToken() =
prefs.edit().remove(REFRESH_TOKEN).apply()
suspend fun removeRefreshToken() {
dataStore.edit { it.remove(REFRESH_TOKEN) }
}

fun getOnBoardingComplete(): Boolean =
prefs.getBoolean(ON_BOARDING_COMPLETED, false)
suspend fun getOnBoardingComplete() =
dataStore.data.map { it[ON_BOARDING_COMPLETED] }.first() ?: false

fun setOnBoardingComplete(complete: Boolean) =
prefs.edit().putBoolean(ON_BOARDING_COMPLETED, complete).apply()
suspend fun setOnBoardingComplete(complete: Boolean) {
dataStore.edit { it[ON_BOARDING_COMPLETED] = complete }
}

fun removeOnBoardingComplete() =
prefs.edit().remove(ON_BOARDING_COMPLETED).apply()
suspend fun removeOnBoardingComplete() {
dataStore.edit { it.remove(ON_BOARDING_COMPLETED) }
}

fun getDeviceId(): String? =
prefs.getString(DEVICE_ID, null)
suspend fun getDeviceId() = dataStore.data.map { it[DEVICE_ID] }.first()

fun setDeviceId(deviceId: String) =
prefs.edit().putString(DEVICE_ID, deviceId).apply()
suspend fun setDeviceId(deviceId: String) {
dataStore.edit { it[DEVICE_ID] = deviceId }
}

fun setFirebaseToken(token: String) =
prefs.edit().putString(FIREBASE_TOKEN, token).apply()
suspend fun setFirebaseToken(token: String) {
dataStore.edit { it[FIREBASE_TOKEN] = token }
}

fun getFirebaseToken(): String? =
prefs.getString(FIREBASE_TOKEN, null)
suspend fun getFirebaseToken() = dataStore.data.map { it[FIREBASE_TOKEN] }.first()

fun getFirebaseTokenSent(): Boolean =
prefs.getBoolean(FIREBASE_TOKEN_SENT, false)
suspend fun getFirebaseTokenSent() =
dataStore.data.map { it[FIREBASE_TOKEN_SENT] }.first() ?: false

fun setFirebaseTokenSent() =
prefs.edit().putBoolean(FIREBASE_TOKEN_SENT, true).apply()
suspend fun setFirebaseTokenSent() {
dataStore.edit { it[FIREBASE_TOKEN_SENT] = true }
}

fun removeFirebaseTokenSent() =
prefs.edit().remove(FIREBASE_TOKEN_SENT).apply()
suspend fun removeFirebaseTokenSent() {
dataStore.edit { it.remove(FIREBASE_TOKEN_SENT) }
}

fun getUserRoles(): String? = prefs.getString(USER_ROLES, null)
suspend fun getUserRoles() = dataStore.data.map { it[USER_ROLES] }.first()

fun setUserRoles(roles: String) = prefs.edit().putString(USER_ROLES, roles).apply()
suspend fun setUserRoles(roles: String) {
dataStore.edit { it[USER_ROLES] = roles }
}

fun removeUserRoles() = prefs.edit().remove(USER_ROLES).apply()
suspend fun removeUserRoles() {
dataStore.edit { it.remove(USER_ROLES) }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import com.whereismymotivation.di.qualifier.AccessTokenInfo
import com.whereismymotivation.di.qualifier.ApiKeyInfo
import com.whereismymotivation.di.qualifier.AppVersionCodeInfo
import com.whereismymotivation.di.qualifier.DeviceIdInfo
import com.whereismymotivation.utils.common.ResultFetcher
import com.whereismymotivation.utils.common.ResultFetcherBlocking
import javax.inject.Inject

class RequestHeaders @Inject constructor(
@ApiKeyInfo val apiKey: String,
@AccessTokenInfo val accessTokenFetcher: ResultFetcher<String>,
@DeviceIdInfo val deviceIdFetcher: ResultFetcher<String>,
@AppVersionCodeInfo val appVersionCodeFetcher: ResultFetcher<Long>,
@AccessTokenInfo val accessTokenFetcher: ResultFetcherBlocking<String>,
@DeviceIdInfo val deviceIdFetcher: ResultFetcherBlocking<String>,
@AppVersionCodeInfo val appVersionCodeFetcher: ResultFetcherBlocking<Long>,
) {
object Key {
const val API_AUTH_TYPE = "API_AUTH_TYPE"
Expand Down
Loading
Loading