diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/CacheAsync.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/CacheAsync.kt index 174df8f..404aa19 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/CacheAsync.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/CacheAsync.kt @@ -1,26 +1,26 @@ package com.topsort.analytics import android.content.Context -import android.content.SharedPreferences import android.text.TextUtils import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import com.topsort.analytics.model.ClickEvent import com.topsort.analytics.model.ImpressionEvent import com.topsort.analytics.model.PurchaseEvent -import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking import java.util.Locale private const val preferencesName = "TOPSORT_EVENTS_CACHE" private val KEY_TOKEN = stringPreferencesKey("KEY_TOKEN") -private val KEY_SESSION_ID = stringPreferencesKey("KEY_SESSION_ID") -private const val KEY_RECORD = "KEY_RECORD_%d" -private const val KEY_RECENT_RECORD_ID = "KEY_RECORD_ID" +private val KEY_OPAQUE_USER_ID = stringPreferencesKey("KEY_OPAQUE_USER_ID") +private const val KEY_RECORD_FORMAT = "KEY_RECORD_%d" +private val KEY_RECENT_RECORD_ID = longPreferencesKey("KEY_RECORD_ID") val Context.dataStore: DataStore by preferencesDataStore(name = "settings") @@ -30,132 +30,128 @@ internal object CacheAsync { private var recentRecordId: Long = 0 - var token: String = "" - set(value) { - field = value - runBlocking { - applicationContext.dataStore.edit{ store -> - store[KEY_TOKEN] = value - } - } - } + private var token: String = "" + fun getToken() = token + + private suspend fun setToken(value: String) { + token = value + applicationContext.dataStore.edit { store -> + store[KEY_TOKEN] = value + } + } - var sessionId: String = "" - set(value) { - field = value - runBlocking { - applicationContext.dataStore.edit { store -> - store[KEY_SESSION_ID] = value - } - } + private var opaqueUserId: String = "" + fun getOpaqueUserId() = opaqueUserId + private suspend fun setOpaqueUserId(value: String){ + opaqueUserId = value + applicationContext.dataStore.edit { store -> + store[KEY_OPAQUE_USER_ID] = value } + } - fun initialize(context: Context) { + private fun initialize(context: Context) { applicationContext = context.applicationContext - - applicationContext.dataStore.data - .map { store -> - store[KEY_TOKEN] - } - - token = preferences.getString(KEY_TOKEN, "")!! - sessionId = preferences.getString(KEY_SESSION_ID, "")!! + runBlocking { + val store = applicationContext.dataStore.data.first() + token = store[KEY_TOKEN] ?: "" + opaqueUserId = store[KEY_OPAQUE_USER_ID] ?: "" + } } fun setup( context: Context, - sessionId: String, + opaqueUserId: String, token: String ) { initialize(context) - recentRecordId = preferences.getLong(KEY_RECENT_RECORD_ID, 0) - this.sessionId = sessionId + runBlocking { + val store = applicationContext.dataStore.data.first() + recentRecordId = store[KEY_RECENT_RECORD_ID] ?: 0L + } + + this.opaqueUserId = opaqueUserId this.token = token } - fun storeImpression( + suspend fun storeImpression( impressionEvent: ImpressionEvent ): Long { val json = impressionEvent.toJsonObject().toString() - preferences - .edit() - .putString(nextRecordKey(), json) - .apply() - - return recentRecordId + return storeEvent(json) } - fun readImpression(recordId: Long): ImpressionEvent? { + suspend fun readImpression(recordId: Long): ImpressionEvent? { return ImpressionEvent.fromJson(readEvent(recordId)) } - fun storeClick( + suspend fun storeClick( clickEvent: ClickEvent ): Long { val json = clickEvent.toJsonObject().toString() - preferences - .edit() - .putString(nextRecordKey(), json) - .apply() - - return recentRecordId + return storeEvent(json) } - fun readClick(recordId: Long): ClickEvent? { + suspend fun readClick(recordId: Long): ClickEvent? { return ClickEvent.fromJson(readEvent(recordId)) } - fun storePurchase( + suspend fun storePurchase( purchaseEvent: PurchaseEvent ): Long { val json = purchaseEvent.toJsonObject().toString() - preferences - .edit() - .putString(nextRecordKey(), json) - .apply() - - return recentRecordId + return storeEvent(json) } - fun readPurchase(recordId: Long): PurchaseEvent? { + suspend fun readPurchase(recordId: Long): PurchaseEvent? { return PurchaseEvent.fromJson(readEvent(recordId)) } - fun deleteEvent(recordId: Long) { - preferences - .edit() - .remove(recordKey(recordId)) - .apply() + suspend fun deleteEvent(recordId: Long) { + applicationContext.dataStore.edit { store -> + store.remove(recordKey(recordId)) + } } - private fun readEvent(recordId: Long): String? { - val json = preferences.getString(recordKey(recordId), "") + private suspend fun readEvent(recordId: Long): String? { + val json = applicationContext.dataStore.data.first()[recordKey(recordId)] ?: "" if (TextUtils.isEmpty(json)) { return null } - return json } - private fun recordKey(recordId: Long) = String.format( - Locale.ENGLISH, - KEY_RECORD, - recordId + private suspend fun storeEvent(json: String): Long { + val recordId = nextRecordKey() + applicationContext.dataStore.edit { store -> + store[recordId] = json + } + + return recentRecordId + } + + private fun recordKey(recordId: Long) = stringPreferencesKey( + String.format( + Locale.ENGLISH, + KEY_RECORD_FORMAT, + recordId + ) ) - private fun nextRecordKey(): String { + private suspend fun nextRecordKey(): Preferences.Key { recentRecordId = if (recentRecordId < Long.MAX_VALUE) { recentRecordId + 1 } else { 0 } - preferences - .edit() - .putLong(KEY_RECENT_RECORD_ID, recentRecordId) - .apply() - return recordKey(recentRecordId) + val recentRecordKey = recordKey(recentRecordId) + + applicationContext.dataStore.edit { store -> + store[KEY_RECENT_RECORD_ID] = recentRecordId + } + + return recentRecordKey } }