diff --git a/app/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt b/app/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt index 05699f658d..0f4da74758 100644 --- a/app/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt +++ b/app/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt @@ -24,6 +24,8 @@ import org.session.libsession.utilities.DecodedAudio import org.session.libsession.utilities.InputStreamMediaDataSource import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.UploadResult +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.session.libsignal.messages.SignalServiceAttachmentStream import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.api.http.HttpBody @@ -43,7 +45,8 @@ class AttachmentUploadJob @AssistedInject constructor( private val messageSendJobFactory: MessageSendJob.Factory, private val threadDatabase: ThreadDatabase, private val attachmentProcessor: AttachmentProcessor, - private val preferences: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val messageSender: MessageSender, private val serverApiExecutor: ServerApiExecutor, private val fileUploadApiFactory: FileUploadApi.Factory, @@ -99,7 +102,7 @@ class AttachmentUploadJob @AssistedInject constructor( } handleSuccess(dispatcherName, attachment, keyAndResult.first, keyAndResult.second) } else { - val fileServer = preferences.alternativeFileServer ?: FileServerApis.DEFAULT_FILE_SERVER + val fileServer = preferenceStorage[MessagingPreferences.ALTERNATIVE_FILE_SERVER] ?: FileServerApis.DEFAULT_FILE_SERVER val keyAndResult = upload( attachment = attachment, encrypt = true @@ -147,7 +150,7 @@ class AttachmentUploadJob @AssistedInject constructor( val deterministicallyEncrypted: Boolean when { - encrypt && preferences.forcesDeterministicAttachmentEncryption -> { + encrypt && preferenceStorage[MessagingPreferences.FORCES_DETERMINISTIC_ATTACHMENT_ENCRYPTION] -> { deterministicallyEncrypted = true val result = attachmentProcessor.encryptDeterministically( plaintext = input, diff --git a/app/src/main/java/org/session/libsession/messaging/jobs/TrimThreadJob.kt b/app/src/main/java/org/session/libsession/messaging/jobs/TrimThreadJob.kt index 9fcc47c1b3..af14fa791b 100644 --- a/app/src/main/java/org/session/libsession/messaging/jobs/TrimThreadJob.kt +++ b/app/src/main/java/org/session/libsession/messaging/jobs/TrimThreadJob.kt @@ -9,7 +9,8 @@ import org.session.libsession.database.StorageProtocol import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.utilities.Data import org.session.libsession.utilities.Address -import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.thoughtcrime.securesms.database.Storage import org.thoughtcrime.securesms.database.ThreadDatabase @@ -18,6 +19,7 @@ class TrimThreadJob @AssistedInject constructor( private val storage: StorageProtocol, @param:ApplicationContext private val context: Context, threadDatabase: ThreadDatabase, + private val preferenceStorage: PreferenceStorage ) : Job { override var delegate: JobDelegate? = null override var id: String? = null @@ -36,7 +38,7 @@ class TrimThreadJob @AssistedInject constructor( val communityAddress: Address.Community? = threadDatabase.getRecipientForThreadId(threadId) as? Address.Community override suspend fun execute(dispatcherName: String) { - val trimmingEnabled = TextSecurePreferences.isThreadLengthTrimmingEnabled(context) + val trimmingEnabled = preferenceStorage[MessagingPreferences.THREAD_TRIM_ENABLED] val messageCount = storage.getMessageCount(threadId) if (trimmingEnabled && messageCount >= THREAD_LENGTH_TRIGGER_SIZE) { val oldestMessageTime = System.currentTimeMillis() - TRIM_TIME_LIMIT diff --git a/app/src/main/java/org/session/libsession/messaging/sending_receiving/MessageParser.kt b/app/src/main/java/org/session/libsession/messaging/sending_receiving/MessageParser.kt index ee64c19de6..812d57eab8 100644 --- a/app/src/main/java/org/session/libsession/messaging/sending_receiving/MessageParser.kt +++ b/app/src/main/java/org/session/libsession/messaging/sending_receiving/MessageParser.kt @@ -21,7 +21,8 @@ import org.session.libsession.messaging.open_groups.OpenGroupApi import org.session.libsession.network.SnodeClock import org.session.libsession.utilities.Address import org.session.libsession.utilities.ConfigFactoryProtocol -import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences import org.session.libsession.utilities.withGroupConfigs import org.session.libsession.utilities.withUserConfigs import org.session.libsignal.exceptions.NonRetryableException @@ -42,7 +43,7 @@ class MessageParser @Inject constructor( private val configFactory: ConfigFactoryProtocol, private val storage: StorageProtocol, private val snodeClock: SnodeClock, - private val prefs: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val proBackendConfig: Provider, ) { @@ -143,7 +144,7 @@ class MessageParser @Inject constructor( message.isSenderSelf = isSenderSelf // Only process pro features post pro launch - if (prefs.forcePostPro()) { + if (preferenceStorage[ProPreferences.FORCE_POST_PRO]) { if (pro?.status == ProProof.STATUS_VALID) { (message as? VisibleMessage)?.proFeatures = buildSet { addAll(pro.proMessageFeatures.asSequence()) diff --git a/app/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageProcessor.kt b/app/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageProcessor.kt index 4f88ad205a..0c022992ac 100644 --- a/app/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageProcessor.kt +++ b/app/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageProcessor.kt @@ -33,7 +33,8 @@ import org.session.libsession.utilities.Address.Companion.toAddress import org.session.libsession.utilities.ConfigFactoryProtocol import org.session.libsession.utilities.GroupUtil.doubleEncodeGroupID import org.session.libsession.utilities.SSKEnvironment -import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.PrivacyPreferences import org.session.libsession.utilities.UserConfigType import org.session.libsession.utilities.recipients.MessageType import org.session.libsession.utilities.recipients.Recipient @@ -69,7 +70,7 @@ class ReceivedMessageProcessor @Inject constructor( private val threadDatabase: ThreadDatabase, private val readReceiptManager: Provider, private val typingIndicators: Provider, - private val prefs: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val groupMessageHandler: Provider, private val messageExpirationManager: Provider, private val messageDataProvider: MessageDataProvider, @@ -377,7 +378,7 @@ class ReceivedMessageProcessor @Inject constructor( private fun showTypingIndicatorIfNeeded(senderPublicKey: String) { // We don't want to show other people's indicators if the toggle is off - if (!prefs.isTypingIndicatorsEnabled()) return + if (!preferenceStorage[PrivacyPreferences.TYPING_INDICATORS]) return val address = Address.fromSerialized(senderPublicKey) val threadID = storage.getThreadId(address) ?: return diff --git a/app/src/main/java/org/session/libsession/network/onion/PathManager.kt b/app/src/main/java/org/session/libsession/network/onion/PathManager.kt index 011a49533a..d888b2e358 100644 --- a/app/src/main/java/org/session/libsession/network/onion/PathManager.kt +++ b/app/src/main/java/org/session/libsession/network/onion/PathManager.kt @@ -21,7 +21,8 @@ import org.session.libsession.network.model.PathStatus import org.session.libsession.network.snode.SnodeDirectory import org.session.libsession.network.snode.SnodePathStorage import org.session.libsession.network.snode.SnodePoolStorage -import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SystemPreferences import org.session.libsignal.crypto.secureRandom import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Snode @@ -44,7 +45,7 @@ open class PathManager @Inject constructor( private val directory: SnodeDirectory, private val storage: SnodePathStorage, private val snodePoolStorage: SnodePoolStorage, - private val prefs: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val snodeApiExecutor: Provider, private val getInfoApi: Provider, ) { @@ -129,12 +130,12 @@ open class PathManager @Inject constructor( private fun rotatePathsIfStale() { val now = System.currentTimeMillis() - val last = prefs.getLastPathRotation() + val last = preferenceStorage[SystemPreferences.LAST_PATH_ROTATION] // if we have never done a path rotation, mark now as the starting time // so we can rotate on the next tick if (last == 0L){ - prefs.setLastPathRotation(now) + preferenceStorage[SystemPreferences.LAST_PATH_ROTATION] = now return } @@ -187,7 +188,7 @@ open class PathManager @Inject constructor( // Phase 1: decide + build candidates under lock val candidates: List = buildMutex.withLock { val now = System.currentTimeMillis() - val last = prefs.getLastPathRotation() + val last = preferenceStorage[SystemPreferences.LAST_PATH_ROTATION] if (now - last < PATH_ROTATE_INTERVAL_MS) return@withLock emptyList() val current = _paths.value @@ -258,7 +259,7 @@ open class PathManager @Inject constructor( val committed = sanitizePaths(working.take(targetPathCount)) _paths.value = committed - prefs.setLastPathRotation(System.currentTimeMillis()) + preferenceStorage[SystemPreferences.LAST_PATH_ROTATION] = System.currentTimeMillis() } } diff --git a/app/src/main/java/org/session/libsession/network/snode/SnodeDirectory.kt b/app/src/main/java/org/session/libsession/network/snode/SnodeDirectory.kt index 1b1f9cac36..e1b4e7a397 100644 --- a/app/src/main/java/org/session/libsession/network/snode/SnodeDirectory.kt +++ b/app/src/main/java/org/session/libsession/network/snode/SnodeDirectory.kt @@ -16,6 +16,8 @@ import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl import org.session.libsession.utilities.Environment import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SystemPreferences import org.session.libsignal.crypto.secureRandom import org.session.libsignal.crypto.shuffledSequence import org.session.libsignal.utilities.Log @@ -41,7 +43,8 @@ import javax.inject.Singleton @Singleton class SnodeDirectory @Inject constructor( private val storage: SnodePoolStorage, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val httpExecutor: Provider, private val snodeAPiExecutor: Provider, private val listSnodeApi: Provider, @@ -83,10 +86,11 @@ class SnodeDirectory @Inject constructor( // Refresh state (non-blocking trigger + real exclusion inside mutex) @Volatile private var snodePoolRefreshing = false - val seedNodePool: Set get() = when (prefs.getEnvironment()) { + val seedNodePool: Set get() = when (textSecurePreferences.getEnvironment()) { Environment.DEV_NET -> DEV_NET_SEED_NODES Environment.TEST_NET -> TEST_NET_SEED_NODES Environment.MAIN_NET -> MAIN_NET_SEED_NODES + else -> MAIN_NET_SEED_NODES } override fun onPostAppStarted() { @@ -105,7 +109,7 @@ class SnodeDirectory @Inject constructor( private fun persistSnodePool(newPool: List) { storage.setSnodePool(newPool) - prefs.setLastSnodePoolRefresh(System.currentTimeMillis()) + preferenceStorage[SystemPreferences.LAST_SNODE_POOL_REFRESH] = System.currentTimeMillis() } /** @@ -126,9 +130,9 @@ class SnodeDirectory @Inject constructor( if (current.size >= minCount) { // ensure we set the refresh timestamp in case we are starting the app // with already cached snodes - set the timestamp to stale to enforce a refresh soon - if (prefs.getLastSnodePoolRefresh() == 0L) { + if (preferenceStorage[SystemPreferences.LAST_SNODE_POOL_REFRESH] == 0L) { // Force a refresh on next opportunity - prefs.setLastSnodePoolRefresh(System.currentTimeMillis() - POOL_REFRESH_INTERVAL_MS - 1) + preferenceStorage[SystemPreferences.LAST_SNODE_POOL_REFRESH] = System.currentTimeMillis() - POOL_REFRESH_INTERVAL_MS - 1 } return current @@ -272,7 +276,7 @@ class SnodeDirectory @Inject constructor( */ fun refreshPoolIfStaleAsync() { // Don’t refresh until we’ve successfully seeded at least once - val last = prefs.getLastSnodePoolRefresh() + val last = preferenceStorage[SystemPreferences.LAST_SNODE_POOL_REFRESH] if (last == 0L) return val now = System.currentTimeMillis() @@ -304,7 +308,7 @@ class SnodeDirectory @Inject constructor( poolWriteMutex.withLock { // Re-check staleness INSIDE the lock to avoid “double refresh” races - val last = prefs.getLastSnodePoolRefresh() + val last = preferenceStorage[SystemPreferences.LAST_SNODE_POOL_REFRESH] if (last == 0L) return// still not seeded val now = System.currentTimeMillis() if (now >= last && now - last < POOL_REFRESH_INTERVAL_MS) return diff --git a/app/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt b/app/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt index 81a63f787d..a9bdb418f3 100644 --- a/app/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt +++ b/app/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt @@ -79,16 +79,9 @@ import javax.inject.Singleton interface TextSecurePreferences { - fun getConfigurationMessageSynced(): Boolean - fun setConfigurationMessageSynced(value: Boolean) - fun setPushEnabled(value: Boolean) val pushEnabled: StateFlow - fun isScreenLockEnabled(): Boolean - fun setScreenLockEnabled(value: Boolean) - fun getScreenLockTimeout(): Long - fun setScreenLockTimeout(value: Long) fun setBackupPassphrase(passphrase: String?) fun getBackupPassphrase(): String? fun setEncryptedBackupPassphrase(encryptedPassphrase: String?) @@ -99,57 +92,12 @@ interface TextSecurePreferences { fun getNextBackupTime(): Long fun setBackupSaveDir(dirUri: String?) fun getBackupSaveDir(): String? - fun getNeedsSqlCipherMigration(): Boolean - fun isIncognitoKeyboardEnabled(): Boolean - fun setIncognitoKeyboardEnabled(enabled : Boolean) - fun isReadReceiptsEnabled(): Boolean - fun setReadReceiptsEnabled(enabled: Boolean) - fun isTypingIndicatorsEnabled(): Boolean - fun setTypingIndicatorsEnabled(enabled: Boolean) - fun isLinkPreviewsEnabled(): Boolean - fun setLinkPreviewsEnabled(enabled: Boolean) - fun hasSeenGIFMetaDataWarning(): Boolean - fun setHasSeenGIFMetaDataWarning() - fun isGifSearchInGridLayout(): Boolean - fun setIsGifSearchInGridLayout(isGrid: Boolean) - fun getMessageBodyTextSize(): Int fun setPreferredCameraDirection(value: CameraSelector) fun getPreferredCameraDirection(): CameraSelector - fun setNotificationPrivacy(string : String) - fun getNotificationPrivacy(): NotificationPrivacyPreference - fun getRepeatAlertsCount(): Int - fun isInThreadNotifications(): Boolean - fun isUniversalUnidentifiedAccess(): Boolean - fun getUpdateApkRefreshTime(): Long - fun setUpdateApkRefreshTime(value: Long) - fun setUpdateApkDownloadId(value: Long) - fun getUpdateApkDownloadId(): Long - fun setUpdateApkDigest(value: String?) - fun getUpdateApkDigest(): String? - fun getHasLegacyConfig(): Boolean - fun setHasLegacyConfig(newValue: Boolean) - fun isPasswordDisabled(): Boolean - fun setPasswordDisabled(disabled: Boolean) - fun getLastVersionCode(): Int - fun setLastVersionCode(versionCode: Int) - fun isPassphraseTimeoutEnabled(): Boolean - fun getPassphraseTimeoutInterval(): Int - fun getLanguage(): String? - fun isNotificationsEnabled(): Boolean fun getNotificationRingtone(): Uri fun removeNotificationRingtone() fun setNotificationRingtone(ringtone: String?) - fun setNotificationVibrateEnabled(enabled: Boolean) - fun isNotificationVibrateEnabled(): Boolean - fun setSoundWhenAppIsOpenEnabled(enabled: Boolean) - fun isSoundWhenAppIsOpenEnabled(): Boolean fun getNotificationLedColor(): Int - fun setThreadLengthTrimmingEnabled(enabled : Boolean) - fun isThreadLengthTrimmingEnabled(): Boolean - fun getNotificationChannelVersion(): Int - fun setNotificationChannelVersion(version: Int) - fun getNotificationMessagesChannelVersion(): Int - fun setNotificationMessagesChannelVersion(version: Int) fun getBooleanPreference(key: String?, defaultValue: Boolean): Boolean fun setBooleanPreference(key: String?, value: Boolean) fun getStringPreference(key: String, defaultValue: String?): String? @@ -162,56 +110,24 @@ interface TextSecurePreferences { fun removePreference(key: String) fun getStringSetPreference(key: String, defaultValues: Set): Set? fun setStringSetPreference(key: String, value: Set) - fun getLastOpenTimeDate(): Long - fun setLastOpenDate() - fun hasSeenLinkPreviewSuggestionDialog(): Boolean - fun setHasSeenLinkPreviewSuggestionDialog() - fun hasHiddenMessageRequests(): Boolean - fun setHasHiddenMessageRequests(hidden: Boolean) - fun forceCurrentUserAsPro(): Boolean - fun setForceCurrentUserAsPro(isPro: Boolean) - fun forceOtherUsersAsPro(): Boolean - fun setForceOtherUsersAsPro(isPro: Boolean) - fun forceIncomingMessagesAsPro(): Boolean - fun setForceIncomingMessagesAsPro(isPro: Boolean) - fun forcePostPro(): Boolean - fun setForcePostPro(postPro: Boolean) - fun hasSeenProExpiring(): Boolean - fun setHasSeenProExpiring() - fun hasSeenProExpired(): Boolean - fun setHasSeenProExpired() fun watchPostProStatus(): StateFlow fun setShownCallWarning(): Boolean fun setShownCallNotification(): Boolean - fun setCallNotificationsEnabled(enabled : Boolean) - fun isCallNotificationsEnabled(): Boolean - fun getLastVacuum(): Long - fun setLastVacuumNow() fun getFingerprintKeyGenerated(): Boolean fun setFingerprintKeyGenerated() - fun getSelectedAccentColor(): String? @StyleRes fun getAccentColorStyle(): Int? fun setAccentColorStyle(@StyleRes newColorStyle: Int?) fun getThemeStyle(): String fun getFollowSystemSettings(): Boolean fun setThemeStyle(themeStyle: String) fun setFollowSystemSettings(followSystemSettings: Boolean) - fun setAutoplayAudioMessages(enabled : Boolean) - fun isAutoplayAudioMessagesEnabled(): Boolean - fun hasForcedNewConfig(): Boolean fun hasPreference(key: String): Boolean fun clearAll() fun getHidePassword(): Boolean fun setHidePassword(value: Boolean) fun watchHidePassword(): StateFlow - fun getLastVersionCheck(): Long - fun setLastVersionCheck() fun getEnvironment(): Environment fun setEnvironment(value: Environment) - fun hasSeenTokenPageNotification(): Boolean - fun setHasSeenTokenPageNotification(value: Boolean) - fun forcedShortTTL(): Boolean - fun setForcedShortTTL(value: Boolean) fun getDebugMessageFeatures(): Set fun setDebugMessageFeatures(features: Set) @@ -220,26 +136,6 @@ interface TextSecurePreferences { fun setDebugSubscriptionType(status: DebugMenuViewModel.DebugSubscriptionStatus?) fun getDebugProPlanStatus(): DebugMenuViewModel.DebugProPlanStatus? fun setDebugProPlanStatus(status: DebugMenuViewModel.DebugProPlanStatus?) - fun getDebugForceNoBilling(): Boolean - fun setDebugForceNoBilling(hasBilling: Boolean) - fun getDebugIsWithinQuickRefund(): Boolean - fun setDebugIsWithinQuickRefund(isWithin: Boolean) - - fun setSubscriptionProvider(provider: String) - fun getSubscriptionProvider(): String? - - fun hasCheckedDozeWhitelist(): Boolean - fun setHasCheckedDozeWhitelist(hasChecked: Boolean) - fun hasDonated(): Boolean - fun setHasDonated(hasDonated: Boolean) - fun hasCopiedDonationURL(): Boolean - fun setHasCopiedDonationURL(hasCopied: Boolean) - fun seenDonationCTAAmount(): Int - fun setSeenDonationCTAAmount(amount: Int) - fun lastSeenDonationCTA(): Long - fun setLastSeenDonationCTA(timestamp: Long) - fun showDonationCTAFromPositiveReview(): Boolean - fun setShowDonationCTAFromPositiveReview(show: Boolean) fun hasDonatedDebug(): String? fun setHasDonatedDebug(hasDonated: String?) @@ -250,30 +146,14 @@ interface TextSecurePreferences { fun showDonationCTAFromPositiveReviewDebug(): String? fun setShowDonationCTAFromPositiveReviewDebug(show: String?) - fun getLastSnodePoolRefresh(): Long - fun setLastSnodePoolRefresh(epochMs: Long) - fun getLastPathRotation(): Long - fun setLastPathRotation(epochMs: Long) - - fun setSendWithEnterEnabled(enabled: Boolean) - fun isSendWithEnterEnabled() : Boolean fun updateBooleanFromKey(key : String, value : Boolean) var deprecationStateOverride: String? var deprecatedTimeOverride: ZonedDateTime? var deprecatingStartTimeOverride: ZonedDateTime? - var migratedToGroupV2Config: Boolean - var migratedToDisablingKDF: Boolean var migratedDisappearingMessagesToMessageContent: Boolean - var selectedActivityAliasName: String? - - var inAppReviewState: String? - var forcesDeterministicAttachmentEncryption: Boolean - var debugAvatarReupload: Boolean - var alternativeFileServer: FileServer? - companion object { val TAG = TextSecurePreferences::class.simpleName @@ -281,9 +161,6 @@ interface TextSecurePreferences { internal val _events = MutableSharedFlow(0, 64, BufferOverflow.DROP_OLDEST) val events get() = _events.asSharedFlow() - @JvmStatic - var pushSuffix = "" - const val DISABLE_PASSPHRASE_PREF = "pref_disable_passphrase" const val LANGUAGE_PREF = "pref_language" @@ -425,62 +302,6 @@ interface TextSecurePreferences { return getBooleanPreference(context, IS_PUSH_ENABLED, false) } - // endregion - @JvmStatic - fun isScreenLockEnabled(context: Context): Boolean { - return getBooleanPreference(context, SCREEN_LOCK, false) - } - - @JvmStatic - fun setScreenLockEnabled(context: Context, value: Boolean) { - setBooleanPreference(context, SCREEN_LOCK, value) - } - - @JvmStatic - fun getScreenLockTimeout(context: Context): Long { - return getLongPreference(context, SCREEN_LOCK_TIMEOUT, 0) - } - - @JvmStatic - fun setScreenLockTimeout(context: Context, value: Long) { - setLongPreference(context, SCREEN_LOCK_TIMEOUT, value) - } - - @JvmStatic - fun isIncognitoKeyboardEnabled(context: Context): Boolean { - return getBooleanPreference(context, INCOGNITO_KEYBOARD_PREF, true) - } - - @JvmStatic - fun isReadReceiptsEnabled(context: Context): Boolean { - return getBooleanPreference(context, READ_RECEIPTS_PREF, false) - } - - @JvmStatic - fun isGifSearchInGridLayout(context: Context): Boolean { - return getBooleanPreference(context, GIF_GRID_LAYOUT, false) - } - - @JvmStatic - fun setIsGifSearchInGridLayout(context: Context, isGrid: Boolean) { - setBooleanPreference(context, GIF_GRID_LAYOUT, isGrid) - } - - @JvmStatic - fun getNotificationPrivacy(context: Context): NotificationPrivacyPreference { - return NotificationPrivacyPreference(getStringPreference(context, NOTIFICATION_PRIVACY_PREF, "all")) - } - - @JvmStatic - fun isPasswordDisabled(context: Context): Boolean { - return getBooleanPreference(context, DISABLE_PASSPHRASE_PREF, true) - } - - fun setPasswordDisabled(context: Context, disabled: Boolean) { - setBooleanPreference(context, DISABLE_PASSPHRASE_PREF, disabled) - _events.tryEmit(DISABLE_PASSPHRASE_PREF) - } - fun getLastVersionCode(context: Context): Int { return getIntegerPreference(context, LAST_VERSION_CODE_PREF, 0) } @@ -492,21 +313,6 @@ interface TextSecurePreferences { } } - @JvmStatic - fun isPassphraseTimeoutEnabled(context: Context): Boolean { - return getBooleanPreference(context, PASSPHRASE_TIMEOUT_PREF, false) - } - - @JvmStatic - fun getPassphraseTimeoutInterval(context: Context): Int { - return getIntegerPreference(context, PASSPHRASE_TIMEOUT_INTERVAL_PREF, 5 * 60) - } - - @JvmStatic - fun isNotificationsEnabled(context: Context): Boolean { - return getBooleanPreference(context, NOTIFICATION_PREF, true) - } - @JvmStatic fun getNotificationRingtone(context: Context): Uri { var result = getStringPreference(context, RINGTONE_PREF, Settings.System.DEFAULT_NOTIFICATION_URI.toString()) @@ -516,41 +322,11 @@ interface TextSecurePreferences { return Uri.parse(result) } - @JvmStatic - fun isNotificationVibrateEnabled(context: Context): Boolean { - return getBooleanPreference(context, VIBRATE_PREF, true) - } - @JvmStatic fun getNotificationLedColor(context: Context): Int { return getIntegerPreference(context, LED_COLOR_PREF_PRIMARY, ThemeUtil.getThemedColor(context, R.attr.colorAccent)) } - @JvmStatic - fun isThreadLengthTrimmingEnabled(context: Context): Boolean { - return getBooleanPreference(context, THREAD_TRIM_ENABLED, true) - } - - @JvmStatic - fun getNotificationChannelVersion(context: Context): Int { - return getIntegerPreference(context, NOTIFICATION_CHANNEL_VERSION, 1) - } - - @JvmStatic - fun setNotificationChannelVersion(context: Context, version: Int) { - setIntegerPreference(context, NOTIFICATION_CHANNEL_VERSION, version) - } - - @JvmStatic - fun getNotificationMessagesChannelVersion(context: Context): Int { - return getIntegerPreference(context, NOTIFICATION_MESSAGES_CHANNEL_VERSION, 1) - } - - @JvmStatic - fun setNotificationMessagesChannelVersion(context: Context, version: Int) { - setIntegerPreference(context, NOTIFICATION_MESSAGES_CHANNEL_VERSION, version) - } - @JvmStatic fun getBooleanPreference(context: Context, key: String?, defaultValue: Boolean): Boolean { return getDefaultSharedPreferences(context).getBoolean(key, defaultValue) @@ -610,17 +386,6 @@ interface TextSecurePreferences { return getLongPreference(context, PROFILE_PIC_EXPIRY, 0) } - @JvmStatic - fun removeHasHiddenMessageRequests(context: Context) { - removePreference(context, HAS_HIDDEN_MESSAGE_REQUESTS) - _events.tryEmit(HAS_HIDDEN_MESSAGE_REQUESTS) - } - - @JvmStatic - fun isCallNotificationsEnabled(context: Context): Boolean { - return getBooleanPreference(context, CALL_NOTIFICATIONS_ENABLED, false) - } - @JvmStatic fun getLastVacuumTime(context: Context): Long { return getLongPreference(context, LAST_VACUUM_TIME, 0) @@ -663,35 +428,10 @@ class AppTextSecurePreferences @Inject constructor( private val postProLaunchState = MutableStateFlow(getBooleanPreference(SET_FORCE_POST_PRO, if (BuildConfig.BUILD_TYPE != "release") true else false)) private val hiddenPasswordState = MutableStateFlow(getBooleanPreference(HIDE_PASSWORD, false)) - override var migratedToGroupV2Config: Boolean - get() = getBooleanPreference(TextSecurePreferences.MIGRATED_TO_GROUP_V2_CONFIG, false) - set(value) = setBooleanPreference(TextSecurePreferences.MIGRATED_TO_GROUP_V2_CONFIG, value) - - override var migratedToDisablingKDF: Boolean - get() = getBooleanPreference(TextSecurePreferences.MIGRATED_TO_DISABLING_KDF, false) - set(value) = getDefaultSharedPreferences(context).edit(commit = true) { - putBoolean(TextSecurePreferences.MIGRATED_TO_DISABLING_KDF, value) - } - override var migratedDisappearingMessagesToMessageContent: Boolean get() = getBooleanPreference("migrated_disappearing_messages_to_message_content", false) set(value) = setBooleanPreference("migrated_disappearing_messages_to_message_content", value) - override fun getConfigurationMessageSynced(): Boolean { - return getBooleanPreference(TextSecurePreferences.CONFIGURATION_SYNCED, false) - } - - override var selectedActivityAliasName: String? - get() = getStringPreference("selected_activity_alias_name", null) - set(value) { - setStringPreference("selected_activity_alias_name", value) - } - - override fun setConfigurationMessageSynced(value: Boolean) { - setBooleanPreference(TextSecurePreferences.CONFIGURATION_SYNCED, value) - _events.tryEmit(TextSecurePreferences.CONFIGURATION_SYNCED) - } - override val pushEnabled: MutableStateFlow = MutableStateFlow( getBooleanPreference(TextSecurePreferences.IS_PUSH_ENABLED, false) ) @@ -701,23 +441,6 @@ class AppTextSecurePreferences @Inject constructor( pushEnabled.value = value } - override fun isScreenLockEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.SCREEN_LOCK, false) - } - - override fun setScreenLockEnabled(value: Boolean) { - setBooleanPreference(TextSecurePreferences.SCREEN_LOCK, value) - _events.tryEmit(TextSecurePreferences.SCREEN_LOCK,) - } - - override fun getScreenLockTimeout(): Long { - return getLongPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT, 0) - } - - override fun setScreenLockTimeout(value: Long) { - setLongPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT, value) - } - override fun setBackupPassphrase(passphrase: String?) { setStringPreference(TextSecurePreferences.BACKUP_PASSPHRASE, passphrase) } @@ -758,66 +481,6 @@ class AppTextSecurePreferences @Inject constructor( return getStringPreference(TextSecurePreferences.BACKUP_SAVE_DIR, null) } - override fun getNeedsSqlCipherMigration(): Boolean { - return getBooleanPreference(TextSecurePreferences.NEEDS_SQLCIPHER_MIGRATION, false) - } - - override fun isIncognitoKeyboardEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.INCOGNITO_KEYBOARD_PREF, true) - } - - override fun setIncognitoKeyboardEnabled(enabled: Boolean) { - setBooleanPreference(TextSecurePreferences.INCOGNITO_KEYBOARD_PREF, enabled) - _events.tryEmit(TextSecurePreferences.INCOGNITO_KEYBOARD_PREF) - } - - override fun isReadReceiptsEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.READ_RECEIPTS_PREF, false) - } - - override fun setReadReceiptsEnabled(enabled: Boolean) { - setBooleanPreference(TextSecurePreferences.READ_RECEIPTS_PREF, enabled) - _events.tryEmit(TextSecurePreferences.READ_RECEIPTS_PREF) - } - - override fun isTypingIndicatorsEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.TYPING_INDICATORS, false) - } - - override fun setTypingIndicatorsEnabled(enabled: Boolean) { - setBooleanPreference(TextSecurePreferences.TYPING_INDICATORS, enabled) - _events.tryEmit(TextSecurePreferences.TYPING_INDICATORS) - } - - override fun isLinkPreviewsEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.LINK_PREVIEWS, false) - } - - override fun setLinkPreviewsEnabled(enabled: Boolean) { - setBooleanPreference(TextSecurePreferences.LINK_PREVIEWS, enabled) - _events.tryEmit(TextSecurePreferences.LINK_PREVIEWS) - } - - override fun hasSeenGIFMetaDataWarning(): Boolean { - return getBooleanPreference(TextSecurePreferences.GIF_METADATA_WARNING, false) - } - - override fun setHasSeenGIFMetaDataWarning() { - setBooleanPreference(TextSecurePreferences.GIF_METADATA_WARNING, true) - } - - override fun isGifSearchInGridLayout(): Boolean { - return getBooleanPreference(TextSecurePreferences.GIF_GRID_LAYOUT, false) - } - - override fun setIsGifSearchInGridLayout(isGrid: Boolean) { - setBooleanPreference(TextSecurePreferences.GIF_GRID_LAYOUT, isGrid) - } - - override fun getMessageBodyTextSize(): Int { - return getStringPreference(TextSecurePreferences.MESSAGE_BODY_TEXT_SIZE_PREF, "16")!!.toInt() - } - override fun setPreferredCameraDirection(value: CameraSelector) { setIntegerPreference(TextSecurePreferences.DIRECT_CAPTURE_CAMERA_ID, when(value){ @@ -833,101 +496,6 @@ class AppTextSecurePreferences @Inject constructor( } } - override fun setNotificationPrivacy(string: String) { - setStringPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF, string) - _events.tryEmit(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF) - } - - override fun getNotificationPrivacy(): NotificationPrivacyPreference { - return NotificationPrivacyPreference(getStringPreference( - TextSecurePreferences.NOTIFICATION_PRIVACY_PREF, "all")) - } - - override fun getRepeatAlertsCount(): Int { - return try { - getStringPreference(TextSecurePreferences.REPEAT_ALERTS_PREF, "0")!!.toInt() - } catch (e: NumberFormatException) { - Log.w(TextSecurePreferences.TAG, e) - 0 - } - } - - override fun isInThreadNotifications(): Boolean { - return getBooleanPreference(TextSecurePreferences.IN_THREAD_NOTIFICATION_PREF, true) - } - - override fun isUniversalUnidentifiedAccess(): Boolean { - return getBooleanPreference(TextSecurePreferences.UNIVERSAL_UNIDENTIFIED_ACCESS, false) - } - - override fun getUpdateApkRefreshTime(): Long { - return getLongPreference(TextSecurePreferences.UPDATE_APK_REFRESH_TIME_PREF, 0L) - } - - override fun setUpdateApkRefreshTime(value: Long) { - setLongPreference(TextSecurePreferences.UPDATE_APK_REFRESH_TIME_PREF, value) - } - - override fun setUpdateApkDownloadId(value: Long) { - setLongPreference(TextSecurePreferences.UPDATE_APK_DOWNLOAD_ID, value) - } - - override fun getUpdateApkDownloadId(): Long { - return getLongPreference(TextSecurePreferences.UPDATE_APK_DOWNLOAD_ID, -1) - } - - override fun setUpdateApkDigest(value: String?) { - setStringPreference(TextSecurePreferences.UPDATE_APK_DIGEST, value) - } - - override fun getUpdateApkDigest(): String? { - return getStringPreference(TextSecurePreferences.UPDATE_APK_DIGEST, null) - } - - override fun getHasLegacyConfig(): Boolean { - return getBooleanPreference(TextSecurePreferences.HAS_RECEIVED_LEGACY_CONFIG, false) - } - - override fun setHasLegacyConfig(newValue: Boolean) { - setBooleanPreference(TextSecurePreferences.HAS_RECEIVED_LEGACY_CONFIG, newValue) - _events.tryEmit(TextSecurePreferences.HAS_RECEIVED_LEGACY_CONFIG) - } - - override fun isPasswordDisabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.DISABLE_PASSPHRASE_PREF, true) - } - - override fun setPasswordDisabled(disabled: Boolean) { - setBooleanPreference(TextSecurePreferences.DISABLE_PASSPHRASE_PREF, disabled) - } - - override fun getLastVersionCode(): Int { - return getIntegerPreference(TextSecurePreferences.LAST_VERSION_CODE_PREF, 0) - } - - @Throws(IOException::class) - override fun setLastVersionCode(versionCode: Int) { - if (!setIntegerPreferenceBlocking(TextSecurePreferences.LAST_VERSION_CODE_PREF, versionCode)) { - throw IOException("couldn't write version code to sharedpreferences") - } - } - - override fun isPassphraseTimeoutEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_PREF, false) - } - - override fun getPassphraseTimeoutInterval(): Int { - return getIntegerPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF, 5 * 60) - } - - override fun getLanguage(): String? { - return getStringPreference(TextSecurePreferences.LANGUAGE_PREF, "zz") - } - - override fun isNotificationsEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.NOTIFICATION_PREF, true) - } - override fun getNotificationRingtone(): Uri { var result = getStringPreference(TextSecurePreferences.RINGTONE_PREF, Settings.System.DEFAULT_NOTIFICATION_URI.toString()) if (result != null && result.startsWith("file:")) { @@ -946,56 +514,10 @@ class AppTextSecurePreferences @Inject constructor( _events.tryEmit(TextSecurePreferences.RINGTONE_PREF) } - override fun setNotificationVibrateEnabled(enabled: Boolean) { - setBooleanPreference(TextSecurePreferences.VIBRATE_PREF, enabled) - _events.tryEmit(TextSecurePreferences.VIBRATE_PREF) - } - - override fun isNotificationVibrateEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.VIBRATE_PREF, true) - } - - override fun setSoundWhenAppIsOpenEnabled(enabled: Boolean) { - setBooleanPreference(TextSecurePreferences.SOUND_WHEN_OPEN, enabled) - _events.tryEmit(TextSecurePreferences.SOUND_WHEN_OPEN) - } - - override fun isSoundWhenAppIsOpenEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.SOUND_WHEN_OPEN, false) - } - override fun getNotificationLedColor(): Int { return getIntegerPreference(TextSecurePreferences.LED_COLOR_PREF_PRIMARY, context.getColor(R.color.accent_green)) } - override fun setThreadLengthTrimmingEnabled(enabled: Boolean) { - setBooleanPreference(TextSecurePreferences.THREAD_TRIM_ENABLED, enabled) - _events.tryEmit(TextSecurePreferences.THREAD_TRIM_ENABLED) - } - - override fun isThreadLengthTrimmingEnabled(): Boolean { - return getBooleanPreference(TextSecurePreferences.THREAD_TRIM_ENABLED, true) - } - - override fun getNotificationChannelVersion(): Int { - return getIntegerPreference(TextSecurePreferences.NOTIFICATION_CHANNEL_VERSION, 1) - } - - override fun setNotificationChannelVersion(version: Int) { - setIntegerPreference(TextSecurePreferences.NOTIFICATION_CHANNEL_VERSION, version) - } - - override fun getNotificationMessagesChannelVersion(): Int { - return getIntegerPreference(TextSecurePreferences.NOTIFICATION_MESSAGES_CHANNEL_VERSION, 1) - } - - override fun setNotificationMessagesChannelVersion(version: Int) { - setIntegerPreference(TextSecurePreferences.NOTIFICATION_MESSAGES_CHANNEL_VERSION, version) - } - - override fun hasForcedNewConfig(): Boolean = - getBooleanPreference(TextSecurePreferences.HAS_FORCED_NEW_CONFIG, false) - override fun getBooleanPreference(key: String?, defaultValue: Boolean): Boolean { return getDefaultSharedPreferences(context).getBoolean(key, defaultValue) } @@ -1053,157 +575,6 @@ class AppTextSecurePreferences @Inject constructor( getDefaultSharedPreferences(context).edit { putStringSet(key, value) } } - override fun getLastSnodePoolRefresh(): Long { - return getLongPreference(LAST_SNODE_POOL_REFRESH, 0) - } - - override fun setLastSnodePoolRefresh(epochMs: Long) { - setLongPreference(LAST_SNODE_POOL_REFRESH, epochMs) - } - - override fun getLastPathRotation(): Long { - return getLongPreference(LAST_PATH_ROTATION, 0) - } - - override fun setLastPathRotation(epochMs: Long) { - setLongPreference(LAST_PATH_ROTATION, epochMs) - } - - override fun getLastOpenTimeDate(): Long { - return getLongPreference(TextSecurePreferences.LAST_OPEN_DATE, 0) - } - - override fun setLastOpenDate() { - setLongPreference(TextSecurePreferences.LAST_OPEN_DATE, System.currentTimeMillis()) - } - - override fun hasSeenLinkPreviewSuggestionDialog(): Boolean { - return getBooleanPreference("has_seen_link_preview_suggestion_dialog", false) - } - - override fun setHasSeenLinkPreviewSuggestionDialog() { - setBooleanPreference("has_seen_link_preview_suggestion_dialog", true) - } - - override fun setCallNotificationsEnabled(enabled: Boolean) { - setBooleanPreference(CALL_NOTIFICATIONS_ENABLED, enabled) - _events.tryEmit(CALL_NOTIFICATIONS_ENABLED) - } - - override fun isCallNotificationsEnabled(): Boolean { - return getBooleanPreference(CALL_NOTIFICATIONS_ENABLED, false) - } - - override fun getLastVacuum(): Long { - return getLongPreference(LAST_VACUUM_TIME, 0) - } - - override fun setLastVacuumNow() { - setLongPreference(LAST_VACUUM_TIME, System.currentTimeMillis()) - } - - override fun getLastVersionCheck(): Long { - return getLongPreference(LAST_VERSION_CHECK, 0) - } - - override fun setLastVersionCheck() { - setLongPreference(LAST_VERSION_CHECK, System.currentTimeMillis()) - } - - override fun getEnvironment(): Environment { - val environment = getStringPreference(ENVIRONMENT, null) - return if (environment != null) { - Environment.valueOf(environment) - } else BuildConfig.DEFAULT_ENVIRONMENT - } - - override fun setEnvironment(value: Environment) { - setStringPreference(ENVIRONMENT, value.name) - } - - override fun setShownCallNotification(): Boolean { - val previousValue = getBooleanPreference(SHOWN_CALL_NOTIFICATION, false) - if (previousValue) return false - val setValue = true - setBooleanPreference(SHOWN_CALL_NOTIFICATION, setValue) - return previousValue != setValue - } - - - /** - * Set the SHOWN_CALL_WARNING preference to `true` - * Return `true` if the value did update (it was previously unset) - */ - override fun setShownCallWarning() : Boolean { - val previousValue = getBooleanPreference(SHOWN_CALL_WARNING, false) - if (previousValue) { - return false - } - val setValue = true - setBooleanPreference(SHOWN_CALL_WARNING, setValue) - return previousValue != setValue - } - - override fun hasHiddenMessageRequests(): Boolean { - return getBooleanPreference(HAS_HIDDEN_MESSAGE_REQUESTS, false) - } - - override fun setHasHiddenMessageRequests(hidden: Boolean) { - setBooleanPreference(HAS_HIDDEN_MESSAGE_REQUESTS, hidden) - _events.tryEmit(HAS_HIDDEN_MESSAGE_REQUESTS) - } - override fun forceCurrentUserAsPro(): Boolean { - return getBooleanPreference(SET_FORCE_CURRENT_USER_PRO, false) - } - - override fun setForceCurrentUserAsPro(isPro: Boolean) { - setBooleanPreference(SET_FORCE_CURRENT_USER_PRO, isPro) - _events.tryEmit(SET_FORCE_CURRENT_USER_PRO) - } - - override fun forceOtherUsersAsPro(): Boolean { - return getBooleanPreference(SET_FORCE_OTHER_USERS_PRO, false) - } - - override fun setForceOtherUsersAsPro(isPro: Boolean) { - setBooleanPreference(SET_FORCE_OTHER_USERS_PRO, isPro) - _events.tryEmit(SET_FORCE_OTHER_USERS_PRO) - } - - override fun forceIncomingMessagesAsPro(): Boolean { - return getBooleanPreference(SET_FORCE_INCOMING_MESSAGE_PRO, false) - } - - override fun setForceIncomingMessagesAsPro(isPro: Boolean) { - setBooleanPreference(SET_FORCE_INCOMING_MESSAGE_PRO, isPro) - } - - override fun forcePostPro(): Boolean { - return postProLaunchState.value - } - - override fun setForcePostPro(postPro: Boolean) { - setBooleanPreference(SET_FORCE_POST_PRO, postPro) - postProLaunchState.update { postPro } - _events.tryEmit(SET_FORCE_POST_PRO) - } - - override fun hasSeenProExpiring(): Boolean { - return getBooleanPreference(HAS_SEEN_PRO_EXPIRING, false) - } - - override fun setHasSeenProExpiring() { - setBooleanPreference(HAS_SEEN_PRO_EXPIRING, true) - } - - override fun hasSeenProExpired(): Boolean { - return getBooleanPreference(HAS_SEEN_PRO_EXPIRED, false) - } - - override fun setHasSeenProExpired() { - setBooleanPreference(HAS_SEEN_PRO_EXPIRED, true) - } - override fun watchPostProStatus(): StateFlow { return postProLaunchState } @@ -1216,12 +587,10 @@ class AppTextSecurePreferences @Inject constructor( setBooleanPreference(TextSecurePreferences.FINGERPRINT_KEY_GENERATED, true) } - override fun getSelectedAccentColor(): String? = - getStringPreference(SELECTED_ACCENT_COLOR, null) - @StyleRes override fun getAccentColorStyle(): Int? { - return when (getSelectedAccentColor()) { + val selectedAccentColor = getStringPreference(TextSecurePreferences.SELECTED_ACCENT_COLOR, null) + return when (selectedAccentColor) { TextSecurePreferences.GREEN_ACCENT -> R.style.PrimaryGreen TextSecurePreferences.BLUE_ACCENT -> R.style.PrimaryBlue TextSecurePreferences.PURPLE_ACCENT -> R.style.PrimaryPurple @@ -1235,7 +604,7 @@ class AppTextSecurePreferences @Inject constructor( override fun setAccentColorStyle(@StyleRes newColorStyle: Int?) { setStringPreference( - SELECTED_ACCENT_COLOR, when (newColorStyle) { + TextSecurePreferences.SELECTED_ACCENT_COLOR, when (newColorStyle) { R.style.PrimaryGreen -> TextSecurePreferences.GREEN_ACCENT R.style.PrimaryBlue -> TextSecurePreferences.BLUE_ACCENT R.style.PrimaryPurple -> TextSecurePreferences.PURPLE_ACCENT @@ -1249,62 +618,53 @@ class AppTextSecurePreferences @Inject constructor( } override fun getThemeStyle(): String { - val hasLegacy = getStringPreference(LEGACY_PREF_KEY_SELECTED_UI_MODE, null) + val hasLegacy = getStringPreference(TextSecurePreferences.LEGACY_PREF_KEY_SELECTED_UI_MODE, null) if (!hasLegacy.isNullOrEmpty()) { migrateLegacyUiPref() } - return getStringPreference(SELECTED_STYLE, CLASSIC_DARK)!! + return getStringPreference(TextSecurePreferences.SELECTED_STYLE, TextSecurePreferences.CLASSIC_DARK)!! } override fun setThemeStyle(themeStyle: String) { - val safeTheme = if (themeStyle !in listOf(CLASSIC_DARK, CLASSIC_LIGHT, OCEAN_DARK, OCEAN_LIGHT)) CLASSIC_DARK else themeStyle - setStringPreference(SELECTED_STYLE, safeTheme) + val safeTheme = if (themeStyle !in listOf(TextSecurePreferences.CLASSIC_DARK, TextSecurePreferences.CLASSIC_LIGHT, TextSecurePreferences.OCEAN_DARK, TextSecurePreferences.OCEAN_LIGHT)) TextSecurePreferences.CLASSIC_DARK else themeStyle + setStringPreference(TextSecurePreferences.SELECTED_STYLE, safeTheme) } override fun getFollowSystemSettings(): Boolean { - val hasLegacy = getStringPreference(LEGACY_PREF_KEY_SELECTED_UI_MODE, null) + val hasLegacy = getStringPreference(TextSecurePreferences.LEGACY_PREF_KEY_SELECTED_UI_MODE, null) if (!hasLegacy.isNullOrEmpty()) { migrateLegacyUiPref() } - return getBooleanPreference(FOLLOW_SYSTEM_SETTINGS, false) + return getBooleanPreference(TextSecurePreferences.FOLLOW_SYSTEM_SETTINGS, false) } private fun migrateLegacyUiPref() { - val legacy = getStringPreference(LEGACY_PREF_KEY_SELECTED_UI_MODE, null) ?: return + val legacy = getStringPreference(TextSecurePreferences.LEGACY_PREF_KEY_SELECTED_UI_MODE, null) ?: return val (mode, followSystem) = when (legacy) { "DAY" -> { - CLASSIC_LIGHT to false + TextSecurePreferences.CLASSIC_LIGHT to false } "NIGHT" -> { - CLASSIC_DARK to false + TextSecurePreferences.CLASSIC_DARK to false } "SYSTEM_DEFAULT" -> { - CLASSIC_DARK to true + TextSecurePreferences.CLASSIC_DARK to true } else -> { - CLASSIC_DARK to false + TextSecurePreferences.CLASSIC_DARK to false } } - if (!hasPreference(FOLLOW_SYSTEM_SETTINGS) && !hasPreference(SELECTED_STYLE)) { + if (!hasPreference(TextSecurePreferences.FOLLOW_SYSTEM_SETTINGS) && !hasPreference(TextSecurePreferences.SELECTED_STYLE)) { setThemeStyle(mode) setFollowSystemSettings(followSystem) } - removePreference(LEGACY_PREF_KEY_SELECTED_UI_MODE) + removePreference(TextSecurePreferences.LEGACY_PREF_KEY_SELECTED_UI_MODE) } override fun setFollowSystemSettings(followSystemSettings: Boolean) { - setBooleanPreference(FOLLOW_SYSTEM_SETTINGS, followSystemSettings) - } - - override fun setAutoplayAudioMessages(enabled: Boolean) { - setBooleanPreference(AUTOPLAY_AUDIO_MESSAGES, enabled) - _events.tryEmit(AUTOPLAY_AUDIO_MESSAGES) - } - - override fun isAutoplayAudioMessagesEnabled(): Boolean { - return getBooleanPreference(AUTOPLAY_AUDIO_MESSAGES, false) + setBooleanPreference(TextSecurePreferences.FOLLOW_SYSTEM_SETTINGS, followSystemSettings) } /** @@ -1318,10 +678,10 @@ class AppTextSecurePreferences @Inject constructor( getDefaultSharedPreferences(context).edit(commit = true) { clear() } } - override fun getHidePassword() = getBooleanPreference(HIDE_PASSWORD, false) + override fun getHidePassword() = getBooleanPreference(TextSecurePreferences.HIDE_PASSWORD, false) override fun setHidePassword(value: Boolean) { - setBooleanPreference(HIDE_PASSWORD, value) + setBooleanPreference(TextSecurePreferences.HIDE_PASSWORD, value) hiddenPasswordState.update { value } } @@ -1329,55 +689,40 @@ class AppTextSecurePreferences @Inject constructor( return hiddenPasswordState } - override fun hasSeenTokenPageNotification(): Boolean { - return getBooleanPreference(HAVE_SHOWN_A_NOTIFICATION_ABOUT_TOKEN_PAGE, false) - } - - override fun setHasSeenTokenPageNotification(value: Boolean) { - setBooleanPreference(HAVE_SHOWN_A_NOTIFICATION_ABOUT_TOKEN_PAGE, value) + override fun getEnvironment(): Environment { + val environment = getStringPreference(TextSecurePreferences.ENVIRONMENT, null) + return if (environment != null) { + Environment.valueOf(environment) + } else BuildConfig.DEFAULT_ENVIRONMENT } - override fun forcedShortTTL(): Boolean { - return getBooleanPreference(FORCED_SHORT_TTL, false) + override fun setEnvironment(value: Environment) { + setStringPreference(TextSecurePreferences.ENVIRONMENT, value.name) } - override fun setForcedShortTTL(value: Boolean) { - setBooleanPreference(FORCED_SHORT_TTL, value) + override fun setShownCallNotification(): Boolean { + val previousValue = getBooleanPreference(TextSecurePreferences.SHOWN_CALL_NOTIFICATION, false) + if (previousValue) return false + val setValue = true + setBooleanPreference(TextSecurePreferences.SHOWN_CALL_NOTIFICATION, setValue) + return previousValue != setValue } - override var inAppReviewState: String? - get() = getStringPreference(TextSecurePreferences.IN_APP_REVIEW_STATE, null) - set(value) = setStringPreference(TextSecurePreferences.IN_APP_REVIEW_STATE, value) - - override var deprecationStateOverride: String? - get() = getStringPreference(TextSecurePreferences.DEPRECATED_STATE_OVERRIDE, null) - set(value) { - if (value == null) { - removePreference(TextSecurePreferences.DEPRECATED_STATE_OVERRIDE) - } else { - setStringPreference(TextSecurePreferences.DEPRECATED_STATE_OVERRIDE, value) - } - } - override var deprecatedTimeOverride: ZonedDateTime? - get() = getStringPreference(TextSecurePreferences.DEPRECATED_TIME_OVERRIDE, null)?.let(ZonedDateTime::parse) - set(value) { - if (value == null) { - removePreference(TextSecurePreferences.DEPRECATED_TIME_OVERRIDE) - } else { - setStringPreference(TextSecurePreferences.DEPRECATED_TIME_OVERRIDE, value.toString()) - } + /** + * Set the SHOWN_CALL_WARNING preference to `true` + * Return `true` if the value did update (it was previously unset) + */ + override fun setShownCallWarning() : Boolean { + val previousValue = getBooleanPreference(TextSecurePreferences.SHOWN_CALL_WARNING, false) + if (previousValue) { + return false } + val setValue = true + setBooleanPreference(TextSecurePreferences.SHOWN_CALL_WARNING, setValue) + return previousValue != setValue + } - override var deprecatingStartTimeOverride: ZonedDateTime? - get() = getStringPreference(TextSecurePreferences.DEPRECATING_START_TIME_OVERRIDE, null)?.let(ZonedDateTime::parse) - set(value) { - if (value == null) { - removePreference(TextSecurePreferences.DEPRECATING_START_TIME_OVERRIDE) - } else { - setStringPreference(TextSecurePreferences.DEPRECATING_START_TIME_OVERRIDE, value.toString()) - } - } override fun getDebugMessageFeatures(): Set { return buildSet { getLongPreference(TextSecurePreferences.DEBUG_PRO_MESSAGE_FEATURES, 0L).toProMessageFeatures(this) @@ -1412,141 +757,68 @@ class AppTextSecurePreferences @Inject constructor( _events.tryEmit(TextSecurePreferences.DEBUG_PRO_PLAN_STATUS) } - override fun getDebugForceNoBilling(): Boolean { - return getBooleanPreference(TextSecurePreferences.DEBUG_FORCE_NO_BILLING, false) - } - - override fun setDebugForceNoBilling(hasBilling: Boolean) { - setBooleanPreference(TextSecurePreferences.DEBUG_FORCE_NO_BILLING, hasBilling) - _events.tryEmit(TextSecurePreferences.DEBUG_FORCE_NO_BILLING) - } - - override fun getDebugIsWithinQuickRefund(): Boolean { - return getBooleanPreference(TextSecurePreferences.DEBUG_WITHIN_QUICK_REFUND, false) - } - - override fun setDebugIsWithinQuickRefund(isWithin: Boolean) { - setBooleanPreference(TextSecurePreferences.DEBUG_WITHIN_QUICK_REFUND, isWithin) - _events.tryEmit(TextSecurePreferences.DEBUG_FORCE_NO_BILLING) - } - - override fun getSubscriptionProvider(): String? { - return getStringPreference(TextSecurePreferences.SUBSCRIPTION_PROVIDER, null) - } - - override fun setSubscriptionProvider(provider: String) { - setStringPreference(TextSecurePreferences.SUBSCRIPTION_PROVIDER, provider) - } - - override var forcesDeterministicAttachmentEncryption: Boolean - get() = getBooleanPreference("forces_deterministic_attachment_upload", false) - set(value) { - setBooleanPreference("forces_deterministic_attachment_upload", value) - } - - override var debugAvatarReupload: Boolean - get() = getBooleanPreference(TextSecurePreferences.DEBUG_AVATAR_REUPLOAD, false) - set(value) { - setBooleanPreference(TextSecurePreferences.DEBUG_AVATAR_REUPLOAD, value) - _events.tryEmit(TextSecurePreferences.DEBUG_AVATAR_REUPLOAD) - } - - override var alternativeFileServer: FileServer? - get() = getStringPreference("alternative_file_server", null)?.let { - json.decodeFromString(it) - } - - set(value) { - setStringPreference("alternative_file_server", value?.let { - json.encodeToString(it) - }) - } - - override fun hasCheckedDozeWhitelist(): Boolean { - return getBooleanPreference(HAS_CHECKED_DOZE_WHITELIST, false) - } - - override fun setHasCheckedDozeWhitelist(hasChecked: Boolean) { - setBooleanPreference(HAS_CHECKED_DOZE_WHITELIST, hasChecked) - _events.tryEmit(HAS_CHECKED_DOZE_WHITELIST) - } - - override fun hasDonated(): Boolean { - return getBooleanPreference(HAS_DONATED, false) - } - override fun setHasDonated(hasDonated: Boolean) { - setBooleanPreference(HAS_DONATED, hasDonated) - } - - override fun hasCopiedDonationURL(): Boolean { - return getBooleanPreference(HAS_COPIED_DONATION_URL, false) - } - override fun setHasCopiedDonationURL(hasCopied: Boolean) { - setBooleanPreference(HAS_COPIED_DONATION_URL, hasCopied) - } - - override fun seenDonationCTAAmount(): Int { - return getIntegerPreference(SEEN_DONATION_CTA_AMOUNT, 0) - } - override fun setSeenDonationCTAAmount(amount: Int) { - setIntegerPreference(SEEN_DONATION_CTA_AMOUNT, amount) - } - - override fun lastSeenDonationCTA(): Long { - return getLongPreference(LAST_SEEN_DONATION_CTA, 0) - } - override fun setLastSeenDonationCTA(timestamp: Long) { - setLongPreference(LAST_SEEN_DONATION_CTA, timestamp) - } - - override fun showDonationCTAFromPositiveReview(): Boolean { - return getBooleanPreference(SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW, false) - } - override fun setShowDonationCTAFromPositiveReview(show: Boolean) { - setBooleanPreference(SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW, show) - } - override fun hasDonatedDebug(): String? { - return getStringPreference(DEBUG_HAS_DONATED, null) + return getStringPreference(TextSecurePreferences.DEBUG_HAS_DONATED, null) } override fun setHasDonatedDebug(hasDonated: String?) { - setStringPreference(DEBUG_HAS_DONATED, hasDonated) + setStringPreference(TextSecurePreferences.DEBUG_HAS_DONATED, hasDonated) } override fun hasCopiedDonationURLDebug(): String? { - return getStringPreference(DEBUG_HAS_COPIED_DONATION_URL, null) + return getStringPreference(TextSecurePreferences.DEBUG_HAS_COPIED_DONATION_URL, null) } override fun setHasCopiedDonationURLDebug(hasCopied: String?) { - setStringPreference(DEBUG_HAS_COPIED_DONATION_URL, hasCopied) + setStringPreference(TextSecurePreferences.DEBUG_HAS_COPIED_DONATION_URL, hasCopied) } override fun seenDonationCTAAmountDebug(): String? { - return getStringPreference(DEBUG_SEEN_DONATION_CTA_AMOUNT, null) + return getStringPreference(TextSecurePreferences.DEBUG_SEEN_DONATION_CTA_AMOUNT, null) } override fun setSeenDonationCTAAmountDebug(amount: String?) { - setStringPreference(DEBUG_SEEN_DONATION_CTA_AMOUNT, amount) + setStringPreference(TextSecurePreferences.DEBUG_SEEN_DONATION_CTA_AMOUNT, amount) } override fun showDonationCTAFromPositiveReviewDebug(): String? { - return getStringPreference(DEBUG_SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW, null) + return getStringPreference(TextSecurePreferences.DEBUG_SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW, null) } override fun setShowDonationCTAFromPositiveReviewDebug(show: String?) { - setStringPreference(DEBUG_SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW, show) - } - - override fun setSendWithEnterEnabled(enabled: Boolean) { - setBooleanPreference(SEND_WITH_ENTER, enabled) - _events.tryEmit(SEND_WITH_ENTER) - } - - override fun isSendWithEnterEnabled(): Boolean { - return getBooleanPreference(SEND_WITH_ENTER, false) + setStringPreference(TextSecurePreferences.DEBUG_SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW, show) } override fun updateBooleanFromKey(key: String, value: Boolean) { setBooleanPreference(key, value) _events.tryEmit(key) } + + override var deprecationStateOverride: String? + get() = getStringPreference(TextSecurePreferences.DEPRECATED_STATE_OVERRIDE, null) + set(value) { + if (value == null) { + removePreference(TextSecurePreferences.DEPRECATED_STATE_OVERRIDE) + } else { + setStringPreference(TextSecurePreferences.DEPRECATED_STATE_OVERRIDE, value) + } + } + + override var deprecatedTimeOverride: ZonedDateTime? + get() = getStringPreference(TextSecurePreferences.DEPRECATED_TIME_OVERRIDE, null)?.let(ZonedDateTime::parse) + set(value) { + if (value == null) { + removePreference(TextSecurePreferences.DEPRECATED_TIME_OVERRIDE) + } else { + setStringPreference(TextSecurePreferences.DEPRECATED_TIME_OVERRIDE, value.toString()) + } + } + + override var deprecatingStartTimeOverride: ZonedDateTime? + get() = getStringPreference(TextSecurePreferences.DEPRECATING_START_TIME_OVERRIDE, null)?.let(ZonedDateTime::parse) + set(value) { + if (value == null) { + removePreference(TextSecurePreferences.DEPRECATING_START_TIME_OVERRIDE) + } else { + setStringPreference(TextSecurePreferences.DEPRECATING_START_TIME_OVERRIDE, value.toString()) + } + } } fun TextSecurePreferences.observeBooleanKey( @@ -1567,4 +839,4 @@ fun TextSecurePreferences.observeStringKey( .filter { it == key } .onStart { emit(key) } .map { getStringPreference(key, default) } - .distinctUntilChanged() \ No newline at end of file + .distinctUntilChanged() diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.kt b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.kt index 23f74c0cb9..951c3f746c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.kt @@ -43,7 +43,6 @@ import org.session.libsession.messaging.MessagingModuleConfiguration.Companion.c import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier import org.session.libsession.utilities.SSKEnvironment import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsession.utilities.TextSecurePreferences.Companion.pushSuffix import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.auth.LoginStateRepository import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider @@ -87,6 +86,8 @@ class ApplicationContext : Application(), DefaultLifecycleObserver, Configuratio @Inject lateinit var persistentLogger: Lazy @Inject lateinit var debugLogger: Lazy @Inject lateinit var textSecurePreferences: Lazy + @Inject lateinit var notificationChannels: Lazy + @Inject lateinit var preferenceStorage: Lazy @Inject lateinit var migrationManager: Lazy @Inject lateinit var imageLoaderProvider: Provider @@ -130,8 +131,6 @@ class ApplicationContext : Application(), DefaultLifecycleObserver, Configuratio override fun onCreate() { - pushSuffix = BuildConfig.PUSH_KEY_SUFFIX - init(this) configure(this) super.onCreate() @@ -139,7 +138,7 @@ class ApplicationContext : Application(), DefaultLifecycleObserver, Configuratio initializeSecurityProvider() initializeLogging() initializeCrashHandling() - NotificationChannels.create(this) + notificationChannels.get().create() ProcessLifecycleOwner.get().lifecycle.addObserver(this) SSKEnvironment.sharedLazy = sskEnvironment diff --git a/app/src/main/java/org/thoughtcrime/securesms/ScreenLockActionBarActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/ScreenLockActionBarActivity.kt index ebe5adcd29..b0d39d3818 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ScreenLockActionBarActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ScreenLockActionBarActivity.kt @@ -16,8 +16,9 @@ import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.session.libsession.utilities.TextSecurePreferences.Companion.isScreenLockEnabled import org.session.libsignal.utilities.Log +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SecurityPreferences import org.thoughtcrime.securesms.home.HomeActivity import org.thoughtcrime.securesms.migration.DatabaseMigrationManager import org.thoughtcrime.securesms.migration.DatabaseMigrationStateActivity @@ -28,9 +29,14 @@ import org.thoughtcrime.securesms.util.FilenameUtils import java.io.File import java.io.FileOutputStream import java.util.Locale +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject +@AndroidEntryPoint abstract class ScreenLockActionBarActivity : BaseActionBarActivity() { + @Inject open lateinit var preferenceStorage: PreferenceStorage + private val migrationManager: DatabaseMigrationManager get() = (applicationContext as ApplicationContext).migrationManager.get() @@ -83,7 +89,7 @@ abstract class ScreenLockActionBarActivity : BaseActionBarActivity() { override fun onCreate(savedInstanceState: Bundle?) { Log.i(TAG, "ScreenLockActionBarActivity.onCreate(" + savedInstanceState + ")") - val locked = KeyCachingService.isLocked(this) && isScreenLockEnabled(this) && + val locked = KeyCachingService.isLocked(this) && preferenceStorage[SecurityPreferences.SCREEN_LOCK] && (applicationContext as ApplicationContext).loginStateRepository.get().peekLoginState() != null routeApplicationState(locked) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ScreenLockActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/ScreenLockActivity.kt index 1c5ba1e8b3..4e0adc0cc1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ScreenLockActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ScreenLockActivity.kt @@ -38,16 +38,20 @@ import java.lang.Exception import network.loki.messenger.R import org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsession.utilities.TextSecurePreferences.Companion.isScreenLockEnabled -import org.session.libsession.utilities.TextSecurePreferences.Companion.setScreenLockEnabled -import org.session.libsession.utilities.TextSecurePreferences.Companion.setScreenLockTimeout +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SecurityPreferences import org.session.libsession.utilities.ThemeUtil import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.crypto.BiometricSecretProvider import org.thoughtcrime.securesms.service.KeyCachingService import org.thoughtcrime.securesms.service.KeyCachingService.KeySetBinder +import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject +@AndroidEntryPoint class ScreenLockActivity : BaseActionBarActivity() { + + @Inject lateinit var preferenceStorage: PreferenceStorage private val TAG: String = ScreenLockActivity::class.java.simpleName private lateinit var fingerprintPrompt: ImageView @@ -178,7 +182,7 @@ class ScreenLockActivity : BaseActionBarActivity() { override fun onResume() { super.onResume() setLockTypeVisibility() - if (isScreenLockEnabled(this) && !authenticated && !failure) { resumeScreenLock() } + if (preferenceStorage[SecurityPreferences.SCREEN_LOCK] && !authenticated && !failure) { resumeScreenLock() } failure = false } @@ -195,8 +199,8 @@ class ScreenLockActivity : BaseActionBarActivity() { // to authenticate against! (we use the system authentication - not our own custom auth.). if (!keyguardManager.isKeyguardSecure) { Log.w(TAG, "Keyguard not secure...") - setScreenLockEnabled(applicationContext, false) - setScreenLockTimeout(applicationContext, 0) + preferenceStorage[SecurityPreferences.SCREEN_LOCK] = false + preferenceStorage[SecurityPreferences.SCREEN_LOCK_TIMEOUT] = 0L handleAuthenticated() return } @@ -294,7 +298,7 @@ class ScreenLockActivity : BaseActionBarActivity() { } private fun setLockTypeVisibility() { - val screenLockEnabled = TextSecurePreferences.isScreenLockEnabled(this) + val screenLockEnabled = preferenceStorage[SecurityPreferences.SCREEN_LOCK] val biometricManager = BiometricManager.from(this) val authenticationPossible = biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS fingerprintPrompt.visibility = if (screenLockEnabled && authenticationPossible) View.VISIBLE else View.GONE diff --git a/app/src/main/java/org/thoughtcrime/securesms/attachments/AvatarReuploadWorker.kt b/app/src/main/java/org/thoughtcrime/securesms/attachments/AvatarReuploadWorker.kt index f8a272a5aa..e84ddde1ca 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/attachments/AvatarReuploadWorker.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/attachments/AvatarReuploadWorker.kt @@ -24,7 +24,8 @@ import okio.source import org.session.libsession.messaging.file_server.FileRenewApi import org.session.libsession.messaging.file_server.FileServerApis import org.session.libsession.utilities.ConfigFactoryProtocol -import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.session.libsession.utilities.recipients.RemoteFile.Companion.toRemoteFile import org.session.libsession.utilities.withUserConfigs import org.session.libsignal.exceptions.NonRetryableException @@ -202,10 +203,10 @@ class AvatarReuploadWorker @AssistedInject constructor( return IntSize(r.first, r.second) } - suspend fun schedule(context: Context, prefs: TextSecurePreferences) { + suspend fun schedule(context: Context, preferenceStorage: PreferenceStorage) { Log.d(TAG, "Scheduling avatar reupload worker.") - val request = if (BuildConfig.DEBUG || prefs.debugAvatarReupload) { + val request = if (BuildConfig.DEBUG || preferenceStorage[MessagingPreferences.DEBUG_AVATAR_REUPLOAD]) { PeriodicWorkRequestBuilder( Duration.ofMinutes(15) ).setInitialDelay(0L, TimeUnit.MILLISECONDS) diff --git a/app/src/main/java/org/thoughtcrime/securesms/attachments/AvatarUploadManager.kt b/app/src/main/java/org/thoughtcrime/securesms/attachments/AvatarUploadManager.kt index 0222ab4641..4a9abd9c7e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/attachments/AvatarUploadManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/attachments/AvatarUploadManager.kt @@ -14,6 +14,8 @@ import org.session.libsession.utilities.AESGCM import org.session.libsession.utilities.ConfigFactoryProtocol import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.Util +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.session.libsession.utilities.recipients.RemoteFile import org.session.libsession.utilities.recipients.RemoteFile.Companion.toRemoteFile import org.session.libsession.utilities.withMutableUserConfigs @@ -39,18 +41,19 @@ import kotlin.time.Duration.Companion.seconds class AvatarUploadManager @Inject constructor( private val application: Application, private val configFactory: ConfigFactoryProtocol, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val localEncryptedFileOutputStreamFactory: LocalEncryptedFileOutputStream.Factory, private val attachmentProcessor: AttachmentProcessor, private val serverApiExecutor: ServerApiExecutor, private val fileUploadApiFactory: FileUploadApi.Factory, ) : AuthAwareComponent { override suspend fun doWhileLoggedIn(loggedInState: LoggedInState) { - TextSecurePreferences._events.filter { it == TextSecurePreferences.DEBUG_AVATAR_REUPLOAD } + preferenceStorage.changes().filter { it.name == MessagingPreferences.DEBUG_AVATAR_REUPLOAD.name } .castAwayType() .onStart { emit(Unit) } .collectLatest { - AvatarReuploadWorker.schedule(application, prefs) + AvatarReuploadWorker.schedule(application, preferenceStorage) } } @@ -73,7 +76,7 @@ class AvatarUploadManager @Inject constructor( "Should not upload an empty avatar" } - val usesDeterministicEncryption = prefs.forcesDeterministicAttachmentEncryption + val usesDeterministicEncryption = preferenceStorage[MessagingPreferences.FORCES_DETERMINISTIC_ATTACHMENT_ENCRYPTION] val result = if (usesDeterministicEncryption) { attachmentProcessor.encryptDeterministically( plaintext = pictureData, @@ -85,7 +88,7 @@ class AvatarUploadManager @Inject constructor( AttachmentProcessor.EncryptResult(ciphertext = ciphertext, key = key) } - val fileServer = prefs.alternativeFileServer ?: FileServerApis.DEFAULT_FILE_SERVER + val fileServer = preferenceStorage[MessagingPreferences.ALTERNATIVE_FILE_SERVER] ?: FileServerApis.DEFAULT_FILE_SERVER val uploadResult = serverApiExecutor.execute( ServerApiRequest( fileServer = fileServer, @@ -93,7 +96,7 @@ class AvatarUploadManager @Inject constructor( fileServer = fileServer, data = result.ciphertext, usedDeterministicEncryption = usesDeterministicEncryption, - customExpiresSeconds = DEBUG_AVATAR_TTL.takeIf { prefs.forcedShortTTL() }?.inWholeSeconds + customExpiresSeconds = DEBUG_AVATAR_TTL.takeIf { preferenceStorage[MessagingPreferences.FORCED_SHORT_TTL] }?.inWholeSeconds ) ) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 9b50b71695..47e64cca01 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -124,6 +124,10 @@ import org.session.libsession.utilities.StringSubstitutionConstants.NAME_KEY import org.session.libsession.utilities.Stub import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences.Companion.CALL_NOTIFICATIONS_ENABLED +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.NotificationPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.PrivacyPreferences import org.session.libsession.utilities.getColorFromAttr import org.session.libsession.utilities.isBlinded import org.session.libsession.utilities.recipients.Recipient @@ -260,6 +264,7 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate, private lateinit var binding: ActivityConversationV2Binding @Inject lateinit var textSecurePreferences: TextSecurePreferences + @Inject override lateinit var preferenceStorage: PreferenceStorage @Inject lateinit var threadDb: ThreadDatabase @Inject lateinit var mmsSmsDb: MmsSmsDatabase @Inject lateinit var groupDb: GroupDatabase @@ -1192,7 +1197,7 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate, } } } - if (textSecurePreferences.isTypingIndicatorsEnabled()) { + if (preferenceStorage[PrivacyPreferences.TYPING_INDICATORS]) { binding.inputBar.addTextChangedListener { if (it.isNotEmpty()) { viewModel.threadId?.let { threadId -> @@ -1281,7 +1286,7 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate, } private fun setUpLinkPreviewObserver() { - if (!textSecurePreferences.isLinkPreviewsEnabled()) { + if (!preferenceStorage[PrivacyPreferences.LINK_PREVIEWS]) { linkPreviewViewModel.onUserCancel(); return } linkPreviewViewModel.linkPreviewState.observe(this) { previewState: LinkPreviewState? -> @@ -1486,7 +1491,7 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate, override fun inputBarEditTextContentChanged(newContent: CharSequence) { val inputBarText = binding.inputBar.text - if (textSecurePreferences.isLinkPreviewsEnabled()) { + if (preferenceStorage[PrivacyPreferences.LINK_PREVIEWS]) { linkPreviewViewModel.onTextChanged(this, inputBarText) } @@ -1497,15 +1502,15 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate, override fun onInputBarEditTextPasted() { val inputBarText = binding.inputBar.text - if ( !textSecurePreferences.isLinkPreviewsEnabled() && !textSecurePreferences.hasSeenLinkPreviewSuggestionDialog() + if (!preferenceStorage[PrivacyPreferences.LINK_PREVIEWS] && !preferenceStorage[PrivacyPreferences.HAS_SEEN_LINK_PREVIEW_SUGGESTION_DIALOG] && LinkPreviewUtil.findWhitelistedUrls(inputBarText).isNotEmpty()) { viewModel.showLinkDownloadDialog { - textSecurePreferences.setLinkPreviewsEnabled(true) + preferenceStorage[PrivacyPreferences.LINK_PREVIEWS] = true setUpLinkPreviewObserver() linkPreviewViewModel.onEnabled() linkPreviewViewModel.onTextChanged(this, inputBarText) } - textSecurePreferences.setHasSeenLinkPreviewSuggestionDialog() + preferenceStorage[PrivacyPreferences.HAS_SEEN_LINK_PREVIEW_SUGGESTION_DIALOG] = true } } @@ -1718,7 +1723,7 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate, } // if the user has not enabled voice/video calls - if (!TextSecurePreferences.isCallNotificationsEnabled(this)) { + if (!preferenceStorage[NotificationPreferences.CALL_NOTIFICATIONS_ENABLED]) { showSessionDialog { title(R.string.callsPermissionsRequired) text(R.string.callsPermissionsRequiredDescription) @@ -2349,7 +2354,7 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate, } private fun playVoiceMessageAtIndexIfPossible(messageId: MessageId) { - if (!textSecurePreferences.isAutoplayAudioMessagesEnabled()) return + if (!preferenceStorage[MessagingPreferences.AUTOPLAY_AUDIO_MESSAGES]) return val finishedMessageIndex = adapter.getItemPositionForId(messageId) ?: return val nextIndex = finishedMessageIndex + 1 @@ -2582,13 +2587,13 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate, } private fun showGIFPicker() { - val hasSeenGIFMetaDataWarning: Boolean = textSecurePreferences.hasSeenGIFMetaDataWarning() + val hasSeenGIFMetaDataWarning: Boolean = preferenceStorage[PrivacyPreferences.HAS_SEEN_GIF_METADATA_WARNING] if (!hasSeenGIFMetaDataWarning) { showSessionDialog { title(R.string.giphyWarning) text(Phrase.from(context, R.string.giphyWarningDescription).put(APP_NAME_KEY, getString(R.string.app_name)).format()) button(R.string.theContinue) { - textSecurePreferences.setHasSeenGIFMetaDataWarning() + preferenceStorage[PrivacyPreferences.HAS_SEEN_GIF_METADATA_WARNING] = true selectGif() } cancelButton() @@ -3024,7 +3029,7 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate, // Before saving an attachment, regardless of Android API version or permissions, we always want to ensure // that we've warned the user just _once_ that any attachments they save can be accessed by other apps. - val haveWarned = TextSecurePreferences.getHaveWarnedUserAboutSavingAttachments(this) + val haveWarned = preferenceStorage[PrivacyPreferences.HAVE_WARNED_USER_ABOUT_SAVING_ATTACHMENTS] if (haveWarned) { // On Android versions below 29 we require the WRITE_EXTERNAL_STORAGE permission to save attachments. if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt index 52e14b8220..8f6cea3fc9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt @@ -21,6 +21,8 @@ import network.loki.messenger.R import network.loki.messenger.databinding.ViewInputBarBinding import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.PrivacyPreferences import org.session.libsession.utilities.getColorFromAttr import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.InputbarViewModel @@ -98,6 +100,9 @@ class InputBar @JvmOverloads constructor( @Inject lateinit var recipientRepository: RecipientRepository + @Inject + lateinit var preferenceStorage: PreferenceStorage + private val attachmentsButton = InputBarButton(context, R.drawable.ic_plus).apply { contentDescription = context.getString(R.string.AccessibilityId_attachmentsButton) } @@ -145,7 +150,7 @@ class InputBar @JvmOverloads constructor( // Prevent some IMEs from switching to fullscreen/extracted text mode in landscape (shows IME-owned text field). binding.inputBarEditText.imeOptions = EditorInfo.IME_ACTION_NONE or EditorInfo.IME_FLAG_NO_EXTRACT_UI - val incognitoFlag = if (TextSecurePreferences.isIncognitoKeyboardEnabled(context)) 16777216 else 0 + val incognitoFlag = if (preferenceStorage[PrivacyPreferences.INCOGNITO_KEYBOARD]) 16777216 else 0 binding.inputBarEditText.imeOptions = binding.inputBarEditText.imeOptions or incognitoFlag // Always use incognito keyboard if setting enabled binding.inputBarEditText.delegate = this diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/ControlMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/ControlMessageView.kt index 4cc0276c5e..b07d8b82ee 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/ControlMessageView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/ControlMessageView.kt @@ -24,7 +24,8 @@ import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY import org.session.libsession.utilities.StringSubstitutionConstants.NAME_KEY import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsession.utilities.TextSecurePreferences.Companion.CALL_NOTIFICATIONS_ENABLED +import org.thoughtcrime.securesms.preferences.NotificationPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.session.libsession.utilities.ThemeUtil import org.session.libsession.utilities.getColorFromAttr import org.session.libsession.utilities.isGroup @@ -78,6 +79,7 @@ class ControlMessageView : LinearLayout { @Inject lateinit var loginStateRepository: LoginStateRepository @Inject lateinit var threadDatabase: ThreadDatabase @Inject lateinit var messageFormatter: MessageFormatter + @Inject lateinit var preferenceStorage: PreferenceStorage val controlContentView: View get() = binding.controlContentView @@ -188,7 +190,7 @@ class ControlMessageView : LinearLayout { when { // when the call toggle is disabled in the privacy screen, // show a dedicated privacy dialog - !TextSecurePreferences.isCallNotificationsEnabled(context) -> { + !preferenceStorage[NotificationPreferences.CALL_NOTIFICATIONS_ENABLED] -> { showInfo() binding.controlContentView.setOnClickListener { context.showSessionDialog { @@ -207,7 +209,7 @@ class ControlMessageView : LinearLayout { button(R.string.sessionSettings) { val intent = Intent(context, PrivacySettingsActivity::class.java) // allow the screen to auto scroll to the appropriate toggle - intent.putExtra(PrivacySettingsActivity.SCROLL_AND_TOGGLE_KEY, CALL_NOTIFICATIONS_ENABLED) + intent.putExtra(PrivacySettingsActivity.SCROLL_AND_TOGGLE_KEY, NotificationPreferences.CALL_NOTIFICATIONS_ENABLED.name) context.startActivity(intent) } cancelButton() diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt index 3c79d3713b..becbb9f162 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt @@ -34,7 +34,8 @@ import org.session.libsession.messaging.sending_receiving.link_preview.LinkPrevi import org.session.libsession.network.SnodeClock import org.session.libsession.utilities.Address.Companion.fromSerialized import org.session.libsession.utilities.Address.Companion.toAddress -import org.session.libsession.utilities.TextSecurePreferences.Companion.isReadReceiptsEnabled +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.PrivacyPreferences import org.session.libsession.utilities.isGroupOrCommunity import org.session.libsession.utilities.recipients.Recipient import org.session.libsession.utilities.toGroupString @@ -74,7 +75,8 @@ class MmsDatabase @Inject constructor( private val reactionDatabase: ReactionDatabase, private val mmsSmsDatabase: Lazy, private val groupDatabase: GroupDatabase, - private val snodeClock: SnodeClock + private val snodeClock: SnodeClock, + private val preferenceStorage: PreferenceStorage ) : MessagingDatabase(context, databaseHelper) { private val earlyDeliveryReceiptCache = EarlyReceiptCache() private val earlyReadReceiptCache = EarlyReceiptCache() @@ -992,7 +994,7 @@ class MmsDatabase @Inject constructor( cursor.getLong(cursor.getColumnIndexOrThrow(PRO_PROFILE_FEATURES)).toProProfileFeatures(this) } - if (!isReadReceiptsEnabled(context)) { + if (!preferenceStorage[PrivacyPreferences.READ_RECEIPTS]) { readReceiptCount = 0 } val recipient = getRecipientFor(address) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientRepository.kt index f009075a38..f63b22c4f6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientRepository.kt @@ -58,6 +58,8 @@ import org.thoughtcrime.securesms.database.model.NotifyType import org.thoughtcrime.securesms.database.model.RecipientSettings import org.thoughtcrime.securesms.dependencies.ManagerScope import org.thoughtcrime.securesms.groups.GroupMemberComparator +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences import org.thoughtcrime.securesms.pro.ProDataState import org.thoughtcrime.securesms.pro.ProStatus import org.thoughtcrime.securesms.pro.ProStatusManager @@ -92,6 +94,7 @@ class RecipientRepository @Inject constructor( private val proDatabase: ProDatabase, private val snodeClock: Lazy, private val proStatusManager: Lazy, + private val preferenceStorage: PreferenceStorage ) { private val recipientFlowCache = LruCache>>(512) @@ -506,12 +509,12 @@ class RecipientRepository @Inject constructor( } // 3. Apply Debug Overrides - if (recipient.isSelf && proData == null && prefs.forceCurrentUserAsPro()) { + if (recipient.isSelf && proData == null && preferenceStorage[ProPreferences.FORCE_CURRENT_USER_AS_PRO]) { proData = RecipientData.ProData(showProBadge = true) } else if (!recipient.isSelf && (recipient.address is Address.Standard) && proData == null - && prefs.forceOtherUsersAsPro() + && preferenceStorage[ProPreferences.FORCE_OTHER_USERS_PRO] ) { proData = RecipientData.ProData(showProBadge = true) } @@ -660,7 +663,7 @@ class RecipientRepository @Inject constructor( configFactory.withUserConfigs { configs -> val pro = configs.userProfile.getProConfig() - if (prefs.forceCurrentUserAsPro()) { + if (preferenceStorage[ProPreferences.FORCE_CURRENT_USER_AS_PRO]) { proDataContext?.addProData( RecipientSettings.ProData( showProBadge = configs.userProfile.getProFeatures().contains( diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 9ec1ee556c..eafc60e8af 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -37,6 +37,8 @@ import org.session.libsession.network.SnodeClock; import org.session.libsession.utilities.Address; import org.session.libsession.utilities.TextSecurePreferences; +import org.thoughtcrime.securesms.preferences.PreferenceStorage; +import org.thoughtcrime.securesms.preferences.PrivacyPreferences; import org.session.libsession.utilities.recipients.Recipient; import org.session.libsignal.utilities.Log; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; @@ -142,6 +144,7 @@ public static void addProFeatureColumns(SupportSQLiteDatabase db) { private final SnodeClock snodeClock; private final Lazy<@NonNull ThreadDatabase> threadDatabase; private final Lazy<@NonNull ReactionDatabase> reactionDatabase; + private final PreferenceStorage preferenceStorage; @Inject public SmsDatabase(@ApplicationContext Context context, @@ -149,12 +152,14 @@ public SmsDatabase(@ApplicationContext Context context, RecipientRepository recipientRepository, SnodeClock snodeClock, Lazy<@NonNull ThreadDatabase> threadDatabase, - Lazy<@NonNull ReactionDatabase> reactionDatabase) { + Lazy<@NonNull ReactionDatabase> reactionDatabase, + PreferenceStorage preferenceStorage) { super(context, databaseHelper); this.recipientRepository = recipientRepository; this.snodeClock = snodeClock; this.threadDatabase = threadDatabase; this.reactionDatabase = reactionDatabase; + this.preferenceStorage = preferenceStorage; } protected String getTableName() { @@ -747,7 +752,7 @@ public SmsMessageRecord getCurrent() { ProFeatureExtKt.toProMessageFeatures(cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.PRO_MESSAGE_FEATURES)), proFeatures); ProFeatureExtKt.toProProfileFeatures(cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.PRO_PROFILE_FEATURES)), proFeatures); - if (!TextSecurePreferences.isReadReceiptsEnabled(context)) { + if (!preferenceStorage.get(PrivacyPreferences.INSTANCE.getREAD_RECEIPTS())) { readReceiptCount = 0; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java index 0dc4ca500d..c6eb89452f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -38,6 +38,8 @@ import org.session.libsession.utilities.ConfigFactoryProtocolKt; import org.session.libsession.utilities.GroupUtil; import org.session.libsession.utilities.TextSecurePreferences; +import org.thoughtcrime.securesms.preferences.PreferenceStorage; +import org.thoughtcrime.securesms.preferences.PrivacyPreferences; import org.session.libsession.utilities.Util; import org.session.libsession.utilities.recipients.Recipient; import org.session.libsignal.utilities.AccountId; @@ -233,6 +235,7 @@ public static void migrateLegacyCommunityAddresses(final SQLiteDatabase db) { private final Json json; private final TextSecurePreferences prefs; private final SnodeClock snodeClock; + private final PreferenceStorage preferenceStorage; private final Lazy<@NonNull RecipientRepository> recipientRepository; private final Lazy<@NonNull MmsSmsDatabase> mmsSmsDatabase; @@ -254,7 +257,8 @@ public ThreadDatabase(@dagger.hilt.android.qualifiers.ApplicationContext Context Lazy<@NonNull MarkReadProcessor> markReadProcessor, TextSecurePreferences prefs, SnodeClock snodeClock, - Json json) { + Json json, + PreferenceStorage preferenceStorage) { super(context, databaseHelper); this.recipientRepository = recipientRepository; this.mmsSmsDatabase = mmsSmsDatabase; @@ -264,6 +268,7 @@ public ThreadDatabase(@dagger.hilt.android.qualifiers.ApplicationContext Context this.smsDatabase = smsDatabase; this.markReadProcessor = markReadProcessor; this.snodeClock = snodeClock; + this.preferenceStorage = preferenceStorage; this.json = json; this.prefs = prefs; @@ -840,7 +845,7 @@ public ThreadRecord getCurrent() { String invitingAdmin = cursor.getString(cursor.getColumnIndexOrThrow(LokiMessageDatabase.invitingSessionId)); String messageContentJson = cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_CONTENT)); - if (!TextSecurePreferences.isReadReceiptsEnabled(context)) { + if (!preferenceStorage.get(PrivacyPreferences.INSTANCE.getREAD_RECEIPTS())) { readReceiptCount = 0; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/debugmenu/DebugMenuViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/debugmenu/DebugMenuViewModel.kt index cbf062a599..0c8e23c020 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/debugmenu/DebugMenuViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/debugmenu/DebugMenuViewModel.kt @@ -44,6 +44,10 @@ import org.session.libsignal.utilities.AccountId import org.session.libsignal.utilities.IdPrefix import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.auth.LoginStateRepository +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences +import org.thoughtcrime.securesms.preferences.SystemPreferences import org.thoughtcrime.securesms.database.AttachmentDatabase import org.thoughtcrime.securesms.database.RecipientSettingsDatabase import org.thoughtcrime.securesms.database.model.ThreadRecord @@ -75,6 +79,7 @@ class DebugMenuViewModel @AssistedInject constructor( private val debugLogger: DebugLogger, private val dateUtils: DateUtils, private val loginStateRepository: LoginStateRepository, + private val preferenceStorage: PreferenceStorage, subscriptionManagers: Set<@JvmSuppressWildcards SubscriptionManager>, ) : ViewModel() { private val TAG = "DebugMenu" @@ -92,19 +97,19 @@ class DebugMenuViewModel @AssistedInject constructor( showEnvironmentWarningDialog = false, showLoadingDialog = false, showDeprecatedStateWarningDialog = false, - hideMessageRequests = textSecurePreferences.hasHiddenMessageRequests(), + hideMessageRequests = preferenceStorage[MessagingPreferences.HAS_HIDDEN_MESSAGE_REQUESTS], hideNoteToSelf = configFactory.withUserConfigs { it.userProfile.getNtsPriority() == PRIORITY_HIDDEN }, forceDeprecationState = deprecationManager.deprecationStateOverride.value, - forceDeterministicEncryption = textSecurePreferences.forcesDeterministicAttachmentEncryption, + forceDeterministicEncryption = preferenceStorage[MessagingPreferences.FORCES_DETERMINISTIC_ATTACHMENT_ENCRYPTION], availableDeprecationState = listOf(null) + LegacyGroupDeprecationManager.DeprecationState.entries.toList(), deprecatedTime = deprecationManager.deprecatedTime.value, deprecatingStartTime = deprecationManager.deprecatingStartTime.value, - forceCurrentUserAsPro = textSecurePreferences.forceCurrentUserAsPro(), - forceOtherUsersAsPro = textSecurePreferences.forceOtherUsersAsPro(), - forceIncomingMessagesAsPro = textSecurePreferences.forceIncomingMessagesAsPro(), - forcePostPro = textSecurePreferences.forcePostPro(), - forceShortTTl = textSecurePreferences.forcedShortTTL(), - debugAvatarReupload = textSecurePreferences.debugAvatarReupload, + forceCurrentUserAsPro = preferenceStorage[ProPreferences.FORCE_CURRENT_USER_AS_PRO], + forceOtherUsersAsPro = preferenceStorage[ProPreferences.FORCE_OTHER_USERS_PRO], + forceIncomingMessagesAsPro = preferenceStorage[ProPreferences.FORCE_INCOMING_MESSAGES_AS_PRO], + forcePostPro = preferenceStorage[ProPreferences.FORCE_POST_PRO], + forceShortTTl = preferenceStorage[MessagingPreferences.FORCED_SHORT_TTL], + debugAvatarReupload = preferenceStorage[MessagingPreferences.DEBUG_AVATAR_REUPLOAD], messageProFeature = textSecurePreferences.getDebugMessageFeatures(), dbInspectorState = DatabaseInspectorState.NOT_AVAILABLE, debugSubscriptionStatuses = setOf( @@ -118,30 +123,30 @@ class DebugMenuViewModel @AssistedInject constructor( DebugSubscriptionStatus.EXPIRED_APPLE, DebugSubscriptionStatus.AUTO_APPLE_REFUNDING, ), - selectedDebugSubscriptionStatus = textSecurePreferences.getDebugSubscriptionType() ?: DebugSubscriptionStatus.AUTO_GOOGLE, + selectedDebugSubscriptionStatus = preferenceStorage[ProPreferences.DEBUG_SUBSCRIPTION_STATUS] ?: DebugSubscriptionStatus.AUTO_GOOGLE, debugProPlanStatus = setOf( DebugProPlanStatus.NORMAL, DebugProPlanStatus.LOADING, DebugProPlanStatus.ERROR, ), - selectedDebugProPlanStatus = textSecurePreferences.getDebugProPlanStatus() ?: DebugProPlanStatus.NORMAL, + selectedDebugProPlanStatus = preferenceStorage[ProPreferences.DEBUG_PRO_PLAN_STATUS] ?: DebugProPlanStatus.NORMAL, debugProPlans = subscriptionManagers.asSequence() .flatMap { it.availablePlans.asSequence().map { plan -> DebugProPlan(it, plan) } } .toList(), - forceNoBilling = textSecurePreferences.getDebugForceNoBilling(), - withinQuickRefund = textSecurePreferences.getDebugIsWithinQuickRefund(), + forceNoBilling = preferenceStorage[ProPreferences.DEBUG_FORCE_NO_BILLING], + withinQuickRefund = preferenceStorage[ProPreferences.DEBUG_IS_WITHIN_QUICK_REFUND], availableAltFileServers = TEST_FILE_SERVERS, - alternativeFileServer = textSecurePreferences.alternativeFileServer, + alternativeFileServer = preferenceStorage[MessagingPreferences.ALTERNATIVE_FILE_SERVER], showToastForGroups = getDebugGroupToastPref(), firstInstall = dateUtils.getLocaleFormattedDate( context.packageManager.getPackageInfo(context.packageName, 0).firstInstallTime ), - hasDonated = textSecurePreferences.hasDonated(), - hasCopiedDonationURL = textSecurePreferences.hasCopiedDonationURL(), - seenDonateCTAAmount = textSecurePreferences.seenDonationCTAAmount(), - lastSeenDonateCTA = if(textSecurePreferences.lastSeenDonationCTA() == 0L ) "Never" - else dateUtils.getLocaleFormattedDate(textSecurePreferences.lastSeenDonationCTA()), - showDonateCTAFromPositiveReview = textSecurePreferences.showDonationCTAFromPositiveReview(), + hasDonated = preferenceStorage[SystemPreferences.HAS_DONATED], + hasCopiedDonationURL = preferenceStorage[SystemPreferences.HAS_COPIED_DONATION_URL], + seenDonateCTAAmount = preferenceStorage[SystemPreferences.SEEN_DONATION_CTA_AMOUNT], + lastSeenDonateCTA = if(preferenceStorage[SystemPreferences.LAST_SEEN_DONATION_CTA] == 0L ) "Never" + else dateUtils.getLocaleFormattedDate(preferenceStorage[SystemPreferences.LAST_SEEN_DONATION_CTA]), + showDonateCTAFromPositiveReview = preferenceStorage[SystemPreferences.SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW], hasDonatedDebug = textSecurePreferences.hasDonatedDebug() ?: NOT_SET, hasCopiedDonationURLDebug = textSecurePreferences.hasCopiedDonationURLDebug() ?: NOT_SET, seenDonateCTAAmountDebug = textSecurePreferences.seenDonationCTAAmountDebug() ?: NOT_SET, @@ -235,7 +240,7 @@ class DebugMenuViewModel @AssistedInject constructor( } is Commands.HideMessageRequest -> { - textSecurePreferences.setHasHiddenMessageRequests(command.hide) + preferenceStorage[MessagingPreferences.HAS_HIDDEN_MESSAGE_REQUESTS] = command.hide _uiState.value = _uiState.value.copy(hideMessageRequests = command.hide) } @@ -309,49 +314,49 @@ class DebugMenuViewModel @AssistedInject constructor( } is Commands.ForceCurrentUserAsPro -> { - textSecurePreferences.setForceCurrentUserAsPro(command.set) + preferenceStorage[ProPreferences.FORCE_CURRENT_USER_AS_PRO] = command.set _uiState.update { it.copy(forceCurrentUserAsPro = command.set) } } is Commands.ForceOtherUsersAsPro -> { - textSecurePreferences.setForceOtherUsersAsPro(command.set) + preferenceStorage[ProPreferences.FORCE_OTHER_USERS_PRO] = command.set _uiState.update { it.copy(forceOtherUsersAsPro = command.set) } } is Commands.ForceIncomingMessagesAsPro -> { - textSecurePreferences.setForceIncomingMessagesAsPro(command.set) + preferenceStorage[ProPreferences.FORCE_INCOMING_MESSAGES_AS_PRO] = command.set _uiState.update { it.copy(forceIncomingMessagesAsPro = command.set) } } is Commands.ForceNoBilling -> { - textSecurePreferences.setDebugForceNoBilling(command.set) + preferenceStorage[ProPreferences.DEBUG_FORCE_NO_BILLING] = command.set _uiState.update { it.copy(forceNoBilling = command.set) } } is Commands.WithinQuickRefund -> { - textSecurePreferences.setDebugIsWithinQuickRefund(command.set) + preferenceStorage[ProPreferences.DEBUG_IS_WITHIN_QUICK_REFUND] = command.set _uiState.update { it.copy(withinQuickRefund = command.set) } } is Commands.ForcePostPro -> { - textSecurePreferences.setForcePostPro(command.set) + preferenceStorage[ProPreferences.FORCE_POST_PRO] = command.set _uiState.update { it.copy(forcePostPro = command.set) } } is Commands.ForceShortTTl -> { - textSecurePreferences.setForcedShortTTL(command.set) + preferenceStorage[MessagingPreferences.FORCED_SHORT_TTL] = command.set _uiState.update { it.copy(forceShortTTl = command.set) } @@ -377,14 +382,14 @@ class DebugMenuViewModel @AssistedInject constructor( } is Commands.SetDebugSubscriptionStatus -> { - textSecurePreferences.setDebugSubscriptionType(command.status) + preferenceStorage[ProPreferences.DEBUG_SUBSCRIPTION_STATUS] = command.status _uiState.update { it.copy(selectedDebugSubscriptionStatus = command.status) } } is Commands.SetDebugProPlanStatus -> { - textSecurePreferences.setDebugProPlanStatus(command.status) + preferenceStorage[ProPreferences.DEBUG_PRO_PLAN_STATUS] = command.status _uiState.update { it.copy(selectedDebugProPlanStatus = command.status) } @@ -399,13 +404,13 @@ class DebugMenuViewModel @AssistedInject constructor( is Commands.ToggleDeterministicEncryption -> { val newValue = !_uiState.value.forceDeterministicEncryption _uiState.update { it.copy(forceDeterministicEncryption = newValue) } - textSecurePreferences.forcesDeterministicAttachmentEncryption = newValue + preferenceStorage[MessagingPreferences.FORCES_DETERMINISTIC_ATTACHMENT_ENCRYPTION] = newValue } is Commands.ToggleDebugAvatarReupload -> { val newValue = !_uiState.value.debugAvatarReupload _uiState.update { it.copy(debugAvatarReupload = newValue) } - textSecurePreferences.debugAvatarReupload = newValue + preferenceStorage[MessagingPreferences.DEBUG_AVATAR_REUPLOAD] = newValue } is Commands.ResetPushToken -> { @@ -416,7 +421,7 @@ class DebugMenuViewModel @AssistedInject constructor( is Commands.SelectAltFileServer -> { _uiState.update { it.copy(alternativeFileServer = command.fileServer) } - textSecurePreferences.alternativeFileServer = command.fileServer + preferenceStorage[MessagingPreferences.ALTERNATIVE_FILE_SERVER] = command.fileServer } is Commands.NavigateTo -> { diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/AppModule.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/AppModule.kt index 13591b71ee..0a0dcaacb5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/AppModule.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/AppModule.kt @@ -19,6 +19,7 @@ import org.session.libsession.utilities.AppTextSecurePreferences import org.session.libsession.utilities.ConfigFactoryProtocol import org.session.libsession.utilities.SSKEnvironment import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.thoughtcrime.securesms.groups.GroupManagerV2Impl import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier import org.thoughtcrime.securesms.repository.ConversationRepository @@ -88,6 +89,6 @@ class ToasterModule { @EntryPoint @InstallIn(SingletonComponent::class) interface AppComponent { - fun getPrefs(): TextSecurePreferences - + fun getPreferenceStorage(): PreferenceStorage + fun getNotificationChannels(): org.thoughtcrime.securesms.notifications.NotificationChannels } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/disguise/AppDisguiseManager.kt b/app/src/main/java/org/thoughtcrime/securesms/disguise/AppDisguiseManager.kt index 0b94e7a268..2fb35d6f48 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/disguise/AppDisguiseManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/disguise/AppDisguiseManager.kt @@ -27,6 +27,8 @@ import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.dependencies.ManagerScope import org.thoughtcrime.securesms.dependencies.OnAppStartupComponent +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ThemingPreferences import org.thoughtcrime.securesms.util.CurrentActivityObserver import javax.inject.Inject import javax.inject.Singleton @@ -38,7 +40,8 @@ import javax.inject.Singleton @Singleton class AppDisguiseManager @Inject constructor( application: Application, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val currentActivityObserver: CurrentActivityObserver, @param:ManagerScope private val scope: CoroutineScope, ) : OnAppStartupComponent { @@ -80,11 +83,11 @@ class AppDisguiseManager @Inject constructor( * The currently selected app alias name. This doesn't equate to if the app disguise is on or off. */ val selectedAppAliasName: StateFlow = prefChangeNotification - .mapLatest { prefs.selectedActivityAliasName } + .mapLatest { preferenceStorage[ThemingPreferences.SELECTED_ACTIVITY_ALIAS_NAME] } .stateIn( scope = scope, started = SharingStarted.Eagerly, - initialValue = prefs.selectedActivityAliasName + initialValue = preferenceStorage[ThemingPreferences.SELECTED_ACTIVITY_ALIAS_NAME] ) init { @@ -150,7 +153,7 @@ class AppDisguiseManager @Inject constructor( fun setSelectedAliasName(name: String?) { Log.d(TAG, "setSelectedAliasName: $name") - prefs.selectedActivityAliasName = name + preferenceStorage[ThemingPreferences.SELECTED_ACTIVITY_ALIAS_NAME] = name prefChangeNotification.tryEmit(Unit) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/giph/ui/GiphyActivityToolbarTextSecurePreferencesPersistence.java b/app/src/main/java/org/thoughtcrime/securesms/giph/ui/GiphyActivityToolbarTextSecurePreferencesPersistence.java index 3147590d6a..f91109540f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/giph/ui/GiphyActivityToolbarTextSecurePreferencesPersistence.java +++ b/app/src/main/java/org/thoughtcrime/securesms/giph/ui/GiphyActivityToolbarTextSecurePreferencesPersistence.java @@ -2,7 +2,10 @@ import android.content.Context; -import org.session.libsession.utilities.TextSecurePreferences; +import org.thoughtcrime.securesms.dependencies.AppComponent; +import dagger.hilt.EntryPoints; +import org.thoughtcrime.securesms.preferences.MessagingPreferences; +import org.thoughtcrime.securesms.preferences.PreferenceStorage; class GiphyActivityToolbarTextSecurePreferencesPersistence implements GiphyActivityToolbar.Persistence { @@ -10,19 +13,19 @@ static GiphyActivityToolbar.Persistence fromContext(Context context) { return new GiphyActivityToolbarTextSecurePreferencesPersistence(context.getApplicationContext()); } - private final Context context; + private final PreferenceStorage preferenceStorage; private GiphyActivityToolbarTextSecurePreferencesPersistence(Context context) { - this.context = context; + this.preferenceStorage = EntryPoints.get(context, AppComponent.class).getPreferenceStorage(); } @Override public boolean getGridSelected() { - return TextSecurePreferences.isGifSearchInGridLayout(context); + return preferenceStorage.get(MessagingPreferences.INSTANCE.getGIF_SEARCH_IN_GRID_LAYOUT()); } @Override public void setGridSelected(boolean isGridSelected) { - TextSecurePreferences.setIsGifSearchInGridLayout(context, isGridSelected); + preferenceStorage.set(MessagingPreferences.INSTANCE.getGIF_SEARCH_IN_GRID_LAYOUT(), isGridSelected); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/giph/ui/GiphyFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/giph/ui/GiphyFragment.kt index 03789b89e7..b2bd3c7ecc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/giph/ui/GiphyFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/giph/ui/GiphyFragment.kt @@ -19,7 +19,8 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import network.loki.messenger.R -import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.session.libsession.utilities.ViewUtil import org.thoughtcrime.securesms.giph.model.GiphyImage import org.thoughtcrime.securesms.giph.net.GiphyLoader @@ -28,15 +29,20 @@ import org.thoughtcrime.securesms.giph.ui.compose.bindGiphyOverlay import org.thoughtcrime.securesms.giph.util.InfiniteScrollListener import java.util.LinkedList import java.util.List +import javax.inject.Inject +import dagger.hilt.android.AndroidEntryPoint /** * Base fragment for both GIF and Sticker tabs. * Subclasses (Gif/Sticker) only implement onCreateLoader(...). */ +@AndroidEntryPoint abstract class GiphyFragment : Fragment(), LoaderManager.LoaderCallbacks> { + @Inject lateinit var preferenceStorage: PreferenceStorage + private lateinit var giphyAdapter: GiphyAdapter private lateinit var recyclerView: RecyclerView private lateinit var overlayView: ComposeView @@ -69,7 +75,7 @@ abstract class GiphyFragment : setLayoutManager(it) pendingGridLayout = null } ?: run { - setLayoutManager(TextSecurePreferences.isGifSearchInGridLayout(requireContext())) + setLayoutManager(preferenceStorage[MessagingPreferences.GIF_SEARCH_IN_GRID_LAYOUT]) } overlayState.value = GiphyOverlayState.Loading diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 088ac79634..c61afde7ac 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -91,7 +91,10 @@ import org.thoughtcrime.securesms.home.search.SearchContactActionBottomSheet import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity import org.thoughtcrime.securesms.onboarding.OnBoardingPreferences.HAS_VIEWED_SEED import org.thoughtcrime.securesms.permissions.Permissions +import org.thoughtcrime.securesms.preferences.MessagingPreferences import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SecurityPreferences +import org.thoughtcrime.securesms.preferences.SystemPreferences import org.thoughtcrime.securesms.preferences.SettingsActivity import org.thoughtcrime.securesms.preferences.prosettings.ProSettingsActivity import org.thoughtcrime.securesms.pro.ProStatusManager @@ -341,7 +344,7 @@ class HomeActivity : ScreenLockActionBarActivity(), binding.globalSearchRecycler.adapter = globalSearchAdapter binding.configOutdatedView.setOnClickListener { - textSecurePreferences.setHasLegacyConfig(false) + preferenceStorage[SystemPreferences.HAS_RECEIVED_LEGACY_CONFIG] = false updateLegacyConfigView() } @@ -639,7 +642,7 @@ class HomeActivity : ScreenLockActionBarActivity(), } private fun updateLegacyConfigView() { - binding.configOutdatedView.isVisible = textSecurePreferences.getHasLegacyConfig() + binding.configOutdatedView.isVisible = preferenceStorage[SystemPreferences.HAS_RECEIVED_LEGACY_CONFIG] } override fun onResume() { @@ -1005,7 +1008,7 @@ class HomeActivity : ScreenLockActionBarActivity(), showSessionDialog { text(getString(R.string.hide)) button(R.string.yes) { - textSecurePreferences.setHasHiddenMessageRequests(true) + preferenceStorage[MessagingPreferences.HAS_HIDDEN_MESSAGE_REQUESTS] = true homeViewModel.tryReload() } button(R.string.no) diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt index b4a1281707..1db5d129fd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt @@ -46,7 +46,11 @@ import org.thoughtcrime.securesms.database.model.ThreadRecord import org.thoughtcrime.securesms.debugmenu.DebugLogGroup import org.thoughtcrime.securesms.dependencies.ConfigFactory import org.thoughtcrime.securesms.onboarding.OnBoardingPreferences.HAS_VIEWED_SEED +import org.thoughtcrime.securesms.preferences.MessagingPreferences import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences +import org.thoughtcrime.securesms.preferences.PushPreferences +import org.thoughtcrime.securesms.preferences.SystemPreferences import org.thoughtcrime.securesms.preferences.prosettings.ProSettingsDestination import org.thoughtcrime.securesms.pro.ProStatus import org.thoughtcrime.securesms.pro.ProStatusManager @@ -143,9 +147,10 @@ class HomeViewModel @Inject constructor( observeTypingStatus(), // Third flow: whether the user has marked message requests as hidden - (TextSecurePreferences.events.filter { it == TextSecurePreferences.HAS_HIDDEN_MESSAGE_REQUESTS } as Flow<*>) - .onStart { emit(Unit) } - .map { prefs.hasHiddenMessageRequests() } + prefStorage.changes() + .filter { it.name == MessagingPreferences.HAS_HIDDEN_MESSAGE_REQUESTS.name } + .onStart { emit(MessagingPreferences.HAS_HIDDEN_MESSAGE_REQUESTS) } + .map { prefStorage[MessagingPreferences.HAS_HIDDEN_MESSAGE_REQUESTS] } ) { (unapproveConvoCount, convoList), typingStatus, hiddenMessageRequest -> // check if we should show the recovery phrase backup banner: // - if the user has not yet seen the warning @@ -183,11 +188,11 @@ class HomeViewModel @Inject constructor( init { // check for white list status in case of slow mode - if(!prefs.hasCheckedDozeWhitelist() // the user has not yet seen the dialog - && !prefs.pushEnabled.value // the user is in slow mode + if(!prefStorage[SystemPreferences.HAS_CHECKED_DOZE_WHITELIST] // the user has not yet seen the dialog + && !prefStorage[PushPreferences.isPushEnabled(TextSecurePreferences.pushSuffix)] // the user is in slow mode && !context.isWhitelistedFromDoze() // the user isn't yet whitelisted ){ - prefs.setHasCheckedDozeWhitelist(true) + prefStorage[SystemPreferences.HAS_CHECKED_DOZE_WHITELIST] = true viewModelScope.launch { delay(1500) _dialogsState.update { @@ -229,7 +234,7 @@ class HomeViewModel @Inject constructor( var showExpired: Boolean = false if(subscription.type is ProStatus.Active.Expiring - && !prefs.hasSeenProExpiring() + && !prefStorage[ProPreferences.HAS_SEEN_PRO_EXPIRING] ){ val validUntil = subscription.type.renewingAt showExpiring = validUntil.isBefore(now.plus(7, ChronoUnit.DAYS)) @@ -245,7 +250,7 @@ class HomeViewModel @Inject constructor( } } else if(subscription.type is ProStatus.Expired - && !prefs.hasSeenProExpired()) { + && !prefStorage[ProPreferences.HAS_SEEN_PRO_EXPIRED]) { val validUntil = subscription.type.expiredAt showExpired = now.isBefore(validUntil.plus(30, ChronoUnit.DAYS)) @@ -383,12 +388,12 @@ class HomeViewModel @Inject constructor( } is Commands.HideExpiringCTADialog -> { - prefs.setHasSeenProExpiring() + prefStorage[ProPreferences.HAS_SEEN_PRO_EXPIRING] = true _dialogsState.update { it.copy(proExpiringCTA = null) } } is Commands.HideExpiredCTADialog -> { - prefs.setHasSeenProExpired() + prefStorage[ProPreferences.HAS_SEEN_PRO_EXPIRED] = true _dialogsState.update { it.copy(proExpiredCTA = false) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/migration/DatabaseMigrationManager.kt b/app/src/main/java/org/thoughtcrime/securesms/migration/DatabaseMigrationManager.kt index c48df759ee..11e0fcf09b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migration/DatabaseMigrationManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/migration/DatabaseMigrationManager.kt @@ -16,6 +16,8 @@ import net.zetetic.database.sqlcipher.SQLiteDatabase import net.zetetic.database.sqlcipher.SQLiteDatabaseHook import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SystemPreferences import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper @@ -28,7 +30,8 @@ import javax.inject.Singleton @Singleton class DatabaseMigrationManager @Inject constructor( private val application: Application, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val databaseSecretProvider: DatabaseSecretProvider, jsonProvider: Provider, @param:ManagerScope private val scope: CoroutineScope, @@ -114,7 +117,7 @@ class DatabaseMigrationManager @Inject constructor( } private fun migrateCipherSettings(fromRetry: Boolean) { - if (prefs.migratedToDisablingKDF) { + if (preferenceStorage[SystemPreferences.MIGRATED_TO_DISABLING_KDF]) { Log.i(TAG, "Already migrated to latest cipher settings") return } @@ -152,7 +155,7 @@ class DatabaseMigrationManager @Inject constructor( } } ?: run { Log.i(TAG, "No database to migrate") - prefs.migratedToDisablingKDF = true + preferenceStorage[SystemPreferences.MIGRATED_TO_DISABLING_KDF] = true return } @@ -212,7 +215,7 @@ class DatabaseMigrationManager @Inject constructor( } check(newDb.exists()) { "New database was not created" } - prefs.migratedToDisablingKDF = true + preferenceStorage[SystemPreferences.MIGRATED_TO_DISABLING_KDF] = true } fun requestMigration(fromRetry: Boolean) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java index 4ad0f6189c..ed9a187ece 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java @@ -29,14 +29,16 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui protected Context context; protected NotificationPrivacyPreference privacy; protected final Bundle extras; + protected final NotificationChannels notificationChannels; - public AbstractNotificationBuilder(Context context, NotificationPrivacyPreference privacy) { + public AbstractNotificationBuilder(Context context, NotificationPrivacyPreference privacy, NotificationChannels notificationChannels) { super(context); extras = new Bundle(); this.context = context; this.privacy = privacy; + this.notificationChannels = notificationChannels; - setChannelId(NotificationChannels.getMessagesChannel(context)); + setChannelId(notificationChannels.getMessagesChannel()); setLed(); } @@ -50,8 +52,8 @@ protected CharSequence getStyledMessage(@NonNull Recipient recipient, @Nullable } public void setAlarms(@Nullable Uri ringtone) { - Uri defaultRingtone = NotificationChannels.getMessageRingtone(context); - boolean defaultVibrate = NotificationChannels.getMessageVibrate(context); + Uri defaultRingtone = notificationChannels.getMessageRingtone(); + boolean defaultVibrate = notificationChannels.getMessageVibrate(); if (ringtone == null && !TextUtils.isEmpty(defaultRingtone.toString())) setSound(defaultRingtone); else if (ringtone != null && !ringtone.toString().isEmpty()) setSound(ringtone); diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.kt index 652c45371a..65075bf473 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.kt @@ -31,9 +31,10 @@ import org.session.libsession.messaging.sending_receiving.notifications.MessageN import org.session.libsession.utilities.Address.Companion.fromSerialized import org.session.libsession.utilities.ServiceUtil import org.session.libsession.utilities.StringSubstitutionConstants.EMOJI_KEY -import org.session.libsession.utilities.TextSecurePreferences.Companion.getNotificationPrivacy -import org.session.libsession.utilities.TextSecurePreferences.Companion.isNotificationsEnabled -import org.session.libsession.utilities.TextSecurePreferences.Companion.removeHasHiddenMessageRequests +import org.session.libsession.utilities.NotificationPrivacyPreference +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.NotificationPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.session.libsession.utilities.recipients.RecipientData import org.session.libsignal.utilities.AccountId import org.session.libsignal.utilities.IdPrefix @@ -76,6 +77,8 @@ class DefaultMessageNotifier @Inject constructor( private val imageLoader: Provider, private val loginStateRepository: LoginStateRepository, private val messageFormatter: Lazy, + private val preferenceStorage: PreferenceStorage, + private val notificationChannels: NotificationChannels, ) : MessageNotifier { override fun setVisibleThread(threadId: Long) { visibleThread = threadId @@ -147,7 +150,7 @@ class DefaultMessageNotifier @Inject constructor( } override fun updateNotification(context: Context) { - if (!isNotificationsEnabled(context)) { + if (!preferenceStorage[NotificationPreferences.NOTIFICATIONS_ENABLED]) { return } @@ -169,10 +172,10 @@ class DefaultMessageNotifier @Inject constructor( ) == 1 && !(recipient.approved || threadDatabase.getLastSeenAndHasSent(threadId).second()) ) { - removeHasHiddenMessageRequests(context) + preferenceStorage.remove(MessagingPreferences.HAS_HIDDEN_MESSAGE_REQUESTS) } - if (!isNotificationsEnabled(context) || + if (!preferenceStorage[NotificationPreferences.NOTIFICATIONS_ENABLED] || (recipient != null && recipient.isMuted()) ) { return @@ -333,9 +336,10 @@ class DefaultMessageNotifier @Inject constructor( val builder = SingleRecipientNotificationBuilder( context, - getNotificationPrivacy(context), + NotificationPrivacyPreference(preferenceStorage[NotificationPreferences.NOTIFICATION_PRIVACY]), avatarUtils, imageLoader, + notificationChannels ) builder.putStringExtra(CONTENT_SIGNATURE, contentSignature) @@ -423,7 +427,7 @@ class DefaultMessageNotifier @Inject constructor( } if (signal && contentChanged) { - builder.setAlarms(notificationState.getRingtone(context)) + builder.setAlarms(notificationState.getRingtone(notificationChannels)) builder.setTicker( notificationItem.individualRecipient, notificationItem.text @@ -479,7 +483,7 @@ class DefaultMessageNotifier @Inject constructor( return } - val builder = GroupSummaryNotificationBuilder(context, getNotificationPrivacy(context)) + val builder = GroupSummaryNotificationBuilder(context, NotificationPrivacyPreference(preferenceStorage[NotificationPreferences.NOTIFICATION_PRIVACY]), notificationChannels) builder.putStringExtra(CONTENT_SIGNATURE, contentSignature) builder.setMessageCount(notificationState.notificationCount, notificationState.threadCount) @@ -524,7 +528,7 @@ class DefaultMessageNotifier @Inject constructor( } if (signal) { - builder.setAlarms(notificationState.getRingtone(context)) + builder.setAlarms(notificationState.getRingtone(notificationChannels)) val text = notifications[0].text builder.setTicker( notifications[0].individualRecipient, diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/GroupSummaryNotificationBuilder.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/GroupSummaryNotificationBuilder.kt index 142b34b772..311eb59c8b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/GroupSummaryNotificationBuilder.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/GroupSummaryNotificationBuilder.kt @@ -19,7 +19,7 @@ import org.thoughtcrime.securesms.home.HomeActivity import org.thoughtcrime.securesms.ui.getSubbedString import java.util.LinkedList -class GroupSummaryNotificationBuilder(context: Context, privacy: NotificationPrivacyPreference?) : AbstractNotificationBuilder(context, privacy) { +class GroupSummaryNotificationBuilder(context: Context, privacy: NotificationPrivacyPreference?, notificationChannels: NotificationChannels) : AbstractNotificationBuilder(context, privacy, notificationChannels) { private val messageBodies: MutableList = LinkedList() init { diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/LocaleChangedReceiver.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/LocaleChangedReceiver.java index f23958cb69..3390dca2e7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/LocaleChangedReceiver.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/LocaleChangedReceiver.java @@ -4,10 +4,13 @@ import android.content.Context; import android.content.Intent; +import org.thoughtcrime.securesms.dependencies.AppComponent; +import dagger.hilt.EntryPoints; + public class LocaleChangedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - NotificationChannels.create(context); + EntryPoints.get(context.getApplicationContext(), AppComponent.class).getNotificationChannels().create(); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadProcessor.kt index 04bcd97df4..d0bb28eb2e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/MarkReadProcessor.kt @@ -11,7 +11,8 @@ import org.session.libsession.database.userAuth import org.session.libsession.messaging.messages.control.ReadReceipt import org.session.libsession.messaging.sending_receiving.MessageSender import org.session.libsession.network.SnodeClock -import org.session.libsession.utilities.TextSecurePreferences.Companion.isReadReceiptsEnabled +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.PrivacyPreferences import org.session.libsession.utilities.associateByNotNull import org.session.libsession.utilities.isGroupOrCommunity import org.session.libsession.utilities.recipients.Recipient @@ -46,6 +47,7 @@ class MarkReadProcessor @Inject constructor( private val lokiMessageDatabase: LokiMessageDatabase, private val swarmApiExecutor: SwarmApiExecutor, private val alterTtyFactory: AlterTtlApi.Factory, + private val preferenceStorage: PreferenceStorage, @param:ManagerScope private val coroutineScope: CoroutineScope, ) { fun process( @@ -138,7 +140,7 @@ class MarkReadProcessor @Inject constructor( private fun sendReadReceipts( markedReadMessages: List ) { - if (!isReadReceiptsEnabled(context)) return + if (!preferenceStorage[PrivacyPreferences.READ_RECEIPTS]) return markedReadMessages.map { it.syncMessageId } .filter { recipientRepository.getRecipientSync(it.address).shouldSendReadReceipt } diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java index a4f1701874..5d3a444607 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java @@ -13,14 +13,20 @@ import org.session.libsession.utilities.Address; import org.session.libsession.utilities.ServiceUtil; -import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsignal.utilities.Log; +import org.thoughtcrime.securesms.preferences.NotificationPreferences; +import org.thoughtcrime.securesms.preferences.PreferenceStorage; import java.util.Arrays; +import javax.inject.Inject; +import javax.inject.Singleton; + +import dagger.hilt.android.qualifiers.ApplicationContext; import network.loki.messenger.BuildConfig; import network.loki.messenger.R; +@Singleton public class NotificationChannels { private static final String TAG = NotificationChannels.class.getSimpleName(); @@ -41,45 +47,54 @@ public class NotificationChannels { public static final String LOCKED_STATUS = "locked_status_v2"; public static final String OTHER = "other_v2"; + private final Context context; + private final PreferenceStorage preferenceStorage; + + @Inject + public NotificationChannels(@ApplicationContext Context context, PreferenceStorage preferenceStorage) { + this.context = context; + this.preferenceStorage = preferenceStorage; + } + /** * Ensures all of the notification channels are created. No harm in repeat calls. Call is safely * ignored for API < 26. */ - public static synchronized void create(@NonNull Context context) { + public synchronized void create() { NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); - int oldVersion = TextSecurePreferences.getNotificationChannelVersion(context); + int oldVersion = preferenceStorage.get(NotificationPreferences.CHANNEL_VERSION); if (oldVersion != VERSION) { onUpgrade(notificationManager, oldVersion, VERSION); - TextSecurePreferences.setNotificationChannelVersion(context, VERSION); + preferenceStorage.set(NotificationPreferences.CHANNEL_VERSION, VERSION); } - onCreate(context, notificationManager); + onCreate(notificationManager); } /** * @return The channel ID for the default messages channel. */ - public static synchronized @NonNull String getMessagesChannel(@NonNull Context context) { - return getMessagesChannelId(TextSecurePreferences.getNotificationMessagesChannelVersion(context)); + public synchronized @NonNull String getMessagesChannel() { + return getMessagesChannelId(preferenceStorage.get(NotificationPreferences.MESSAGES_CHANNEL_VERSION)); } /** * @return The message ringtone set for the default message channel. */ - public static synchronized @NonNull Uri getMessageRingtone(@NonNull Context context) { - Uri sound = ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).getSound(); + public synchronized @NonNull Uri getMessageRingtone() { + Uri sound = ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel()).getSound(); return sound == null ? Uri.EMPTY : sound; } /** * Update the message ringtone for the default message channel. */ - public static synchronized void updateMessageRingtone(@NonNull Context context, @Nullable Uri uri) { + public synchronized void updateMessageRingtone(@Nullable Uri uri) { Log.i(TAG, "Updating default message ringtone with URI: " + String.valueOf(uri)); - updateMessageChannel(context, channel -> { + updateMessageChannel(channel -> { channel.setSound(uri == null ? Settings.System.DEFAULT_NOTIFICATION_URI : uri, getRingtoneAudioAttributes()); }); } @@ -88,34 +103,35 @@ public static synchronized void updateMessageRingtone(@NonNull Context context, /** * @return The vibrate settings for the default message channel. */ - public static synchronized boolean getMessageVibrate(@NonNull Context context) { - return ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).shouldVibrate(); + public synchronized boolean getMessageVibrate() { + return ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel()).shouldVibrate(); } /** * Sets the vibrate property for the default message channel. */ - public static synchronized void updateMessageVibrate(@NonNull Context context, boolean enabled) { + public synchronized void updateMessageVibrate(boolean enabled) { Log.i(TAG, "Updating default vibrate with value: " + enabled); - updateMessageChannel(context, channel -> channel.enableVibration(enabled)); + updateMessageChannel(channel -> channel.enableVibration(enabled)); } - private static void onCreate(@NonNull Context context, @NonNull NotificationManager notificationManager) { + private void onCreate(@NonNull NotificationManager notificationManager) { NotificationChannelGroup messagesGroup = new NotificationChannelGroup(CATEGORY_MESSAGES, context.getResources().getString(R.string.messages)); notificationManager.createNotificationChannelGroup(messagesGroup); - NotificationChannel messages = new NotificationChannel(getMessagesChannel(context), context.getString(R.string.theDefault), NotificationManager.IMPORTANCE_HIGH); + NotificationChannel messages = new NotificationChannel(getMessagesChannel(), context.getString(R.string.theDefault), NotificationManager.IMPORTANCE_HIGH); NotificationChannel calls = new NotificationChannel(CALLS, context.getString(R.string.callsSettings), NotificationManager.IMPORTANCE_HIGH); NotificationChannel failures = new NotificationChannel(FAILURES, context.getString(R.string.failures), NotificationManager.IMPORTANCE_HIGH); NotificationChannel lockedStatus = new NotificationChannel(LOCKED_STATUS, context.getString(R.string.lockAppStatus), NotificationManager.IMPORTANCE_LOW); NotificationChannel other = new NotificationChannel(OTHER, context.getString(R.string.other), NotificationManager.IMPORTANCE_LOW); messages.setGroup(CATEGORY_MESSAGES); - messages.enableVibration(TextSecurePreferences.isNotificationVibrateEnabled(context)); - messages.setSound(TextSecurePreferences.getNotificationRingtone(context), getRingtoneAudioAttributes()); - setLedPreference(messages, TextSecurePreferences.getNotificationLedColor(context)); + + messages.enableVibration(preferenceStorage.get(NotificationPreferences.VIBRATE_ENABLED)); + messages.setSound(Uri.parse(preferenceStorage.get(NotificationPreferences.RINGTONE)), getRingtoneAudioAttributes()); + setLedPreference(messages, preferenceStorage.get(NotificationPreferences.LED_COLOR)); calls.setShowBadge(false); calls.setSound(null, null); @@ -132,7 +148,7 @@ private static void onCreate(@NonNull Context context, @NonNull NotificationMana } } - private static void onUpgrade(@NonNull NotificationManager notificationManager, int oldVersion, int newVersion) { + private void onUpgrade(@NonNull NotificationManager notificationManager, int oldVersion, int newVersion) { Log.i(TAG, "Upgrading channels from " + oldVersion + " to " + newVersion); if (oldVersion < VERSION_MESSAGES_CATEGORY) { @@ -146,7 +162,7 @@ private static void onUpgrade(@NonNull NotificationManager notificationManager, } } - private static void setLedPreference(@NonNull NotificationChannel channel, @NonNull Integer ledColor) { + private void setLedPreference(@NonNull NotificationChannel channel, @NonNull Integer ledColor) { if ("none".equals(ledColor)) { channel.enableLights(false); } else { @@ -156,11 +172,11 @@ private static void setLedPreference(@NonNull NotificationChannel channel, @NonN } - private static @NonNull String generateChannelIdFor(@NonNull Address address) { + private @NonNull String generateChannelIdFor(@NonNull Address address) { return CONTACT_PREFIX + address.toString() + "_" + System.currentTimeMillis(); } - private static @NonNull NotificationChannel copyChannel(@NonNull NotificationChannel original, @NonNull String id) { + private @NonNull NotificationChannel copyChannel(@NonNull NotificationChannel original, @NonNull String id) { NotificationChannel copy = new NotificationChannel(id, original.getName(), original.getImportance()); copy.setGroup(original.getGroup()); @@ -176,25 +192,25 @@ private static void setLedPreference(@NonNull NotificationChannel channel, @NonN return copy; } - private static String getMessagesChannelId(int version) { + private String getMessagesChannelId(int version) { return MESSAGES_PREFIX + version; } - private static void updateMessageChannel(@NonNull Context context, @NonNull ChannelUpdater updater) { + private void updateMessageChannel(@NonNull ChannelUpdater updater) { NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); - int existingVersion = TextSecurePreferences.getNotificationMessagesChannelVersion(context); + int existingVersion = preferenceStorage.get(NotificationPreferences.MESSAGES_CHANNEL_VERSION); int newVersion = existingVersion + 1; Log.i(TAG, "Updating message channel from version " + existingVersion + " to " + newVersion); if (updateExistingChannel(notificationManager, getMessagesChannelId(existingVersion), getMessagesChannelId(newVersion), updater)) { - TextSecurePreferences.setNotificationMessagesChannelVersion(context, newVersion); + preferenceStorage.set(NotificationPreferences.MESSAGES_CHANNEL_VERSION, newVersion); } else { - onCreate(context, notificationManager); + onCreate(notificationManager); } } - private static boolean updateExistingChannel(@NonNull NotificationManager notificationManager, + private boolean updateExistingChannel(@NonNull NotificationManager notificationManager, @NonNull String channelId, @NonNull String newChannelId, @NonNull ChannelUpdater updater) @@ -213,13 +229,13 @@ private static boolean updateExistingChannel(@NonNull NotificationManager notifi return true; } - private static AudioAttributes getRingtoneAudioAttributes() { + private AudioAttributes getRingtoneAudioAttributes() { return new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT) .build(); } - private static boolean channelExists(@Nullable NotificationChannel channel) { + private boolean channelExists(@Nullable NotificationChannel channel) { return channel != null && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationState.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationState.java index 301c04a5a5..406b3438a1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationState.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationState.java @@ -54,9 +54,9 @@ public void addNotification(@NonNull NotificationItem item) { notificationCount = notifications.size(); } - public @Nullable Uri getRingtone(@NonNull Context context) { + public @Nullable Uri getRingtone(@NonNull NotificationChannels notificationChannels) { if (!notifications.isEmpty()) { - return NotificationChannels.getMessageRingtone(context); + return notificationChannels.getMessageRingtone(); } return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistrationHandler.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistrationHandler.kt index 7fb8fb2d9d..8e7037e41f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistrationHandler.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistrationHandler.kt @@ -12,7 +12,8 @@ import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import org.session.libsession.messaging.notifications.TokenFetcher -import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.PushPreferences import org.session.libsession.utilities.UserConfigType import org.session.libsession.utilities.userConfigsChanged import org.session.libsession.utilities.withUserConfigs @@ -21,6 +22,7 @@ import org.thoughtcrime.securesms.auth.AuthAwareComponent import org.thoughtcrime.securesms.auth.LoggedInState import org.thoughtcrime.securesms.database.PushRegistrationDatabase import org.thoughtcrime.securesms.dependencies.ConfigFactory +import org.thoughtcrime.securesms.dependencies.ManagerScope import org.thoughtcrime.securesms.util.castAwayType import java.util.EnumSet import java.util.concurrent.atomic.AtomicBoolean @@ -34,12 +36,13 @@ import javax.inject.Singleton @Singleton class PushRegistrationHandler @Inject constructor( private val configFactory: ConfigFactory, - private val preferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val tokenFetcher: TokenFetcher, @param:ApplicationContext private val context: Context, @param:PushNotificationModule.PushProcessingSemaphore private val semaphore: Semaphore, private val pushRegistrationDatabase: PushRegistrationDatabase, + @param:ManagerScope private val scope: kotlinx.coroutines.CoroutineScope ) : AuthAwareComponent { private val firstRun = AtomicBoolean(true) @@ -52,7 +55,7 @@ class PushRegistrationHandler @Inject constructor( ) .castAwayType() .onStart { emit(Unit) }, - preferences.pushEnabled, + preferenceStorage.watch(scope = scope, key = PushPreferences.IS_PUSH_ENABLED), tokenFetcher.token.filterNotNull().filter { !it.isBlank() } ) { _, enabled, token -> if (enabled) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java index bb554ba913..fbab4b4d5d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java @@ -70,9 +70,10 @@ public SingleRecipientNotificationBuilder( @NonNull Context context, @NonNull NotificationPrivacyPreference privacy, @NonNull AvatarUtils avatarUtils, - Provider imageLoaderProvider + Provider imageLoaderProvider, + @NonNull NotificationChannels notificationChannels ) { - super(context, privacy); + super(context, privacy, notificationChannels); this.avatarUtils = avatarUtils; this.imageLoaderProvider = imageLoaderProvider; @@ -82,7 +83,7 @@ public SingleRecipientNotificationBuilder( } public void setThread(@NonNull Recipient recipient) { - setChannelId(NotificationChannels.getMessagesChannel(context)); + setChannelId(notificationChannels.getMessagesChannel()); Bitmap largeIconBitmap; boolean recycleBitmap; diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/LandingActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/LandingActivity.kt index cabc138f2d..3d55299204 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/LandingActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/landing/LandingActivity.kt @@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.onboarding.landing import android.os.Bundle import dagger.hilt.android.AndroidEntryPoint import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SecurityPreferences import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.onboarding.loadaccount.LoadAccountActivity @@ -19,6 +21,9 @@ class LandingActivity: BaseActionBarActivity() { @Inject internal lateinit var prefs: TextSecurePreferences + @Inject + lateinit var preferenceStorage: PreferenceStorage + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -36,7 +41,7 @@ class LandingActivity: BaseActionBarActivity() { } IdentityKeyUtil.generateIdentityKeyPair(this) - TextSecurePreferences.setPasswordDisabled(this, true) + preferenceStorage[SecurityPreferences.PASSWORD_DISABLED] = true // AC: This is a temporary workaround to trick the old code that the screen is unlocked. KeyCachingService.setMasterSecret(applicationContext, Object()) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loadaccount/LoadAccountActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loadaccount/LoadAccountActivity.kt index bbb688785e..33b1194ee5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loadaccount/LoadAccountActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loadaccount/LoadAccountActivity.kt @@ -13,6 +13,8 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.onboarding.manager.LoadAccountManager import org.thoughtcrime.securesms.onboarding.messagenotifications.MessageNotificationsActivity @@ -28,6 +30,8 @@ class LoadAccountActivity : BaseActionBarActivity() { @Inject internal lateinit var prefs: TextSecurePreferences @Inject + lateinit var preferenceStorage: PreferenceStorage + @Inject internal lateinit var loadAccountManager: LoadAccountManager private val viewModel: LoadAccountViewModel by viewModels() @@ -45,7 +49,7 @@ class LoadAccountActivity : BaseActionBarActivity() { ) supportActionBar?.setTitle(R.string.loadAccount) - prefs.setConfigurationMessageSynced(false) + preferenceStorage[MessagingPreferences.CONFIGURATION_SYNCED] = false lifecycleScope.launch { diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BackupPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BackupPreferences.kt new file mode 100644 index 0000000000..b3271f8d4e --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BackupPreferences.kt @@ -0,0 +1,9 @@ +package org.thoughtcrime.securesms.preferences + +object BackupPreferences { + val BACKUP_ENABLED = PreferenceKey.boolean("pref_backup_enabled_v3", false) + val BACKUP_PASSPHRASE = PreferenceKey.string("pref_backup_passphrase", null) + val ENCRYPTED_BACKUP_PASSPHRASE = PreferenceKey.string("pref_encrypted_backup_passphrase", null) + val NEXT_BACKUP_TIME = PreferenceKey.long("pref_backup_next_time", -1L) + val BACKUP_SAVE_DIR = PreferenceKey.string("pref_save_dir", null) +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/MessagingPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/MessagingPreferences.kt new file mode 100644 index 0000000000..254c34fa17 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/MessagingPreferences.kt @@ -0,0 +1,18 @@ +package org.thoughtcrime.securesms.preferences + +import kotlinx.serialization.Serializable +import org.session.libsession.messaging.file_server.FileServer + +object MessagingPreferences { + val AUTOPLAY_AUDIO_MESSAGES = PreferenceKey.boolean("pref_autoplay_audio", false) + val SEND_WITH_ENTER = PreferenceKey.boolean("pref_enter_sends", false) + val THREAD_TRIM_ENABLED = PreferenceKey.boolean("pref_trim_threads", true) + val CONFIGURATION_SYNCED = PreferenceKey.boolean("pref_configuration_synced", false) + val GIF_SEARCH_IN_GRID_LAYOUT = PreferenceKey.boolean("pref_gif_grid_layout", false) + val MESSAGE_BODY_TEXT_SIZE = PreferenceKey.string("pref_message_body_text_size", "16") + val HAS_HIDDEN_MESSAGE_REQUESTS = PreferenceKey.boolean("pref_message_requests_hidden", false) + val FORCED_SHORT_TTL = PreferenceKey.boolean("forced_short_ttl", false) + val FORCES_DETERMINISTIC_ATTACHMENT_ENCRYPTION = PreferenceKey.boolean("forces_deterministic_attachment_upload", false) + val DEBUG_AVATAR_REUPLOAD = PreferenceKey.boolean("debug_avatar_reupload", false) + val ALTERNATIVE_FILE_SERVER = PreferenceKey.json("alternative_file_server") +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationPreferences.kt new file mode 100644 index 0000000000..807366a041 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationPreferences.kt @@ -0,0 +1,16 @@ +package org.thoughtcrime.securesms.preferences + +object NotificationPreferences { + @JvmField val NOTIFICATIONS_ENABLED = PreferenceKey.boolean("pref_key_enable_notifications", true) + @JvmField val VIBRATE_ENABLED = PreferenceKey.boolean("pref_key_vibrate", true) + @JvmField val RINGTONE = PreferenceKey.string("pref_key_ringtone", "content://settings/system/notification_sound") + @JvmField val LED_COLOR = PreferenceKey.int("pref_led_color_primary", 0) + @JvmField val CALL_NOTIFICATIONS_ENABLED = PreferenceKey.boolean("pref_call_notifications_enabled", false) + @JvmField val NOTIFICATION_PRIVACY = PreferenceKey.string("pref_notification_privacy", "all") + @JvmField val SOUND_WHEN_OPEN = PreferenceKey.boolean("pref_sound_when_app_open", false) + @JvmField val REPEAT_ALERTS_COUNT = PreferenceKey.string("pref_repeat_alerts", "0") + @JvmField val IN_THREAD_NOTIFICATIONS = PreferenceKey.boolean("pref_key_inthread_notifications", true) + @JvmField val CHANNEL_VERSION = PreferenceKey.int("pref_notification_channel_version", 1) + @JvmField val MESSAGES_CHANNEL_VERSION = PreferenceKey.int("pref_notification_messages_channel_version", 1) + @JvmField val HAVE_SHOWN_TOKEN_PAGE_NOTIFICATION = PreferenceKey.boolean("pref_shown_a_notification_about_token_page", false) +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacyPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacyPreferences.kt new file mode 100644 index 0000000000..cc05b6ca45 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacyPreferences.kt @@ -0,0 +1,12 @@ +package org.thoughtcrime.securesms.preferences + +object PrivacyPreferences { + val READ_RECEIPTS = PreferenceKey.boolean("pref_read_receipts", false) + val TYPING_INDICATORS = PreferenceKey.boolean("pref_typing_indicators", false) + val LINK_PREVIEWS = PreferenceKey.boolean("pref_link_previews", false) + val INCOGNITO_KEYBOARD = PreferenceKey.boolean("pref_incognito_keyboard", true) + val HAS_SEEN_LINK_PREVIEW_SUGGESTION_DIALOG = PreferenceKey.boolean("has_seen_link_preview_suggestion_dialog", false) + val HAS_SEEN_GIF_METADATA_WARNING = PreferenceKey.boolean("has_seen_gif_metadata_warning", false) + val HAVE_WARNED_USER_ABOUT_SAVING_ATTACHMENTS = PreferenceKey.boolean("libsession.HAVE_WARNED_USER_ABOUT_SAVING_ATTACHMENTS", false) + val UNIVERSAL_UNIDENTIFIED_ACCESS = PreferenceKey.boolean("pref_universal_unidentified_access", false) +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ProPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/ProPreferences.kt new file mode 100644 index 0000000000..36b6340c23 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ProPreferences.kt @@ -0,0 +1,18 @@ +package org.thoughtcrime.securesms.preferences + +import org.thoughtcrime.securesms.debugmenu.DebugMenuViewModel + +object ProPreferences { + val FORCE_CURRENT_USER_AS_PRO = PreferenceKey.boolean("pref_force_current_user_pro", false) + val FORCE_OTHER_USERS_PRO = PreferenceKey.boolean("pref_force_other_users_pro", false) + val FORCE_INCOMING_MESSAGES_AS_PRO = PreferenceKey.boolean("pref_force_incoming_message_pro", false) + val FORCE_POST_PRO = PreferenceKey.boolean("pref_force_post_pro", false) + val HAS_SEEN_PRO_EXPIRING = PreferenceKey.boolean("has_seen_pro_expiring", false) + val HAS_SEEN_PRO_EXPIRED = PreferenceKey.boolean("has_seen_pro_expired", false) + val DEBUG_FORCE_NO_BILLING = PreferenceKey.boolean("debug_pro_has_billing", false) + val DEBUG_IS_WITHIN_QUICK_REFUND = PreferenceKey.boolean("debug_within_quick_refund", false) + val SUBSCRIPTION_PROVIDER = PreferenceKey.string("session_subscription_provider", null) + + val DEBUG_SUBSCRIPTION_STATUS = PreferenceKey.enum("debug_subscription_status") + val DEBUG_PRO_PLAN_STATUS = PreferenceKey.enum("debug_pro_plan_status") +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/PushPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/PushPreferences.kt new file mode 100644 index 0000000000..139d2374df --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/PushPreferences.kt @@ -0,0 +1,7 @@ +package org.thoughtcrime.securesms.preferences + +import network.loki.messenger.BuildConfig + +object PushPreferences { + val IS_PUSH_ENABLED = PreferenceKey.boolean("pref_is_using_fcm${BuildConfig.PUSH_KEY_SUFFIX}", false) +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SecurityPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SecurityPreferences.kt new file mode 100644 index 0000000000..19e9315d1c --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SecurityPreferences.kt @@ -0,0 +1,10 @@ +package org.thoughtcrime.securesms.preferences + +object SecurityPreferences { + @JvmField val SCREEN_LOCK = PreferenceKey.boolean("pref_android_screen_lock", false) + @JvmField val PASSWORD_DISABLED = PreferenceKey.boolean("pref_disable_passphrase", true) + @JvmField val SCREEN_LOCK_TIMEOUT = PreferenceKey.long("pref_android_screen_lock_timeout", 0L) + @JvmField val PASSPHRASE_TIMEOUT_ENABLED = PreferenceKey.boolean("pref_timeout_passphrase", false) + @JvmField val PASSPHRASE_TIMEOUT_INTERVAL = PreferenceKey.int("pref_timeout_interval", 5 * 60) + @JvmField val NEEDS_SQLCIPHER_MIGRATION = PreferenceKey.boolean("pref_needs_sql_cipher_migration", false) +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SystemPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SystemPreferences.kt new file mode 100644 index 0000000000..980d11b9ed --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SystemPreferences.kt @@ -0,0 +1,25 @@ +package org.thoughtcrime.securesms.preferences + +object SystemPreferences { + val UPDATE_APK_REFRESH_TIME = PreferenceKey.long("pref_update_apk_refresh_time", 0L) + val UPDATE_APK_DOWNLOAD_ID = PreferenceKey.long("pref_update_apk_download_id", -1L) + val UPDATE_APK_DIGEST = PreferenceKey.string("pref_update_apk_digest", null) + val HAS_RECEIVED_LEGACY_CONFIG = PreferenceKey.boolean("has_received_legacy_config", false) + val LAST_VERSION_CODE = PreferenceKey.int("last_version_code", 0) + val LANGUAGE = PreferenceKey.string("pref_language", "zz") + val LAST_OPEN_DATE = PreferenceKey.long("pref_last_open_date", 0L) + val LAST_VACUUM_TIME = PreferenceKey.long("pref_last_vacuum_time", 0L) + val HAS_FORCED_NEW_CONFIG = PreferenceKey.boolean("has_forced_new_config", false) + val LAST_VERSION_CHECK = PreferenceKey.long("pref_last_version_check", 0L) + val HAS_CHECKED_DOZE_WHITELIST = PreferenceKey.boolean("has_checked_doze_whitelist", false) + val HAS_DONATED = PreferenceKey.boolean("has_donated", false) + val HAS_COPIED_DONATION_URL = PreferenceKey.boolean("has_copied_donation_url", false) + val SEEN_DONATION_CTA_AMOUNT = PreferenceKey.int("seen_donation_cta_amount", 0) + val LAST_SEEN_DONATION_CTA = PreferenceKey.long("last_seen_donation_cta", 0L) + val SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW = PreferenceKey.boolean("show_donation_cta_from_positive_review", false) + val LAST_SNODE_POOL_REFRESH = PreferenceKey.long("last_snode_pool_refresh", 0L) + val LAST_PATH_ROTATION = PreferenceKey.long("last_path_rotation", 0L) + val IN_APP_REVIEW_STATE = PreferenceKey.string("in_app_review_state", null) + val MIGRATED_TO_GROUP_V2_CONFIG = PreferenceKey.boolean("migrated_to_group_v2_config", false) + val MIGRATED_TO_DISABLING_KDF = PreferenceKey.boolean("migrated_to_disabling_kdf", false) +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ThemingPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/ThemingPreferences.kt new file mode 100644 index 0000000000..b72b43ab1d --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ThemingPreferences.kt @@ -0,0 +1,13 @@ +package org.thoughtcrime.securesms.preferences + +object ThemingPreferences { + const val CLASSIC_DARK = "classic.dark" + const val CLASSIC_LIGHT = "classic.light" + const val OCEAN_DARK = "ocean.dark" + const val OCEAN_LIGHT = "ocean.light" + + val SELECTED_STYLE = PreferenceKey.string("pref_selected_style", CLASSIC_DARK) + val FOLLOW_SYSTEM_SETTINGS = PreferenceKey.boolean("pref_follow_system", false) + val SELECTED_ACCENT_COLOR = PreferenceKey.string("selected_accent_color", null) + val SELECTED_ACTIVITY_ALIAS_NAME = PreferenceKey.string("selected_activity_alias_name", null) +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/ChatsPreferenceViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/ChatsPreferenceViewModel.kt index 25a6f90caa..2076e1a936 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/ChatsPreferenceViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/ChatsPreferenceViewModel.kt @@ -8,19 +8,21 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.stateIn import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsession.utilities.observeBooleanKey +import org.thoughtcrime.securesms.preferences.MessagingPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import javax.inject.Inject @HiltViewModel class ChatsPreferenceViewModel @Inject constructor( - var prefs: TextSecurePreferences + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage ) : ViewModel() { val uiState: StateFlow = combine( - prefs.observeBooleanKey(TextSecurePreferences.THREAD_TRIM_ENABLED, default = false), - prefs.observeBooleanKey(TextSecurePreferences.SEND_WITH_ENTER, default = false), - prefs.observeBooleanKey(TextSecurePreferences.AUTOPLAY_AUDIO_MESSAGES, default = false), + preferenceStorage.watch(viewModelScope, MessagingPreferences.THREAD_TRIM_ENABLED), + preferenceStorage.watch(viewModelScope, MessagingPreferences.SEND_WITH_ENTER), + preferenceStorage.watch(viewModelScope, MessagingPreferences.AUTOPLAY_AUDIO_MESSAGES), ) { trim, enter, autoplay -> UIState( trimThreads = trim, @@ -31,17 +33,17 @@ class ChatsPreferenceViewModel @Inject constructor( scope = viewModelScope, started = SharingStarted.Eagerly, initialValue = UIState( - trimThreads = prefs.isThreadLengthTrimmingEnabled(), - sendWithEnter = prefs.isSendWithEnterEnabled(), - autoplayAudioMessage = prefs.isAutoplayAudioMessagesEnabled(), + trimThreads = preferenceStorage[MessagingPreferences.THREAD_TRIM_ENABLED], + sendWithEnter = preferenceStorage[MessagingPreferences.SEND_WITH_ENTER], + autoplayAudioMessage = preferenceStorage[MessagingPreferences.AUTOPLAY_AUDIO_MESSAGES], ) ) fun onCommand(command: Commands) { when (command) { - is Commands.ToggleTrimThreads -> prefs.setThreadLengthTrimmingEnabled(command.isEnabled) - is Commands.ToggleSendWithEnter -> prefs.setSendWithEnterEnabled(command.isEnabled) - is Commands.ToggleAutoplayAudioMessages -> prefs.setAutoplayAudioMessages(command.isEnabled) + is Commands.ToggleTrimThreads -> preferenceStorage[MessagingPreferences.THREAD_TRIM_ENABLED] = command.isEnabled + is Commands.ToggleSendWithEnter -> preferenceStorage[MessagingPreferences.SEND_WITH_ENTER] = command.isEnabled + is Commands.ToggleAutoplayAudioMessages -> preferenceStorage[MessagingPreferences.AUTOPLAY_AUDIO_MESSAGES] = command.isEnabled } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/NotificationsPreferenceViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/NotificationsPreferenceViewModel.kt index 6b3850a009..cfead2c136 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/NotificationsPreferenceViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/NotificationsPreferenceViewModel.kt @@ -19,16 +19,19 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsession.utilities.observeBooleanKey -import org.session.libsession.utilities.observeStringKey import org.thoughtcrime.securesms.notifications.NotificationChannels +import org.thoughtcrime.securesms.preferences.NotificationPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SystemPreferences import org.thoughtcrime.securesms.ui.isWhitelistedFromDoze import javax.inject.Inject import kotlin.Boolean @HiltViewModel class NotificationsPreferenceViewModel @Inject constructor( - var prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, + private val notificationChannels: NotificationChannels, val application: Application, ) : ViewModel() { @@ -46,11 +49,11 @@ class NotificationsPreferenceViewModel @Inject constructor( private val notifPrefsFlow = combine( - prefs.observeBooleanKey(TextSecurePreferences.HAS_CHECKED_DOZE_WHITELIST, default = false), - prefs.observeStringKey(TextSecurePreferences.RINGTONE_PREF, default = null), - prefs.observeBooleanKey(TextSecurePreferences.SOUND_WHEN_OPEN, default = false), - prefs.observeBooleanKey(TextSecurePreferences.VIBRATE_PREF, default = true), - prefs.observeStringKey(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF, default = "all"), + preferenceStorage.watch(viewModelScope, SystemPreferences.HAS_CHECKED_DOZE_WHITELIST), + preferenceStorage.watch(viewModelScope, NotificationPreferences.RINGTONE), + preferenceStorage.watch(viewModelScope, NotificationPreferences.SOUND_WHEN_OPEN), + preferenceStorage.watch(viewModelScope, NotificationPreferences.VIBRATE_ENABLED), + preferenceStorage.watch(viewModelScope, NotificationPreferences.NOTIFICATION_PRIVACY), ) { checkedDozeWhitelist, ringtonePrefString, soundWhenOpen, vibrate, notificationPrivacy -> NotifPrefsData( checkedDozeWhitelist = checkedDozeWhitelist, @@ -62,7 +65,7 @@ class NotificationsPreferenceViewModel @Inject constructor( } init { - combine(prefs.pushEnabled, notifPrefsFlow) { strategy, notif -> + combine(textSecurePreferences.pushEnabled, notifPrefsFlow) { strategy, notif -> strategy to notif }.onEach { (isPushEnabled, notif) -> _uiState.update { old -> @@ -122,11 +125,11 @@ class NotificationsPreferenceViewModel @Inject constructor( val currentState = uiState.value val isEnabled = command.isEnabled - prefs.setPushEnabled(isEnabled) + textSecurePreferences.setPushEnabled(isEnabled) if (!isEnabled && !currentState.checkedDozeWhitelist) { _uiState.update { it.copy(showWhitelistEnableDialog = true) } - prefs.setHasCheckedDozeWhitelist(true) + preferenceStorage[SystemPreferences.HAS_CHECKED_DOZE_WHITELIST] = true } } @@ -144,7 +147,7 @@ class NotificationsPreferenceViewModel @Inject constructor( } Commands.RingtoneClicked -> { - val current = prefs.getNotificationRingtone() + val current = textSecurePreferences.getNotificationRingtone() val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER) intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true) intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true) @@ -170,21 +173,22 @@ class NotificationsPreferenceViewModel @Inject constructor( is Commands.SetRingtone -> { var ringtoneUri = command.uri if (Settings.System.DEFAULT_NOTIFICATION_URI == ringtoneUri) { - NotificationChannels.updateMessageRingtone(application, ringtoneUri) - prefs.removeNotificationRingtone() + notificationChannels.updateMessageRingtone(ringtoneUri) + preferenceStorage.remove(NotificationPreferences.RINGTONE) } else { ringtoneUri = command.uri ?: Uri.EMPTY - NotificationChannels.updateMessageRingtone(application, ringtoneUri) - prefs.setNotificationRingtone(ringtoneUri.toString()) + notificationChannels.updateMessageRingtone(ringtoneUri) + preferenceStorage[NotificationPreferences.RINGTONE] = ringtoneUri.toString() } } is Commands.ToggleSoundWhenOpen -> { - prefs.setSoundWhenAppIsOpenEnabled(command.isEnabled) + preferenceStorage[NotificationPreferences.SOUND_WHEN_OPEN] = command.isEnabled } is Commands.ToggleVibrate -> { - prefs.setNotificationVibrateEnabled(command.isEnabled) + preferenceStorage[NotificationPreferences.VIBRATE_ENABLED] = command.isEnabled + notificationChannels.updateMessageVibrate(command.isEnabled) } Commands.OpenSystemBgWhitelist -> { @@ -203,7 +207,7 @@ class NotificationsPreferenceViewModel @Inject constructor( val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) intent.putExtra( Settings.EXTRA_CHANNEL_ID, - NotificationChannels.getMessagesChannel(application) + notificationChannels.getMessagesChannel() ) intent.putExtra(Settings.EXTRA_APP_PACKAGE, application.packageName) @@ -213,7 +217,7 @@ class NotificationsPreferenceViewModel @Inject constructor( } is Commands.SelectNotificationPrivacyOption -> { - prefs.setNotificationPrivacy(command.option) + preferenceStorage[NotificationPreferences.NOTIFICATION_PRIVACY] = command.option hideNotificationPrivacyDialog() } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/PrivacySettingsPreferenceViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/PrivacySettingsPreferenceViewModel.kt index da63239f2f..f82670c1b8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/PrivacySettingsPreferenceViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/compose/PrivacySettingsPreferenceViewModel.kt @@ -17,17 +17,12 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsession.utilities.TextSecurePreferences.Companion.CALL_NOTIFICATIONS_ENABLED -import org.session.libsession.utilities.TextSecurePreferences.Companion.DISABLE_PASSPHRASE_PREF -import org.session.libsession.utilities.TextSecurePreferences.Companion.INCOGNITO_KEYBOARD_PREF -import org.session.libsession.utilities.TextSecurePreferences.Companion.READ_RECEIPTS_PREF -import org.session.libsession.utilities.TextSecurePreferences.Companion.SCREEN_LOCK -import org.session.libsession.utilities.TextSecurePreferences.Companion.TYPING_INDICATORS -import org.session.libsession.utilities.TextSecurePreferences.Companion.LINK_PREVIEWS -import org.session.libsession.utilities.observeBooleanKey +import org.session.libsession.utilities.ConfigFactoryProtocol import org.session.libsession.utilities.withMutableUserConfigs -import org.thoughtcrime.securesms.dependencies.ConfigFactory +import org.thoughtcrime.securesms.preferences.NotificationPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.PrivacyPreferences +import org.thoughtcrime.securesms.preferences.SecurityPreferences import org.thoughtcrime.securesms.preferences.compose.PrivacySettingsPreferenceViewModel.Commands.ShowCallsWarningDialog import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder.Companion.areNotificationsEnabled @@ -35,8 +30,8 @@ import javax.inject.Inject @HiltViewModel class PrivacySettingsPreferenceViewModel @Inject constructor( - private val prefs: TextSecurePreferences, - private val configFactory: ConfigFactory, + private val preferenceStorage: PreferenceStorage, + private val configFactory: ConfigFactoryProtocol, private val app: Application, private val typingStatusRepository: TypingStatusRepository, ) : ViewModel() { @@ -61,19 +56,19 @@ class PrivacySettingsPreferenceViewModel @Inject constructor( // Use this to get index for UI item. We need the index to tell the listState where to scroll // list things ordered by how they appear on the list private var prefItemsOrder = listOf( - CALL_NOTIFICATIONS_ENABLED, - SCREEN_LOCK, + NotificationPreferences.CALL_NOTIFICATIONS_ENABLED.name, + SecurityPreferences.SCREEN_LOCK.name, "community_message_requests", - READ_RECEIPTS_PREF, - TYPING_INDICATORS, - LINK_PREVIEWS, - INCOGNITO_KEYBOARD_PREF + PrivacyPreferences.READ_RECEIPTS.name, + PrivacyPreferences.TYPING_INDICATORS.name, + PrivacyPreferences.LINK_PREVIEWS.name, + PrivacyPreferences.INCOGNITO_KEYBOARD.name ) private val screenLockFlow = combine( - prefs.observeBooleanKey(SCREEN_LOCK, default = false), - prefs.observeBooleanKey(DISABLE_PASSPHRASE_PREF, default = false), + preferenceStorage.watch(viewModelScope, SecurityPreferences.SCREEN_LOCK), + preferenceStorage.watch(viewModelScope, SecurityPreferences.PASSWORD_DISABLED), keyguardSecure ) { screenLockPref, isPasswordDisabled, keyguard -> @@ -86,11 +81,11 @@ class PrivacySettingsPreferenceViewModel @Inject constructor( private val togglesFlow = combine( - prefs.observeBooleanKey(CALL_NOTIFICATIONS_ENABLED, default = false), - prefs.observeBooleanKey(READ_RECEIPTS_PREF, default = false), - prefs.observeBooleanKey(TYPING_INDICATORS, default = false), - prefs.observeBooleanKey(LINK_PREVIEWS, default = false), - prefs.observeBooleanKey(INCOGNITO_KEYBOARD_PREF, default = false), + preferenceStorage.watch(viewModelScope, NotificationPreferences.CALL_NOTIFICATIONS_ENABLED), + preferenceStorage.watch(viewModelScope, PrivacyPreferences.READ_RECEIPTS), + preferenceStorage.watch(viewModelScope, PrivacyPreferences.TYPING_INDICATORS), + preferenceStorage.watch(viewModelScope, PrivacyPreferences.LINK_PREVIEWS), + preferenceStorage.watch(viewModelScope, PrivacyPreferences.INCOGNITO_KEYBOARD), ) { callsEnabled, readReceipts, typing, linkPreviews, incognito -> TogglePrefsData(callsEnabled, readReceipts, typing, linkPreviews, incognito) } @@ -169,12 +164,16 @@ class PrivacySettingsPreferenceViewModel @Inject constructor( action.scrollAndToggleKey?.let { key -> when (key) { - CALL_NOTIFICATIONS_ENABLED -> { + NotificationPreferences.CALL_NOTIFICATIONS_ENABLED.name -> { // need to do some checks before toggling onCommand(ShowCallsWarningDialog) } - else -> prefs.updateBooleanFromKey(key, true) + PrivacyPreferences.READ_RECEIPTS.name -> preferenceStorage[PrivacyPreferences.READ_RECEIPTS] = true + PrivacyPreferences.TYPING_INDICATORS.name -> preferenceStorage[PrivacyPreferences.TYPING_INDICATORS] = true + PrivacyPreferences.LINK_PREVIEWS.name -> preferenceStorage[PrivacyPreferences.LINK_PREVIEWS] = true + PrivacyPreferences.INCOGNITO_KEYBOARD.name -> preferenceStorage[PrivacyPreferences.INCOGNITO_KEYBOARD] = true + SecurityPreferences.SCREEN_LOCK.name -> preferenceStorage[SecurityPreferences.SCREEN_LOCK] = true } } @@ -190,7 +189,7 @@ class PrivacySettingsPreferenceViewModel @Inject constructor( fun onCommand(command: Commands) { when (command) { is Commands.ToggleCallsNotification -> { - prefs.setCallNotificationsEnabled(command.isEnabled) + preferenceStorage[NotificationPreferences.CALL_NOTIFICATIONS_ENABLED] = command.isEnabled if (command.isEnabled && !areNotificationsEnabled(app)) { _uiState.update { it.copy(showCallsNotificationDialog = true) } } @@ -199,7 +198,7 @@ class PrivacySettingsPreferenceViewModel @Inject constructor( is Commands.ToggleLockApp -> { // if UI disabled it, ignore if (!uiState.value.screenLockEnabled) return - prefs.setScreenLockEnabled(command.isEnabled) + preferenceStorage[SecurityPreferences.SCREEN_LOCK] = command.isEnabled viewModelScope.launch { _uiEvents.emit(PrivacySettingsPreferenceEvent.StartLockToggledService) } @@ -215,20 +214,20 @@ class PrivacySettingsPreferenceViewModel @Inject constructor( } is Commands.ToggleReadReceipts -> { - prefs.setReadReceiptsEnabled(command.isEnabled) + preferenceStorage[PrivacyPreferences.READ_RECEIPTS] = command.isEnabled } is Commands.ToggleTypingIndicators -> { - prefs.setTypingIndicatorsEnabled(command.isEnabled) + preferenceStorage[PrivacyPreferences.TYPING_INDICATORS] = command.isEnabled if (!command.isEnabled) typingStatusRepository.clear() } is Commands.ToggleLinkPreviews -> { - prefs.setLinkPreviewsEnabled(command.isEnabled) + preferenceStorage[PrivacyPreferences.LINK_PREVIEWS] = command.isEnabled } is Commands.ToggleIncognitoKeyboard -> { - prefs.setIncognitoKeyboardEnabled(command.isEnabled) + preferenceStorage[PrivacyPreferences.INCOGNITO_KEYBOARD] = command.isEnabled } Commands.AskMicPermission -> { diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/prosettings/ProSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/prosettings/ProSettingsViewModel.kt index 62fbf7e31b..41b90d94be 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/prosettings/ProSettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/prosettings/ProSettingsViewModel.kt @@ -50,6 +50,8 @@ import org.session.libsession.utilities.withMutableUserConfigs import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.debugmenu.DebugLogGroup import org.thoughtcrime.securesms.debugmenu.DebugMenuViewModel +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences import org.thoughtcrime.securesms.preferences.prosettings.ProSettingsViewModel.Commands.ShowOpenUrlDialog import org.thoughtcrime.securesms.pro.ProDataState import org.thoughtcrime.securesms.pro.ProDetailsRepository @@ -79,7 +81,8 @@ class ProSettingsViewModel @AssistedInject constructor( private val proStatusManager: ProStatusManager, private val subscriptionCoordinator: SubscriptionCoordinator, private val dateUtils: DateUtils, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val proDetailsRepository: ProDetailsRepository, private val configFactory: Lazy, private val storage: StorageProtocol, @@ -392,7 +395,7 @@ class ProSettingsViewModel @AssistedInject constructor( viewModelScope.launch { _refundPlanState.update { - val isQuickRefund = if(prefs.forceCurrentUserAsPro()) prefs.getDebugIsWithinQuickRefund()// debug mode + val isQuickRefund = if(preferenceStorage[ProPreferences.FORCE_CURRENT_USER_AS_PRO]) preferenceStorage[ProPreferences.DEBUG_IS_WITHIN_QUICK_REFUND] ?: false// debug mode else sub.isWithinQuickRefundWindow() State.Success( @@ -942,7 +945,7 @@ class ProSettingsViewModel @AssistedInject constructor( private fun refreshProStats(){ viewModelScope.launch { // if we have a debug toggle for the loading state, respect it - val currentDebugState = prefs.getDebugProPlanStatus() + val currentDebugState = preferenceStorage[ProPreferences.DEBUG_PRO_PLAN_STATUS] val debugState = when(currentDebugState) { DebugMenuViewModel.DebugProPlanStatus.LOADING -> State.Loading DebugMenuViewModel.DebugProPlanStatus.ERROR -> State.Error(Exception()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/pro/FetchProDetailsWorker.kt b/app/src/main/java/org/thoughtcrime/securesms/pro/FetchProDetailsWorker.kt index 6efe79e888..eb94d80946 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/pro/FetchProDetailsWorker.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/pro/FetchProDetailsWorker.kt @@ -21,6 +21,10 @@ import kotlinx.coroutines.flow.mapNotNull import org.session.libsession.network.SnodeClock import org.session.libsession.utilities.ConfigFactoryProtocol import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.dependencies.AppComponent +import dagger.hilt.EntryPoints +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences import org.session.libsession.utilities.withMutableUserConfigs import org.session.libsession.utilities.withUserConfigs import org.session.libsignal.exceptions.NonRetryableException @@ -58,7 +62,8 @@ class FetchProDetailsWorker @AssistedInject constructor( private val prefs: TextSecurePreferences, ) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { - if (!prefs.forcePostPro()) { + val preferenceStorage = EntryPoints.get(context.applicationContext, AppComponent::class.java).getPreferenceStorage() + if (!preferenceStorage[ProPreferences.FORCE_POST_PRO]) { Log.d(TAG, "Pro details fetch skipped because pro is not enabled") return Result.success() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/pro/ProDetailsRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/pro/ProDetailsRepository.kt index 5f66b6cda1..b75fc56712 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/pro/ProDetailsRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/pro/ProDetailsRepository.kt @@ -13,6 +13,8 @@ import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import org.session.libsession.network.SnodeClock import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.auth.LoginStateRepository import org.thoughtcrime.securesms.debugmenu.DebugLogGroup @@ -31,7 +33,8 @@ class ProDetailsRepository @Inject constructor( private val snodeClock: SnodeClock, @ManagerScope scope: CoroutineScope, loginStateRepository: LoginStateRepository, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val networkConnectivity: NetworkConnectivity, ) { sealed interface LoadState { @@ -89,7 +92,7 @@ class ProDetailsRepository @Inject constructor( * made regardless of the freshness of the last update. */ fun requestRefresh(force: Boolean = false) { - if (!prefs.forcePostPro()) { + if (!preferenceStorage[ProPreferences.FORCE_POST_PRO]) { Log.d(DebugLogGroup.PRO_DATA.label, "Pro hasn't been enabled, skipping refresh") return } diff --git a/app/src/main/java/org/thoughtcrime/securesms/pro/ProStatusManager.kt b/app/src/main/java/org/thoughtcrime/securesms/pro/ProStatusManager.kt index 481f3a891f..c69af59c18 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/pro/ProStatusManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/pro/ProStatusManager.kt @@ -63,6 +63,8 @@ import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.debugmenu.DebugLogGroup import org.thoughtcrime.securesms.debugmenu.DebugMenuViewModel import org.thoughtcrime.securesms.dependencies.ManagerScope +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences import org.thoughtcrime.securesms.pro.api.AddPaymentErrorStatus import org.thoughtcrime.securesms.pro.api.AddProPaymentApi import org.thoughtcrime.securesms.pro.api.ProApiResponse @@ -84,7 +86,8 @@ import kotlin.time.Duration.Companion.milliseconds @Singleton class ProStatusManager @Inject constructor( private val application: Application, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, @param:ManagerScope private val scope: CoroutineScope, private val serverApiExecutor: ServerApiExecutor, private val addProPaymentApiFactory: AddProPaymentApi.Factory, @@ -108,15 +111,18 @@ class ProStatusManager @Inject constructor( } .distinctUntilChanged(), proDetailsRepository.get().loadState, - (TextSecurePreferences.events.filter { it == TextSecurePreferences.DEBUG_SUBSCRIPTION_STATUS } as Flow<*>) - .onStart { emit(Unit) } - .map { prefs.getDebugSubscriptionType() }, - (TextSecurePreferences.events.filter { it == TextSecurePreferences.DEBUG_PRO_PLAN_STATUS } as Flow<*>) - .onStart { emit(Unit) } - .map { prefs.getDebugProPlanStatus() }, - (TextSecurePreferences.events.filter { it == TextSecurePreferences.SET_FORCE_CURRENT_USER_PRO } as Flow<*>) - .onStart { emit(Unit) } - .map { prefs.forceCurrentUserAsPro() }, + preferenceStorage.changes() + .filter { it.name == ProPreferences.DEBUG_SUBSCRIPTION_STATUS.name } + .onStart { emit(ProPreferences.DEBUG_SUBSCRIPTION_STATUS) } + .map { preferenceStorage[ProPreferences.DEBUG_SUBSCRIPTION_STATUS] }, + preferenceStorage.changes() + .filter { it.name == ProPreferences.DEBUG_PRO_PLAN_STATUS.name } + .onStart { emit(ProPreferences.DEBUG_PRO_PLAN_STATUS) } + .map { preferenceStorage[ProPreferences.DEBUG_PRO_PLAN_STATUS] }, + preferenceStorage.changes() + .filter { it.name == ProPreferences.FORCE_CURRENT_USER_AS_PRO.name } + .onStart { emit(ProPreferences.FORCE_CURRENT_USER_AS_PRO) } + .map { preferenceStorage[ProPreferences.FORCE_CURRENT_USER_AS_PRO] }, ){ showProBadgePreference, proDetailsState, debugSubscription, debugProPlanStatus, forceCurrentUserAsPro -> val proDataRefreshState = when(debugProPlanStatus){ @@ -231,9 +237,12 @@ class ProStatusManager @Inject constructor( init { scope.launch { - prefs.watchPostProStatus().collect { - _postProLaunchStatus.update { isPostPro() } - } + preferenceStorage.changes() + .filter { it.name == ProPreferences.FORCE_POST_PRO.name } + .onStart { emit(ProPreferences.FORCE_POST_PRO) } + .collect { + _postProLaunchStatus.update { isPostPro() } + } } } @@ -412,7 +421,7 @@ class ProStatusManager @Inject constructor( fun getIncomingMessageMaxLength(message: VisibleMessage): Int { // if the debug is set, return that // of if we are in pre-pro world - if (prefs.forceIncomingMessagesAsPro() || !isPostPro()) return MAX_CHARACTER_PRO + if (preferenceStorage[ProPreferences.FORCE_INCOMING_MESSAGES_AS_PRO] || !isPostPro()) return MAX_CHARACTER_PRO if (message.proFeatures.contains(ProMessageFeature.HIGHER_CHARACTER_LIMIT)) { return MAX_CHARACTER_PRO @@ -423,7 +432,7 @@ class ProStatusManager @Inject constructor( // Temporary method and concept that we should remove once Pro is out fun isPostPro(): Boolean { - return prefs.forcePostPro() + return preferenceStorage[ProPreferences.FORCE_POST_PRO] } fun getCharacterLimit(isPro: Boolean): Int { @@ -441,8 +450,8 @@ class ProStatusManager @Inject constructor( */ fun getMessageProFeatures(message: MessageRecord): Set { // use debug values if any - if(prefs.forceIncomingMessagesAsPro()){ - return prefs.getDebugMessageFeatures() + if(preferenceStorage[ProPreferences.FORCE_INCOMING_MESSAGES_AS_PRO]){ + return textSecurePreferences.getDebugMessageFeatures() } return message.proFeatures @@ -565,6 +574,14 @@ class ProStatusManager @Inject constructor( throw SubscriptionManager.PaymentServerException() } + private fun getDefaultSubscriptionStateData(): ProDataState { + return ProDataState( + type = ProStatus.NeverSubscribed, + showProBadge = false, + refreshState = State.Success(Unit) + ) + } + companion object { const val MAX_CHARACTER_PRO = 10000 // max characters in a message for pro users private const val MAX_CHARACTER_REGULAR = 2000 // max characters in a message for non pro users @@ -574,4 +591,4 @@ class ProStatusManager @Inject constructor( const val DEFAULT_GOOGLE_STORE = "Google Play Store" const val DEFAULT_APPLE_STORE = "Apple App Store" } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/pro/subscription/SubscriptionCoordinator.kt b/app/src/main/java/org/thoughtcrime/securesms/pro/subscription/SubscriptionCoordinator.kt index 64c8fb23d6..d37fec8ce8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/pro/subscription/SubscriptionCoordinator.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/pro/subscription/SubscriptionCoordinator.kt @@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.pro.subscription import jakarta.inject.Inject import jakarta.inject.Singleton import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.dependencies.OnAppStartupComponent @@ -13,7 +15,8 @@ import org.thoughtcrime.securesms.dependencies.OnAppStartupComponent class SubscriptionCoordinator @Inject constructor( private val availableManagers: Set<@JvmSuppressWildcards SubscriptionManager>, private val noopSubManager: NoOpSubscriptionManager, - private val prefs: TextSecurePreferences + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage ): OnAppStartupComponent { private var currentManager: SubscriptionManager? = null @@ -29,7 +32,7 @@ class SubscriptionCoordinator @Inject constructor( currentManager = managers.first() } else -> { - val savedProviderId = prefs.getSubscriptionProvider() + val savedProviderId = preferenceStorage[ProPreferences.SUBSCRIPTION_PROVIDER] currentManager = managers.find { it.id == savedProviderId } // If null, user needs to choose } @@ -44,7 +47,7 @@ class SubscriptionCoordinator @Inject constructor( currentManager = availableManagers.find { it.id == providerId } ?: throw IllegalArgumentException("Provider not found: $providerId") - prefs.setSubscriptionProvider(providerId) + preferenceStorage[ProPreferences.SUBSCRIPTION_PROVIDER] = providerId } fun getCurrentManager(): SubscriptionManager { diff --git a/app/src/main/java/org/thoughtcrime/securesms/reviews/InAppReviewManager.kt b/app/src/main/java/org/thoughtcrime/securesms/reviews/InAppReviewManager.kt index b00d41ffbb..4b4e62c631 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/reviews/InAppReviewManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/reviews/InAppReviewManager.kt @@ -24,6 +24,8 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.serialization.json.Json import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SystemPreferences import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.dependencies.ManagerScope import java.util.EnumSet @@ -35,7 +37,8 @@ import kotlin.time.Duration.Companion.days @Singleton class InAppReviewManager @Inject constructor( @param:ApplicationContext val context: Context, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val json: Json, private val storeReviewManager: StoreReviewManager, @param:ManagerScope private val scope: CoroutineScope, @@ -46,7 +49,7 @@ class InAppReviewManager @Inject constructor( @Suppress("OPT_IN_USAGE") val shouldShowPrompt: StateFlow = stateChangeNotification .onStart { emit(Unit) } - .map { prefs.reviewState } + .map { reviewState } .flatMapLatest { state -> when (state) { InAppReviewState.DismissedForever, is InAppReviewState.WaitingForTrigger, null -> flowOf(false) @@ -74,7 +77,7 @@ class InAppReviewManager @Inject constructor( eventsChannel = channel scope.launch { - val startState = prefs.reviewState ?: run { + val startState = reviewState ?: run { if (storeReviewManager.supportsReviewFlow) { val pkg = context.packageManager.getPackageInfo(context.packageName, 0) InAppReviewState.WaitingForTrigger( @@ -131,7 +134,7 @@ class InAppReviewManager @Inject constructor( } .distinctUntilChanged() .collectLatest { - prefs.reviewState = it + reviewState = it Log.d(TAG, "New review state is: $it") } } @@ -149,14 +152,14 @@ class InAppReviewManager @Inject constructor( Dismiss, } - private var TextSecurePreferences.reviewState - get() = prefs.inAppReviewState?.let { + private var reviewState: InAppReviewState? + get() = preferenceStorage[SystemPreferences.IN_APP_REVIEW_STATE]?.let { runCatching { json.decodeFromString(it) } .onFailure { Log.w(TAG, "Failed to decode review state", it) } .getOrNull() } set(value) { - prefs.inAppReviewState = + preferenceStorage[SystemPreferences.IN_APP_REVIEW_STATE] = value?.let { json.encodeToString(InAppReviewState.serializer(), it) } stateChangeNotification.tryEmit(Unit) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/reviews/ui/InAppReviewViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/reviews/ui/InAppReviewViewModel.kt index ba1a6833b2..c9ea4f97d8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/reviews/ui/InAppReviewViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/reviews/ui/InAppReviewViewModel.kt @@ -15,6 +15,8 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.scan import kotlinx.coroutines.flow.stateIn import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SystemPreferences import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.reviews.InAppReviewManager import org.thoughtcrime.securesms.reviews.StoreReviewManager @@ -26,7 +28,8 @@ private const val TAG = "InAppReviewViewModel" class InAppReviewViewModel @Inject constructor( private val manager: InAppReviewManager, private val storeReviewManager: StoreReviewManager, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, ) : ViewModel() { private val commands = MutableSharedFlow(extraBufferCapacity = 1) @@ -51,7 +54,7 @@ class InAppReviewViewModel @Inject constructor( // "It's Great" button clicked UiCommand.NegativeButtonClicked -> { // mark the app as needing to display the donation post positive review - prefs.setShowDonationCTAFromPositiveReview(true) + preferenceStorage[SystemPreferences.SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW] = true UiState.PositivePrompt } diff --git a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java index 7cbff2d8f3..a90b1afe0c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java @@ -25,14 +25,23 @@ import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker; import org.thoughtcrime.securesms.util.ParcelUtil; import org.session.libsession.utilities.TextSecurePreferences; +import org.thoughtcrime.securesms.preferences.PreferenceStorage; +import org.thoughtcrime.securesms.preferences.PrivacyPreferences; import org.thoughtcrime.securesms.util.ViewUtilitiesKt; import static android.app.Activity.RESULT_OK; +import javax.inject.Inject; + +import dagger.hilt.android.AndroidEntryPoint; + +@AndroidEntryPoint public final class ImageEditorFragment extends Fragment implements ImageEditorHud.EventListener, VerticalSlideColorPicker.OnColorChangeListener, MediaSendPageFragment { + @Inject PreferenceStorage preferenceStorage; + private static final String TAG = Log.tag(ImageEditorFragment.class); private static final String KEY_IMAGE_URI = "image_uri"; @@ -204,7 +213,7 @@ private void changeEntityColor(int selectedColor) { } private void startTextEntityEditing(@NonNull EditorElement textElement, boolean selectAll) { - imageEditorView.startTextEditing(textElement, TextSecurePreferences.isIncognitoKeyboardEnabled(requireContext()), selectAll); + imageEditorView.startTextEditing(textElement, preferenceStorage.get(PrivacyPreferences.INSTANCE.getINCOGNITO_KEYBOARD()), selectAll); } protected void addText() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java b/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java index 932498a158..00867e56e4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java @@ -44,6 +44,10 @@ import network.loki.messenger.R; import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.TextSecurePreferences; +import org.thoughtcrime.securesms.dependencies.AppComponent; +import dagger.hilt.EntryPoints; +import org.thoughtcrime.securesms.preferences.PreferenceStorage; +import org.thoughtcrime.securesms.preferences.SecurityPreferences; import org.session.libsignal.utilities.Log; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.DatabaseUpgradeActivity; @@ -51,6 +55,9 @@ import org.thoughtcrime.securesms.home.HomeActivity; import org.thoughtcrime.securesms.notifications.NotificationChannels; +import javax.inject.Inject; +import dagger.hilt.android.AndroidEntryPoint; + /** * Small service that stays running to keep a key cached in memory. * @@ -58,6 +65,7 @@ */ // TODO: This service does only serve one purpose now - to track the screen lock state and handle the timer. // We need to refactor it and cleanup from all the old Signal code. +@AndroidEntryPoint public class KeyCachingService extends Service { private static final String TAG = KeyCachingService.class.getSimpleName(); @@ -102,7 +110,8 @@ public void onServiceDisconnected(ComponentName name) { public KeyCachingService() {} public static synchronized boolean isLocked(Context context) { - boolean enabled = !TextSecurePreferences.isPasswordDisabled(context) || TextSecurePreferences.isScreenLockEnabled(context); + PreferenceStorage preferenceStorage = ApplicationContext.getInstance(context).getPreferenceStorage().get(); + boolean enabled = !preferenceStorage.get(SecurityPreferences.PASSWORD_DISABLED) || preferenceStorage.get(SecurityPreferences.SCREEN_LOCK); return getMasterSecret(context) == null && enabled; } @@ -158,7 +167,8 @@ public void onCreate() { Log.i(TAG, "onCreate()"); super.onCreate(); - if (TextSecurePreferences.isPasswordDisabled(this) && !TextSecurePreferences.isScreenLockEnabled(this)) { + PreferenceStorage preferenceStorage = ApplicationContext.getInstance(this).getPreferenceStorage().get(); + if (preferenceStorage.get(SecurityPreferences.PASSWORD_DISABLED) && !preferenceStorage.get(SecurityPreferences.SCREEN_LOCK)) { setMasterSecret(new Object()); } } @@ -210,19 +220,20 @@ private static void startTimeoutIfAppropriate(@NonNull Context context) { boolean appVisible = ApplicationContext.getInstance(context).isAppVisible(); boolean secretSet = KeyCachingService.masterSecret != null; - boolean timeoutEnabled = TextSecurePreferences.isPassphraseTimeoutEnabled(context); - boolean passLockActive = timeoutEnabled && !TextSecurePreferences.isPasswordDisabled(context); + PreferenceStorage preferenceStorage = ApplicationContext.getInstance(context).getPreferenceStorage().get(); + boolean timeoutEnabled = preferenceStorage.get(SecurityPreferences.PASSPHRASE_TIMEOUT_ENABLED); + boolean passLockActive = timeoutEnabled && !preferenceStorage.get(SecurityPreferences.PASSWORD_DISABLED); - long screenTimeout = TextSecurePreferences.getScreenLockTimeout(context); - boolean screenLockActive = screenTimeout >= 0 && TextSecurePreferences.isScreenLockEnabled(context); + long screenTimeout = preferenceStorage.get(SecurityPreferences.SCREEN_LOCK_TIMEOUT); + boolean screenLockActive = screenTimeout >= 0 && preferenceStorage.get(SecurityPreferences.SCREEN_LOCK); if (!appVisible && secretSet && (passLockActive || screenLockActive)) { - long passphraseTimeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(context); - long screenLockTimeoutSeconds = TextSecurePreferences.getScreenLockTimeout(context); + long passphraseTimeoutMinutes = preferenceStorage.get(SecurityPreferences.PASSPHRASE_TIMEOUT_INTERVAL); + long screenLockTimeoutSeconds = preferenceStorage.get(SecurityPreferences.SCREEN_LOCK_TIMEOUT); long timeoutMillis; - if (!TextSecurePreferences.isPasswordDisabled(context)) timeoutMillis = TimeUnit.MINUTES.toMillis(passphraseTimeoutMinutes); + if (!preferenceStorage.get(SecurityPreferences.PASSWORD_DISABLED)) timeoutMillis = TimeUnit.MINUTES.toMillis(passphraseTimeoutMinutes); else timeoutMillis = TimeUnit.SECONDS.toMillis(screenLockTimeoutSeconds); Log.i(TAG, "Starting timeout: " + timeoutMillis); @@ -236,7 +247,8 @@ private static void startTimeoutIfAppropriate(@NonNull Context context) { } private void foregroundService() { - if (TextSecurePreferences.isPasswordDisabled(this) && !TextSecurePreferences.isScreenLockEnabled(this)) { + PreferenceStorage preferenceStorage = ApplicationContext.getInstance(this).getPreferenceStorage().get(); + if (preferenceStorage.get(SecurityPreferences.PASSWORD_DISABLED) && !preferenceStorage.get(SecurityPreferences.SCREEN_LOCK)) { stopForeground(true); return; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/PanicResponderListener.java b/app/src/main/java/org/thoughtcrime/securesms/service/PanicResponderListener.java index a23544d570..1028c06ff7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/PanicResponderListener.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/PanicResponderListener.java @@ -6,6 +6,10 @@ import android.os.Build; import org.session.libsession.utilities.TextSecurePreferences; +import org.thoughtcrime.securesms.dependencies.AppComponent; +import dagger.hilt.EntryPoints; +import org.thoughtcrime.securesms.preferences.PreferenceStorage; +import org.thoughtcrime.securesms.preferences.SecurityPreferences; /** * Respond to a PanicKit trigger Intent by locking the app. PanicKit provides a @@ -18,7 +22,8 @@ public class PanicResponderListener extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - if (intent != null && !TextSecurePreferences.isPasswordDisabled(context) && + PreferenceStorage preferenceStorage = org.thoughtcrime.securesms.ApplicationContext.getInstance(context).getPreferenceStorage().get(); + if (intent != null && !preferenceStorage.get(SecurityPreferences.PASSWORD_DISABLED) && "info.guardianproject.panic.action.TRIGGER".equals(intent.getAction())) { Intent lockIntent = new Intent(context, KeyCachingService.class); diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ReadReceiptManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ReadReceiptManager.kt index 599ef2041c..a9fa2bdf21 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ReadReceiptManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ReadReceiptManager.kt @@ -2,7 +2,8 @@ package org.thoughtcrime.securesms.sskenvironment import org.session.libsession.utilities.Address import org.session.libsession.utilities.SSKEnvironment -import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.PrivacyPreferences import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId import org.thoughtcrime.securesms.database.MmsSmsDatabase @@ -11,7 +12,7 @@ import javax.inject.Singleton @Singleton class ReadReceiptManager @Inject constructor( - private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val mmsSmsDatabase: MmsSmsDatabase, ): SSKEnvironment.ReadReceiptManagerProtocol { @@ -20,7 +21,7 @@ class ReadReceiptManager @Inject constructor( sentTimestamps: List, readTimestamp: Long ) { - if (textSecurePreferences.isReadReceiptsEnabled()) { + if (preferenceStorage[PrivacyPreferences.READ_RECEIPTS]) { // Redirect message to master device conversation var address = Address.fromSerialized(fromRecipientId) diff --git a/app/src/main/java/org/thoughtcrime/securesms/tokenpage/TokenDropNotificationWorker.kt b/app/src/main/java/org/thoughtcrime/securesms/tokenpage/TokenDropNotificationWorker.kt index 4741c9555e..167f01c188 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/tokenpage/TokenDropNotificationWorker.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/tokenpage/TokenDropNotificationWorker.kt @@ -23,6 +23,8 @@ import org.session.libsession.utilities.StringSubstitutionConstants.NETWORK_NAME import org.session.libsession.utilities.StringSubstitutionConstants.TOKEN_NAME_LONG_KEY import org.session.libsession.utilities.TextSecurePreferences import org.thoughtcrime.securesms.home.HomeActivity +import org.thoughtcrime.securesms.preferences.NotificationPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.thoughtcrime.securesms.preferences.SettingsActivity @HiltWorker @@ -30,7 +32,8 @@ class TokenDropNotificationWorker @AssistedInject constructor( @Assisted private val context: Context, @Assisted private val workerParams: WorkerParameters, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val tokenDataManager: TokenDataManager ) : CoroutineWorker(context, workerParams) { @@ -41,7 +44,7 @@ class TokenDropNotificationWorker override suspend fun doWork(): Result { val isDebugNotification = workerParams.tags.contains(TokenPageNotificationManager.debugNotificationWorkName) - val alreadyShownTokenPageNotification = prefs.hasSeenTokenPageNotification() + val alreadyShownTokenPageNotification = preferenceStorage[NotificationPreferences.HAVE_SHOWN_TOKEN_PAGE_NOTIFICATION] tokenDataManager.fetchInfoDataIfNeeded() @@ -132,7 +135,7 @@ class TokenDropNotificationWorker // Update our preference data to indicate we've now shown the notification if this isn't a debug / test notification if (!isDebugNotification) { - prefs.setHasSeenTokenPageNotification(true) + preferenceStorage[NotificationPreferences.HAVE_SHOWN_TOKEN_PAGE_NOTIFICATION] = true } return Result.success() diff --git a/app/src/main/java/org/thoughtcrime/securesms/tokenpage/TokenPageNotificationManager.kt b/app/src/main/java/org/thoughtcrime/securesms/tokenpage/TokenPageNotificationManager.kt index 78822c41eb..623a30e726 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/tokenpage/TokenPageNotificationManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/tokenpage/TokenPageNotificationManager.kt @@ -7,6 +7,8 @@ import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager import dagger.hilt.android.qualifiers.ApplicationContext import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.NotificationPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Singleton @@ -17,7 +19,8 @@ import kotlin.time.Duration.Companion.seconds class TokenPageNotificationManager @Inject constructor( @ApplicationContext private val context: Context, private val tokenDataManager: TokenDataManager, - private val prefs: TextSecurePreferences + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage ) { companion object { @@ -32,7 +35,7 @@ class TokenPageNotificationManager @Inject constructor( // the notification once - which is what we want for production. fun scheduleTokenPageNotification(constructDebugNotification: Boolean) { // Bail early if we are this isn't a debug notification and we've already shown the notification - if (prefs.hasSeenTokenPageNotification() && !constructDebugNotification) return + if (preferenceStorage[NotificationPreferences.HAVE_SHOWN_TOKEN_PAGE_NOTIFICATION] && !constructDebugNotification) return // The notification is scheduled for 10 seconds after opening for debug notifications & 1 hour after opening for production val scheduleDelayMS = if (constructDebugNotification) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/theme/ThemeFromPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/theme/ThemeFromPreferences.kt index 326c2d8d49..5bbb5a0080 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/theme/ThemeFromPreferences.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/theme/ThemeFromPreferences.kt @@ -8,6 +8,8 @@ import org.session.libsession.utilities.TextSecurePreferences.Companion.PINK_ACC import org.session.libsession.utilities.TextSecurePreferences.Companion.PURPLE_ACCENT import org.session.libsession.utilities.TextSecurePreferences.Companion.RED_ACCENT import org.session.libsession.utilities.TextSecurePreferences.Companion.YELLOW_ACCENT +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ThemingPreferences /** @@ -15,11 +17,11 @@ import org.session.libsession.utilities.TextSecurePreferences.Companion.YELLOW_A * Some behaviour is hardcoded to cater for legacy usage of people with themes already set * But future themes will be picked and set directly from the "Appearance" screen */ -fun TextSecurePreferences.getColorsProvider(): ThemeColorsProvider { - val selectedTheme = getThemeStyle() +fun getColorsProvider(textSecurePreferences: TextSecurePreferences, preferenceStorage: PreferenceStorage): ThemeColorsProvider { + val selectedTheme = textSecurePreferences.getThemeStyle() // get the chosen accent color from the preferences - val selectedAccent = accentColor() + val selectedAccent = accentColor(preferenceStorage) val isOcean = "ocean" in selectedTheme @@ -27,7 +29,7 @@ fun TextSecurePreferences.getColorsProvider(): ThemeColorsProvider { val createDark = if (isOcean) ::OceanDark else ::ClassicDark return when { - getFollowSystemSettings() -> FollowSystemThemeColorsProvider( + textSecurePreferences.getFollowSystemSettings() -> FollowSystemThemeColorsProvider( light = createLight(selectedAccent), dark = createDark(selectedAccent) ) @@ -36,7 +38,7 @@ fun TextSecurePreferences.getColorsProvider(): ThemeColorsProvider { } } -fun TextSecurePreferences.accentColor(): Color = when(getSelectedAccentColor()) { +fun accentColor(preferenceStorage: PreferenceStorage): Color = when(preferenceStorage[ThemingPreferences.SELECTED_ACCENT_COLOR]) { BLUE_ACCENT -> primaryBlue PURPLE_ACCENT -> primaryPurple PINK_ACCENT -> primaryPink diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/theme/Themes.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/theme/Themes.kt index aa2ef6f7cc..43caff823b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/theme/Themes.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/theme/Themes.kt @@ -18,6 +18,7 @@ import androidx.compose.ui.unit.dp import org.session.libsession.utilities.AppTextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences import org.thoughtcrime.securesms.ApplicationContext +import org.thoughtcrime.securesms.preferences.PreferenceStorage // Globally accessible composition local objects val LocalColors = staticCompositionLocalOf { ClassicDark() } @@ -37,9 +38,11 @@ fun invalidateComposeThemeColors() { fun SessionMaterialTheme( preferences: TextSecurePreferences = (LocalContext.current.applicationContext as ApplicationContext).textSecurePreferences.get(), + preferenceStorage: PreferenceStorage = + (LocalContext.current.applicationContext as ApplicationContext).preferenceStorage.get(), content: @Composable () -> Unit ) { - val cachedColors = cachedColorsProvider ?: preferences.getColorsProvider().also { cachedColorsProvider = it } + val cachedColors = cachedColorsProvider ?: getColorsProvider(preferences, preferenceStorage).also { cachedColorsProvider = it } SessionMaterialTheme( colors = cachedColors.get(), diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/DonationManager.kt b/app/src/main/java/org/thoughtcrime/securesms/util/DonationManager.kt index e9ac3fbf4b..db2757d3e2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/DonationManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/DonationManager.kt @@ -3,8 +3,9 @@ package org.thoughtcrime.securesms.util import android.content.Context import dagger.hilt.android.qualifiers.ApplicationContext import org.session.libsession.utilities.TextSecurePreferences -import org.thoughtcrime.securesms.debugmenu.DebugMenuViewModel.Companion.SEEN_1 import org.thoughtcrime.securesms.debugmenu.DebugMenuViewModel.Companion.TRUE +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.SystemPreferences import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Singleton @@ -12,7 +13,8 @@ import javax.inject.Singleton @Singleton class DonationManager @Inject constructor( @param:ApplicationContext val context: Context, - val prefs: TextSecurePreferences + val textSecurePreferences: TextSecurePreferences, + val preferenceStorage: PreferenceStorage ){ companion object { const val URL_DONATE = "https://getsession.org/donate#app" @@ -34,7 +36,7 @@ class DonationManager @Inject constructor( // if we gave a positive review and never donated, then show the donate CTA if(getShowFromReview()) { - prefs.setShowDonationCTAFromPositiveReview(false) // reset flag + preferenceStorage[SystemPreferences.SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW] = false // reset flag return true } @@ -42,7 +44,7 @@ class DonationManager @Inject constructor( // the comparison point is either the last time the CTA was seen, // or if it was never seen we check the app's install date val comparisonDate = if(seenAmount > 0) - prefs.lastSeenDonationCTA() + preferenceStorage[SystemPreferences.LAST_SEEN_DONATION_CTA] else context.packageManager.getPackageInfo(context.packageName, 0).firstInstallTime @@ -55,53 +57,53 @@ class DonationManager @Inject constructor( fun onDonationCTAViewed(){ // increment seen amount - prefs.setSeenDonationCTAAmount(prefs.seenDonationCTAAmount() + 1) + preferenceStorage[SystemPreferences.SEEN_DONATION_CTA_AMOUNT] = preferenceStorage[SystemPreferences.SEEN_DONATION_CTA_AMOUNT] + 1 // set seen time - prefs.setLastSeenDonationCTA(System.currentTimeMillis()) + preferenceStorage[SystemPreferences.LAST_SEEN_DONATION_CTA] = System.currentTimeMillis() } fun onDonationSeen(){ - prefs.setHasDonated(true) + preferenceStorage[SystemPreferences.HAS_DONATED] = true } fun onDonationCopied(){ - prefs.setHasCopiedDonationURL(true) + preferenceStorage[SystemPreferences.HAS_COPIED_DONATION_URL] = true } private fun getHasDonated(): Boolean{ - val debug = prefs.hasDonatedDebug() + val debug = textSecurePreferences.hasDonatedDebug() return if(debug != null){ when(debug){ TRUE -> true else -> false } - } else prefs.hasDonated() + } else preferenceStorage[SystemPreferences.HAS_DONATED] } private fun getHasCopiedLink(): Boolean{ - val debug = prefs.hasCopiedDonationURLDebug() + val debug = textSecurePreferences.hasCopiedDonationURLDebug() return if(debug != null){ when(debug){ TRUE -> true else -> false } - } else prefs.hasCopiedDonationURL() + } else preferenceStorage[SystemPreferences.HAS_COPIED_DONATION_URL] } private fun getSeenCTAAmount(): Int{ - val debug = prefs.seenDonationCTAAmountDebug() + val debug = textSecurePreferences.seenDonationCTAAmountDebug() return if(debug != null){ debug.toInt() - } else prefs.seenDonationCTAAmount() + } else preferenceStorage[SystemPreferences.SEEN_DONATION_CTA_AMOUNT] } private fun getShowFromReview(): Boolean{ - val debug = prefs.showDonationCTAFromPositiveReviewDebug() + val debug = textSecurePreferences.showDonationCTAFromPositiveReviewDebug() return if(debug != null){ when(debug){ TRUE -> true else -> false } - } else prefs.showDonationCTAFromPositiveReview() + } else preferenceStorage[SystemPreferences.SHOW_DONATION_CTA_FROM_POSITIVE_REVIEW] } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt b/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt index 5d65638002..be3ebaeb40 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt @@ -17,6 +17,9 @@ import java.lang.ref.WeakReference import java.util.concurrent.TimeUnit import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.dependencies.AppComponent +import dagger.hilt.EntryPoints +import org.thoughtcrime.securesms.preferences.PrivacyPreferences import org.session.libsession.utilities.task.ProgressDialogAsyncTask import org.session.libsignal.utilities.ExternalStorageUtil import org.session.libsignal.utilities.Log @@ -47,7 +50,8 @@ class SaveAttachmentTask @JvmOverloads constructor(context: Context, count: Int fun showOneTimeWarningDialogOrSave(context: Context, count: Int = 1, onAcceptListener: () -> Unit = {}) { // If we've already warned the user that saved attachments can be accessed by other apps // then we'll just perform the save.. - val haveWarned = TextSecurePreferences.getHaveWarnedUserAboutSavingAttachments(context) + val preferenceStorage = EntryPoints.get(context.applicationContext, AppComponent::class.java).getPreferenceStorage() + val haveWarned = preferenceStorage[PrivacyPreferences.HAVE_WARNED_USER_ABOUT_SAVING_ATTACHMENTS] if (haveWarned) { onAcceptListener() } else { @@ -58,7 +62,7 @@ class SaveAttachmentTask @JvmOverloads constructor(context: Context, count: Int text(context.getString(R.string.attachmentsWarning)) dangerButton(R.string.save) { // Set our 'haveWarned' SharedPref and perform the save on accept - TextSecurePreferences.setHaveWarnedUserAboutSavingAttachments(context) + preferenceStorage[PrivacyPreferences.HAVE_WARNED_USER_ABOUT_SAVING_ATTACHMENTS] = true onAcceptListener() } button(R.string.cancel) diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallMessageProcessor.kt index 0f4e461a2b..2e4ef010b1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallMessageProcessor.kt @@ -9,7 +9,8 @@ import org.session.libsession.messaging.messages.control.CallMessage import org.session.libsession.messaging.utilities.WebRtcUtils import org.session.libsession.network.SnodeClock import org.session.libsession.utilities.Address -import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.NotificationPreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage import org.session.libsignal.utilities.Log import org.session.protos.SessionProtos.CallMessage.Type.ANSWER import org.session.protos.SessionProtos.CallMessage.Type.END_CALL @@ -28,7 +29,7 @@ import javax.inject.Singleton @Singleton class CallMessageProcessor @Inject constructor( @param:ApplicationContext private val context: Context, - private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val storage: StorageProtocol, private val webRtcBridge: WebRtcCallBridge, private val recipientRepository: RecipientRepository, @@ -51,7 +52,7 @@ class CallMessageProcessor @Inject constructor( // If the user has not enabled voice/video calls or if the user has not granted audio/microphone permissions if ( - !textSecurePreferences.isCallNotificationsEnabled() || + !preferenceStorage[NotificationPreferences.CALL_NOTIFICATIONS_ENABLED] || !Permissions.hasAll(context, Manifest.permission.RECORD_AUDIO) ) { Log.d("Loki","Dropping call message if call notifications disabled") diff --git a/app/src/play/kotlin/org/thoughtcrime/securesms/pro/subscription/PlayStoreSubscriptionManager.kt b/app/src/play/kotlin/org/thoughtcrime/securesms/pro/subscription/PlayStoreSubscriptionManager.kt index 3b1e0ae088..680e976334 100644 --- a/app/src/play/kotlin/org/thoughtcrime/securesms/pro/subscription/PlayStoreSubscriptionManager.kt +++ b/app/src/play/kotlin/org/thoughtcrime/securesms/pro/subscription/PlayStoreSubscriptionManager.kt @@ -28,6 +28,8 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.PreferenceStorage +import org.thoughtcrime.securesms.preferences.ProPreferences import org.session.libsignal.utilities.Hex import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.auth.LoginStateRepository @@ -45,7 +47,8 @@ import javax.inject.Singleton class PlayStoreSubscriptionManager @Inject constructor( private val application: Application, private val currentActivityObserver: CurrentActivityObserver, - private val prefs: TextSecurePreferences, + private val textSecurePreferences: TextSecurePreferences, + private val preferenceStorage: PreferenceStorage, private val loginStateRepository: LoginStateRepository, proStatusManager: ProStatusManager, @param:ManagerScope scope: CoroutineScope, @@ -61,9 +64,7 @@ class PlayStoreSubscriptionManager @Inject constructor( // generic billing support method. Uses the property above and also checks the debug pref override val supportsBilling: StateFlow = combine( _playBillingAvailable, - (TextSecurePreferences.events.filter { it == TextSecurePreferences.DEBUG_FORCE_NO_BILLING } as Flow<*>) - .onStart { emit(Unit) } - .map { prefs.getDebugForceNoBilling() }, + preferenceStorage.watch(scope, ProPreferences.DEBUG_FORCE_NO_BILLING), ){ available, forceNoBilling -> !forceNoBilling && available } @@ -280,7 +281,7 @@ class PlayStoreSubscriptionManager @Inject constructor( override suspend fun hasValidSubscription(): Boolean { // if in debug mode, always return true - return if(prefs.forceCurrentUserAsPro()) true + return if(preferenceStorage[ProPreferences.FORCE_CURRENT_USER_AS_PRO]) true else getExistingSubscription() != null }