diff --git a/FlowCrypt/build.gradle.kts b/FlowCrypt/build.gradle.kts index 9b4764eb8c..f5cb666744 100644 --- a/FlowCrypt/build.gradle.kts +++ b/FlowCrypt/build.gradle.kts @@ -445,6 +445,7 @@ dependencies { implementation("androidx.navigation:navigation-ui-ktx:2.7.7") implementation("androidx.navigation:navigation-runtime-ktx:2.7.7") implementation("androidx.webkit:webkit:1.11.0") + implementation("androidx.datastore:datastore-preferences:1.1.1") implementation("com.google.android.gms:play-services-base:18.5.0") implementation("com.google.android.gms:play-services-auth:21.2.0") diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/util/TestGeneralUtil.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/util/TestGeneralUtil.kt index 6d5e10b59e..0c176e154e 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/util/TestGeneralUtil.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/util/TestGeneralUtil.kt @@ -210,7 +210,11 @@ object TestGeneralUtil { } fun clearApp(context: Context) { - SharedPreferencesHelper.clear(context) + runBlocking { + context.dataStore.edit { preferences -> + preferences.clear() + } + } FileAndDirectoryUtils.cleanDir(context.cacheDir) FileAndDirectoryUtils.cleanDir(File(context.filesDir, MsgsCacheManager.CACHE_DIR_NAME)) FlowCryptRoomDatabase.getDatabase(context).forceDatabaseCreationIfNeeded() diff --git a/FlowCrypt/src/dev/java/com/flowcrypt/email/util/FlavorSettings.kt b/FlowCrypt/src/dev/java/com/flowcrypt/email/util/FlavorSettings.kt index 2bfdd3b998..20ac1bdae4 100644 --- a/FlowCrypt/src/dev/java/com/flowcrypt/email/util/FlavorSettings.kt +++ b/FlowCrypt/src/dev/java/com/flowcrypt/email/util/FlavorSettings.kt @@ -21,9 +21,9 @@ object FlavorSettings : EnvironmentSettings { private fun configureLeakCanary(context: Context) { if (GeneralUtil.isDebugBuild()) { - val isLeakCanaryEnabled = SharedPreferencesHelper.getBoolean( - sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context), - key = Constants.PREF_KEY_IS_DETECT_MEMORY_LEAK_ENABLED, + val isLeakCanaryEnabled = SharedPreferencesHelper.getValue( + context, + PreferencesKeys.KEY_IS_DETECT_MEMORY_LEAK_ENABLED, defaultValue = false ) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/FlowCryptApplication.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/FlowCryptApplication.kt index c6db5493a2..00f6279fe9 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/FlowCryptApplication.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/FlowCryptApplication.kt @@ -24,6 +24,7 @@ import com.flowcrypt.email.service.PassPhrasesInRAMService import com.flowcrypt.email.ui.notifications.NotificationChannelManager import com.flowcrypt.email.util.FlavorSettings import com.flowcrypt.email.util.GeneralUtil +import com.flowcrypt.email.util.PreferencesKeys import com.flowcrypt.email.util.SharedPreferencesHelper import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers @@ -129,9 +130,9 @@ class FlowCryptApplication : Application(), Configuration.Provider { private fun initACRA() { if (GeneralUtil.isDebugBuild()) { - val isAcraEnabled = SharedPreferencesHelper.getBoolean( - sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this), - key = Constants.PREF_KEY_IS_ACRA_ENABLED, + val isAcraEnabled = SharedPreferencesHelper.getValue( + context = this, + key = PreferencesKeys.KEY_IS_ACRA_ENABLED, defaultValue = BuildConfig.IS_ACRA_ENABLED ) if (isAcraEnabled) { diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/EmailUtil.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/EmailUtil.kt index 59d7656688..b406eda14a 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/EmailUtil.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/EmailUtil.kt @@ -14,7 +14,6 @@ import android.provider.OpenableColumns import android.text.TextUtils import android.util.SparseArray import androidx.annotation.WorkerThread -import androidx.preference.PreferenceManager import com.flowcrypt.email.BuildConfig import com.flowcrypt.email.Constants import com.flowcrypt.email.R @@ -39,6 +38,7 @@ import com.flowcrypt.email.security.pgp.PgpDecryptAndOrVerify import com.flowcrypt.email.security.pgp.PgpEncryptAndOrSign import com.flowcrypt.email.util.GeneralUtil import com.flowcrypt.email.util.OutgoingMessagesManager +import com.flowcrypt.email.util.PreferencesKeys import com.flowcrypt.email.util.SharedPreferencesHelper import com.flowcrypt.email.util.exception.ExceptionUtil import com.google.android.gms.auth.GoogleAuthException @@ -329,10 +329,12 @@ class EmailUtil { * @return true if debug enable, false - otherwise. */ fun hasEnabledDebug(context: Context): Boolean { - return GeneralUtil.isDebugBuild() && SharedPreferencesHelper.getBoolean( - PreferenceManager.getDefaultSharedPreferences(context.applicationContext), - Constants.PREF_KEY_IS_MAIL_DEBUG_ENABLED, BuildConfig.IS_MAIL_DEBUG_ENABLED - ) + return GeneralUtil.isDebugBuild() && + SharedPreferencesHelper.getValue( + context = context.applicationContext, + key = PreferencesKeys.KEY_IS_MAIL_DEBUG_ENABLED, + defaultValue = BuildConfig.IS_MAIL_DEBUG_ENABLED + ) } /** diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiHelper.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiHelper.kt index 73415b0559..bdf757369c 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiHelper.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiHelper.kt @@ -13,6 +13,7 @@ import com.flowcrypt.email.Constants import com.flowcrypt.email.api.retrofit.okhttp.ApiVersionInterceptor import com.flowcrypt.email.api.retrofit.okhttp.LoggingInFileInterceptor import com.flowcrypt.email.util.GeneralUtil +import com.flowcrypt.email.util.PreferencesKeys import com.flowcrypt.email.util.SharedPreferencesHelper import com.flowcrypt.email.util.google.gson.ByteArrayJsonSerializerDeserializer import com.flowcrypt.email.util.google.gson.CharArrayJsonSerializerDeserializer @@ -84,10 +85,10 @@ class ApiHelper private constructor(context: Context) { context: Context, okHttpClientBuilder: OkHttpClient.Builder ) { if (GeneralUtil.isDebugBuild()) { - val isHttpLogEnabled = - SharedPreferencesHelper.getBoolean( - PreferenceManager.getDefaultSharedPreferences(context), - Constants.PREF_KEY_IS_HTTP_LOG_ENABLED, BuildConfig.IS_HTTP_LOG_ENABLED + val isHttpLogEnabled = SharedPreferencesHelper.getValue( + context = context.applicationContext, + key = PreferencesKeys.KEY_IS_HTTP_LOG_ENABLED, + defaultValue = BuildConfig.IS_HTTP_LOG_ENABLED ) if (isHttpLogEnabled) { @@ -98,10 +99,10 @@ class ApiHelper private constructor(context: Context) { BuildConfig.HTTP_LOG_LEVEL ) - val isWriteLogsEnabled = - SharedPreferencesHelper.getBoolean( - PreferenceManager.getDefaultSharedPreferences(context), - Constants.PREF_KEY_IS_WRITE_LOGS_TO_FILE_ENABLED, false + val isWriteLogsEnabled = SharedPreferencesHelper.getValue( + context = context.applicationContext, + key = PreferencesKeys.KEY_IS_WRITE_LOGS_TO_FILE_ENABLED, + defaultValue = false ) if (isWriteLogsEnabled) { diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/broadcastreceivers/AppUpdateBroadcastReceiver.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/broadcastreceivers/AppUpdateBroadcastReceiver.kt index 20620cc656..51aef6e5be 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/broadcastreceivers/AppUpdateBroadcastReceiver.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/broadcastreceivers/AppUpdateBroadcastReceiver.kt @@ -8,8 +8,7 @@ package com.flowcrypt.email.broadcastreceivers import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import androidx.preference.PreferenceManager -import com.flowcrypt.email.Constants +import com.flowcrypt.email.util.PreferencesKeys import com.flowcrypt.email.util.SharedPreferencesHelper /** @@ -21,10 +20,7 @@ class AppUpdateBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent?) { if (intent != null && Intent.ACTION_MY_PACKAGE_REPLACED == intent.action) { - SharedPreferencesHelper.setBoolean( - PreferenceManager - .getDefaultSharedPreferences(context), Constants.PREF_KEY_IS_CHECK_KEYS_NEEDED, true - ) + SharedPreferencesHelper.setValue(context, PreferencesKeys.KEY_IS_CHECK_KEYS_NEEDED, true) } } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/Context.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/Context.kt index 258d847c74..d0a52da7c0 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/Context.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/Context.kt @@ -10,10 +10,22 @@ import android.net.ConnectivityManager import android.net.NetworkCapabilities import android.os.Build import android.widget.Toast +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.SharedPreferencesMigration +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.preferencesDataStore +import com.flowcrypt.email.BuildConfig /** * @author Denys Bondarenko */ + +val Context.dataStore: DataStore by preferencesDataStore( + name = BuildConfig.APPLICATION_ID + "_preferences", + produceMigrations = { context -> + listOf(SharedPreferencesMigration(context, BuildConfig.APPLICATION_ID + "_preferences")) + }) + fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT) { Toast.makeText(this, text ?: "", duration).show() } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/EncryptPrivateKeysIfNeededAction.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/EncryptPrivateKeysIfNeededAction.kt index 5ec1c590f4..b4962a30c1 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/EncryptPrivateKeysIfNeededAction.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/EncryptPrivateKeysIfNeededAction.kt @@ -8,16 +8,16 @@ package com.flowcrypt.email.service.actionqueue.actions import android.content.Context -import androidx.preference.PreferenceManager -import com.flowcrypt.email.Constants +import androidx.datastore.preferences.core.edit import com.flowcrypt.email.database.FlowCryptRoomDatabase import com.flowcrypt.email.database.entity.KeyEntity +import com.flowcrypt.email.extensions.dataStore import com.flowcrypt.email.security.KeyStoreCryptoManager import com.flowcrypt.email.security.KeysStorageImpl import com.flowcrypt.email.security.pgp.PgpKey import com.flowcrypt.email.security.pgp.PgpPwd import com.flowcrypt.email.ui.notifications.SystemNotificationManager -import com.flowcrypt.email.util.SharedPreferencesHelper +import com.flowcrypt.email.util.PreferencesKeys import com.flowcrypt.email.util.exception.ExceptionUtil import com.flowcrypt.email.util.exception.PrivateKeyStrengthException import com.google.android.gms.common.util.CollectionUtils @@ -100,10 +100,8 @@ data class EncryptPrivateKeysIfNeededAction @JvmOverloads constructor( } roomDatabase.keysDao().update(modifiedKeyEntities) - - SharedPreferencesHelper.setBoolean( - PreferenceManager - .getDefaultSharedPreferences(context), Constants.PREF_KEY_IS_CHECK_KEYS_NEEDED, false - ) + context.dataStore.edit { preferences -> + preferences[PreferencesKeys.KEY_IS_CHECK_KEYS_NEEDED] = false + } } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/AddOtherAccountFragment.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/AddOtherAccountFragment.kt index 245638aae1..4f71f81bd8 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/AddOtherAccountFragment.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/AddOtherAccountFragment.kt @@ -49,6 +49,7 @@ import com.flowcrypt.email.ui.activity.fragment.base.BaseSingInFragment import com.flowcrypt.email.ui.activity.fragment.dialog.TwoWayDialogFragment import com.flowcrypt.email.ui.widget.inputfilters.InputFilters import com.flowcrypt.email.util.GeneralUtil +import com.flowcrypt.email.util.PreferencesKeys import com.flowcrypt.email.util.SharedPreferencesHelper import com.flowcrypt.email.util.exception.AccountAlreadyAddedException import com.flowcrypt.email.util.exception.ExceptionUtil @@ -628,9 +629,10 @@ class AddOtherAccountFragment : BaseSingInFragment - ): Set? { - return sharedPreferences.getStringSet(key, defValues) - } - - fun getLong(sharedPreferences: SharedPreferences, key: String, defaultValue: Long): Long { - return sharedPreferences.getLong(key, defaultValue) - } - - fun setLong(sharedPreferences: SharedPreferences, key: String, value: Long): Boolean { - val editor = sharedPreferences.edit() - editor.putLong(key, value) - return editor.commit() - } - - fun setString(sharedPreferences: SharedPreferences, key: String, value: String): Boolean { - val editor = sharedPreferences.edit() - editor.putString(key, value) - return editor.commit() - } - - fun getInt(sharedPreferences: SharedPreferences, key: String, defaultValue: Int): Int { - return sharedPreferences.getInt(key, defaultValue) - } - - fun setInt(sharedPreferences: SharedPreferences, key: String, value: Int): Boolean { - val editor = sharedPreferences.edit() - editor.putInt(key, value) - return editor.commit() + fun getValue(context: Context, key: Preferences.Key, defaultValue: T): T { + return runBlocking { + context.dataStore.data + .map { preferences -> + preferences[key] ?: defaultValue + }.lastOrNull() ?: defaultValue + } } - /** - * Clear the all shared preferences. - * - * @param context Interface to global information about an application environment. - * @return Returns true if the new values were successfully written to persistent storage. - */ - fun clear(context: Context): Boolean { - return PreferenceManager.getDefaultSharedPreferences(context).edit().clear().commit() + fun setValue(context: Context, key: Preferences.Key, value: T): Boolean { + return runBlocking { + context.dataStore.edit { preferences -> + preferences[key] = value + } + }.contains(key) } } }