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 c6a5eb026d..e62cde1857 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -8,7 +8,6 @@ import android.content.Context import android.content.Intent import android.os.Build import android.os.Bundle -import android.provider.Telephony.Mms.Addr import android.widget.Toast import androidx.activity.viewModels import androidx.core.os.bundleOf @@ -21,7 +20,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -185,9 +183,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), // subscribe to outdated config updates, this should be removed after long enough time for device migration lifecycleScope.launch { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { - TextSecurePreferences.events.filter { it == TextSecurePreferences.HAS_RECEIVED_LEGACY_CONFIG.name }.collect { - updateLegacyConfigView() - } + prefs.hasLegacyConfigFlow().collect(::updateLegacyConfigView) } } @@ -224,10 +220,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), } withContext(Dispatchers.Main) { - updateProfileButton() - TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF.name }.collect { - updateProfileButton() - } + prefs.profileNameFlow().collect(::updateProfileButton) } } @@ -330,8 +323,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), binding.newConversationButton.isVisible = !isShown } - private fun updateLegacyConfigView() { - binding.configOutdatedView.isVisible = textSecurePreferences.getHasLegacyConfig() + private fun updateLegacyConfigView(hasLegacyConfig: Boolean = textSecurePreferences.getHasLegacyConfig()) { + binding.configOutdatedView.isVisible = hasLegacyConfig } override fun onResume() { @@ -382,9 +375,9 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), } } - private fun updateProfileButton() { + private fun updateProfileButton(profileName: String? = textSecurePreferences.getProfileName()) { binding.profileButton.publicKey = publicKey - binding.profileButton.displayName = textSecurePreferences.getProfileName() + binding.profileButton.displayName = profileName binding.profileButton.recycle() binding.profileButton.update() } 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 cbad1f976e..ac71682480 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt @@ -16,7 +16,6 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest @@ -60,11 +59,6 @@ class HomeViewModel @Inject constructor( ::Data ).stateIn(viewModelScope, SharingStarted.Eagerly, null) - private fun hasHiddenMessageRequests() = TextSecurePreferences.events - .filter { it == TextSecurePreferences.HAS_HIDDEN_MESSAGE_REQUESTS.name } - .map { prefs.hasHiddenMessageRequests() } - .onStart { emit(prefs.hasHiddenMessageRequests()) } - private fun observeTypingStatus(): Flow> = ApplicationContext.getInstance(context).typingStatusRepository .typingThreads @@ -74,7 +68,7 @@ class HomeViewModel @Inject constructor( private fun messageRequests() = combine( unapprovedConversationCount(), - hasHiddenMessageRequests(), + prefs.hasHiddenMessageRequestsFlow(), latestUnapprovedConversationTimestamp(), ::createMessageRequests ).flowOn(Dispatchers.IO) diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingViewModel.kt index 28d11f1d7a..046154b750 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingViewModel.kt @@ -12,8 +12,6 @@ import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.timeout import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -44,10 +42,8 @@ internal class LoadingViewModel @Inject constructor( init { viewModelScope.launch(Dispatchers.IO) { try { - TextSecurePreferences.events - .filter { it == TextSecurePreferences.CONFIGURATION_SYNCED.name } - .onStart { emit(TextSecurePreferences.CONFIGURATION_SYNCED.name) } - .filter { prefs.getConfigurationMessageSynced() } + prefs.configurationMessageSyncedFlow() + .filter { it } .timeout(TIMEOUT_TIME) .collectLatest { onSuccess() } } catch (e: Exception) { diff --git a/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt b/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt index 34d236b3ca..6f81d1c22b 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt @@ -2,6 +2,7 @@ package org.session.libsession.utilities import android.content.Context import android.content.SharedPreferences +import android.content.SharedPreferences.OnSharedPreferenceChangeListener import android.hardware.Camera import android.net.Uri import android.provider.Settings @@ -12,9 +13,9 @@ import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceManager.getDefaultSharedPreferences import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow import org.session.libsession.R import org.session.libsession.utilities.TextSecurePreferences.Companion.instance import java.util.Date @@ -42,7 +43,6 @@ fun Pref(name: String, default: String) = Pref(name, default, { _, _ -> getStrin fun Pref(name: String) = Pref(name, null, SharedPreferences::getString, SharedPreferences.Editor::putStringOrRemove) fun Pref(name: String, default: Set) = Pref(name, default, SharedPreferences::getStringSet, SharedPreferences.Editor::putStringSet) - private fun SharedPreferences.Editor.putStringOrRemove(name: String, value: String?) = value?.let { putString(name, it) } ?: run { remove(name) } operator fun SharedPreferences.get(pref: Pref): T = pref.get(this) @@ -76,9 +76,6 @@ class TextSecurePreferences @Inject constructor( var instance: TextSecurePreferences? = null - internal val _events = MutableSharedFlow(0, 64, BufferOverflow.DROP_OLDEST) - val events get() = _events.asSharedFlow() - @JvmStatic var pushSuffix = "" @@ -165,19 +162,26 @@ class TextSecurePreferences @Inject constructor( fun set(pref: Pref, value: T?) = sharedPreferences.set(pref, value) fun remove(pref: Pref) = sharedPreferences.set(pref, null) fun has(pref: Pref) = sharedPreferences.contains(pref.name) + fun flow(pref: Pref) = callbackFlow { + OnSharedPreferenceChangeListener { _, _ -> trySend(sharedPreferences[pref]) }.let { + trySend(sharedPreferences[pref]) + + sharedPreferences.registerOnSharedPreferenceChangeListener(it) + + awaitClose { + sharedPreferences.unregisterOnSharedPreferenceChangeListener(it) + } + } + } fun getConfigurationMessageSynced(): Boolean = sharedPreferences[CONFIGURATION_SYNCED] - - fun setConfigurationMessageSynced(value: Boolean) { - set(CONFIGURATION_SYNCED, value) - _events.tryEmit(CONFIGURATION_SYNCED.name) - } + fun configurationMessageSyncedFlow() = flow(CONFIGURATION_SYNCED) + fun setConfigurationMessageSynced(value: Boolean) = set(CONFIGURATION_SYNCED, value) fun isPushEnabled(): Boolean = sharedPreferences[IS_PUSH_ENABLED] fun setPushEnabled(value: Boolean) = sharedPreferences.set(IS_PUSH_ENABLED, value) fun getPushToken(): String? = sharedPreferences[PUSH_TOKEN] fun setPushToken(value: String) = set(PUSH_TOKEN, value) fun getPushRegisterTime(): Long = sharedPreferences[PUSH_REGISTER_TIME] - fun setPushRegisterTime(value: Long) = set(PUSH_REGISTER_TIME, value) fun isScreenLockEnabled() = sharedPreferences[SCREEN_LOCK] fun setScreenLockEnabled(value: Boolean) = set(SCREEN_LOCK, value) @@ -202,11 +206,9 @@ class TextSecurePreferences @Inject constructor( fun setIsGifSearchInGridLayout(isGrid: Boolean) = set(GIF_GRID_LAYOUT, isGrid) fun getProfileKey(): String? = sharedPreferences[PROFILE_KEY_PREF] fun setProfileKey(key: String?) = set(PROFILE_KEY_PREF, key) - fun setProfileName(name: String?) { - sharedPreferences[PROFILE_NAME_PREF] = name - _events.tryEmit(PROFILE_NAME_PREF.name) - } + fun setProfileName(name: String?) = sharedPreferences.set(PROFILE_NAME_PREF, name) fun getProfileName(): String? = sharedPreferences[PROFILE_NAME_PREF] + fun profileNameFlow() = flow(PROFILE_NAME_PREF) fun setProfileAvatarId(id: Int) = set(PROFILE_AVATAR_ID_PREF, id) fun getProfileAvatarId(): Int = sharedPreferences[PROFILE_AVATAR_ID_PREF] fun setProfilePictureURL(url: String?) = set(PROFILE_AVATAR_URL_PREF, url) @@ -220,10 +222,8 @@ class TextSecurePreferences @Inject constructor( fun setLocalRegistrationId(registrationId: Int) = set(LOCAL_REGISTRATION_ID_PREF, registrationId) fun getLocalNumber(): String? = sharedPreferences[LOCAL_NUMBER_PREF] fun getHasLegacyConfig(): Boolean = sharedPreferences[HAS_RECEIVED_LEGACY_CONFIG] - fun setHasLegacyConfig(newValue: Boolean) { - sharedPreferences[HAS_RECEIVED_LEGACY_CONFIG] = newValue - _events.tryEmit(HAS_RECEIVED_LEGACY_CONFIG.name) - } + fun hasLegacyConfigFlow(): Flow = flow(HAS_RECEIVED_LEGACY_CONFIG) + fun setHasLegacyConfig(newValue: Boolean) = sharedPreferences.set(HAS_RECEIVED_LEGACY_CONFIG, newValue) fun setLocalNumber(localNumber: String) = set(LOCAL_NUMBER_PREF, localNumber.lowercase()) fun isEnterSendsEnabled() = sharedPreferences[ENTER_SENDS_PREF] fun isPasswordDisabled(): Boolean = sharedPreferences[DISABLE_PASSPHRASE_PREF] @@ -278,6 +278,7 @@ class TextSecurePreferences @Inject constructor( } } fun hasHiddenMessageRequests(): Boolean = sharedPreferences[HAS_HIDDEN_MESSAGE_REQUESTS] + fun hasHiddenMessageRequestsFlow() = flow(HAS_HIDDEN_MESSAGE_REQUESTS) fun setHasHiddenMessageRequests() = set(HAS_HIDDEN_MESSAGE_REQUESTS, true) fun removeHasHiddenMessageRequests() = remove(HAS_HIDDEN_MESSAGE_REQUESTS) fun getFingerprintKeyGenerated(): Boolean = sharedPreferences[FINGERPRINT_KEY_GENERATED]