From 182d3f69733a1734b1008f0e408b28df9660ce50 Mon Sep 17 00:00:00 2001 From: bemusementpark Date: Wed, 10 Jul 2024 20:18:11 +0930 Subject: [PATCH] Use semi-type-safe Pref --- .../network/loki/messenger/LibSessionTests.kt | 11 +- .../securesms/BaseActionBarActivity.java | 3 +- .../components/CustomDefaultPreference.java | 261 ----- .../securesms/database/LokiAPIDatabase.kt | 6 +- .../securesms/dependencies/ConfigFactory.kt | 2 - .../securesms/home/HomeActivity.kt | 10 +- .../securesms/home/HomeViewModel.kt | 2 +- .../AbstractNotificationBuilder.java | 2 +- .../notifications/NotificationChannels.java | 2 +- .../loadaccount/LoadAccountActivity.kt | 1 - .../onboarding/loading/LoadingActivity.kt | 2 - .../onboarding/loading/LoadingViewModel.kt | 4 +- .../manager/CreateAccountManager.kt | 1 - .../onboarding/manager/LoadAccountManager.kt | 1 - .../CorrectedPreferenceFragment.java | 18 - .../NotificationsPreferenceFragment.kt | 16 +- .../PrivacySettingsPreferenceFragment.kt | 1 + .../service/UpdateApkReadyListener.java | 122 --- .../utilities/TextSecurePreferences.kt | 968 +++++------------- 19 files changed, 249 insertions(+), 1184 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/CustomDefaultPreference.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkReadyListener.java diff --git a/app/src/androidTest/java/network/loki/messenger/LibSessionTests.kt b/app/src/androidTest/java/network/loki/messenger/LibSessionTests.kt index 9cc76ce7d5..720c9731bc 100644 --- a/app/src/androidTest/java/network/loki/messenger/LibSessionTests.kt +++ b/app/src/androidTest/java/network/loki/messenger/LibSessionTests.kt @@ -27,6 +27,7 @@ import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.snode.SnodeAPI import org.session.libsession.utilities.Address import org.session.libsession.utilities.TextSecurePreferences +import org.session.libsession.utilities.prefs import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.utilities.hexEncodedPublicKey import org.thoughtcrime.securesms.ApplicationContext @@ -82,18 +83,14 @@ class LibSessionTests { @Before fun setupUser() { - PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getInstrumentation().targetContext.applicationContext).edit { - putBoolean(TextSecurePreferences.HAS_FORCED_NEW_CONFIG, true).apply() - } val newBytes = randomSeedBytes().toByteArray() val context = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext val kp = KeyPairUtilities.generate(newBytes) KeyPairUtilities.store(context, kp.seed, kp.ed25519KeyPair, kp.x25519KeyPair) val registrationID = KeyHelper.generateRegistrationId(false) - context.prefs.setLocalRegistrationId(context, registrationID) - context.prefs.setLocalNumber(context, kp.x25519KeyPair.hexEncodedPublicKey) - context.prefs.setRestorationTime(context, 0) - context.prefs.setHasViewedSeed(context, false) + context.prefs.setLocalRegistrationId(registrationID) + context.prefs.setLocalNumber(kp.x25519KeyPair.hexEncodedPublicKey) + context.prefs.setHasViewedSeed(false) } @Test diff --git a/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java b/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java index ef1bb3fae7..76bd7fb2ef 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java @@ -1,7 +1,6 @@ package org.thoughtcrime.securesms; import static android.os.Build.VERSION.SDK_INT; -import static org.session.libsession.utilities.TextSecurePreferences.SELECTED_ACCENT_COLOR; import android.app.ActivityManager; import android.content.Context; @@ -62,7 +61,7 @@ public abstract class BaseActionBarActivity extends AppCompatActivity { @StyleRes @Nullable private Integer getAccentTheme() { - if (!getPreferences().hasPreference(SELECTED_ACCENT_COLOR)) return null; + if (!getPreferences().hasSelectedAccentColor()) return null; ThemeState themeState = ActivityUtilitiesKt.themeState(getPreferences()); return themeState.getAccentStyle(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/CustomDefaultPreference.java b/app/src/main/java/org/thoughtcrime/securesms/components/CustomDefaultPreference.java deleted file mode 100644 index 5a1d2b4bee..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/components/CustomDefaultPreference.java +++ /dev/null @@ -1,261 +0,0 @@ -package org.thoughtcrime.securesms.components; - -import android.app.Dialog; -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; -import androidx.preference.DialogPreference; -import androidx.preference.PreferenceDialogFragmentCompat; -import android.text.Editable; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.AttributeSet; - -import org.session.libsession.messaging.MessagingModuleConfiguration; -import org.session.libsignal.utilities.Log; -import android.view.View; -import android.widget.AdapterView; -import android.widget.Button; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.TextView; - -import network.loki.messenger.R; -import org.thoughtcrime.securesms.components.CustomDefaultPreference.CustomDefaultPreferenceDialogFragmentCompat.CustomPreferenceValidator; -import org.session.libsession.utilities.TextSecurePreferences; - -import java.net.URI; -import java.net.URISyntaxException; - - -public class CustomDefaultPreference extends DialogPreference { - - private static final String TAG = CustomDefaultPreference.class.getSimpleName(); - - private final int inputType; - private final String customPreference; - private final String customToggle; - - private CustomPreferenceValidator validator; - private String defaultValue; - - public CustomDefaultPreference(Context context, AttributeSet attrs) { - super(context, attrs); - - int[] attributeNames = new int[]{android.R.attr.inputType, R.attr.custom_pref_toggle}; - TypedArray attributes = context.obtainStyledAttributes(attrs, attributeNames); - - this.inputType = attributes.getInt(0, 0); - this.customPreference = getKey(); - this.customToggle = attributes.getString(1); - this.validator = new CustomDefaultPreferenceDialogFragmentCompat.NullValidator(); - - attributes.recycle(); - - setPersistent(false); - setDialogLayoutResource(R.layout.custom_default_preference_dialog); - } - - public CustomDefaultPreference setValidator(CustomPreferenceValidator validator) { - this.validator = validator; - return this; - } - - public CustomDefaultPreference setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - this.setSummary(getSummary()); - return this; - } - - @Override - public String getSummary() { - if (isCustom()) { - return getContext().getString(R.string.CustomDefaultPreference_using_custom, - getPrettyPrintValue(getCustomValue())); - } else { - return getContext().getString(R.string.CustomDefaultPreference_using_default, - getPrettyPrintValue(getDefaultValue())); - } - } - - private String getPrettyPrintValue(String value) { - if (TextUtils.isEmpty(value)) return getContext().getString(R.string.CustomDefaultPreference_none); - else return value; - } - - private boolean isCustom() { - return MessagingModuleConfiguration.getShared().getPrefs().getBooleanPreference(customToggle, false); - } - - private void setCustom(boolean custom) { - MessagingModuleConfiguration.getShared().getPrefs().setBooleanPreference(customToggle, custom); - } - - private String getCustomValue() { - return MessagingModuleConfiguration.getShared().getPrefs().getStringPreference(customPreference, ""); - } - - private void setCustomValue(String value) { - MessagingModuleConfiguration.getShared().getPrefs().setStringPreference(customPreference, value); - } - - private String getDefaultValue() { - return defaultValue; - } - - - public static class CustomDefaultPreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat { - - private static final String INPUT_TYPE = "input_type"; - - private Spinner spinner; - private EditText customText; - private TextView defaultLabel; - - public static CustomDefaultPreferenceDialogFragmentCompat newInstance(String key) { - CustomDefaultPreferenceDialogFragmentCompat fragment = new CustomDefaultPreferenceDialogFragmentCompat(); - Bundle b = new Bundle(1); - b.putString(PreferenceDialogFragmentCompat.ARG_KEY, key); - fragment.setArguments(b); - return fragment; - } - - @Override - protected void onBindDialogView(@NonNull View view) { - Log.i(TAG, "onBindDialogView"); - super.onBindDialogView(view); - - CustomDefaultPreference preference = (CustomDefaultPreference)getPreference(); - - this.spinner = (Spinner) view.findViewById(R.id.default_or_custom); - this.defaultLabel = (TextView) view.findViewById(R.id.default_label); - this.customText = (EditText) view.findViewById(R.id.custom_edit); - - this.customText.setInputType(preference.inputType); - this.customText.addTextChangedListener(new TextValidator()); - this.customText.setText(preference.getCustomValue()); - this.spinner.setOnItemSelectedListener(new SelectionLister()); - this.defaultLabel.setText(preference.getPrettyPrintValue(preference.defaultValue)); - } - - - @Override - public @NonNull Dialog onCreateDialog(Bundle instanceState) { - Dialog dialog = super.onCreateDialog(instanceState); - - CustomDefaultPreference preference = (CustomDefaultPreference)getPreference(); - - if (preference.isCustom()) spinner.setSelection(1, true); - else spinner.setSelection(0, true); - - return dialog; - } - - @Override - public void onDialogClosed(boolean positiveResult) { - CustomDefaultPreference preference = (CustomDefaultPreference)getPreference(); - - if (positiveResult) { - if (spinner != null) preference.setCustom(spinner.getSelectedItemPosition() == 1); - if (customText != null) preference.setCustomValue(customText.getText().toString()); - - preference.setSummary(preference.getSummary()); - } - } - - interface CustomPreferenceValidator { - public boolean isValid(String value); - } - - private static class NullValidator implements CustomPreferenceValidator { - @Override - public boolean isValid(String value) { - return true; - } - } - - private class TextValidator implements TextWatcher { - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - CustomDefaultPreference preference = (CustomDefaultPreference)getPreference(); - - if (spinner.getSelectedItemPosition() == 1) { - Button positiveButton = ((AlertDialog)getDialog()).getButton(AlertDialog.BUTTON_POSITIVE); - positiveButton.setEnabled(preference.validator.isValid(s.toString())); - } - } - } - - public static class UriValidator implements CustomPreferenceValidator { - @Override - public boolean isValid(String value) { - if (TextUtils.isEmpty(value)) return true; - - try { - new URI(value); - return true; - } catch (URISyntaxException mue) { - return false; - } - } - } - - public static class HostnameValidator implements CustomPreferenceValidator { - @Override - public boolean isValid(String value) { - if (TextUtils.isEmpty(value)) return true; - - try { - URI uri = new URI(null, value, null, null); - return true; - } catch (URISyntaxException mue) { - return false; - } - } - } - - public static class PortValidator implements CustomPreferenceValidator { - @Override - public boolean isValid(String value) { - try { - Integer.parseInt(value); - return true; - } catch (NumberFormatException e) { - return false; - } - } - } - - private class SelectionLister implements AdapterView.OnItemSelectedListener { - - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - CustomDefaultPreference preference = (CustomDefaultPreference)getPreference(); - Button positiveButton = ((AlertDialog)getDialog()).getButton(AlertDialog.BUTTON_POSITIVE); - - defaultLabel.setVisibility(position == 0 ? View.VISIBLE : View.GONE); - customText.setVisibility(position == 0 ? View.GONE : View.VISIBLE); - positiveButton.setEnabled(position == 0 || preference.validator.isValid(customText.getText().toString())); - } - - @Override - public void onNothingSelected(AdapterView parent) { - defaultLabel.setVisibility(View.VISIBLE); - customText.setVisibility(View.GONE); - } - } - - } - - - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/LokiAPIDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/LokiAPIDatabase.kt index 8c58abcaa1..01b2e9a6e5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/LokiAPIDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/LokiAPIDatabase.kt @@ -480,11 +480,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database( database.insertOrUpdate(openGroupPublicKeyTable, row, "${LokiAPIDatabase.server} = ?", wrap(server)) } - override fun getLastSnodePoolRefreshDate(): Date? { - val time = context.prefs.getLastSnodePoolRefreshDate() - if (time <= 0) { return null } - return Date(time) - } + override fun getLastSnodePoolRefreshDate(): Date? = context.prefs.getLastSnodePoolRefreshDate().takeIf { it > 0 }?.let(::Date) override fun setLastSnodePoolRefreshDate(date: Date) { context.prefs.setLastSnodePoolRefreshDate(date) diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt index be70c88a7b..281162010c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt @@ -51,8 +51,6 @@ class ConfigFactory( private val userGroupsLock = Object() private var _userGroups: UserGroupsConfig? = null - private val isConfigForcedOn by lazy { context.prefs.hasForcedNewConfig() } - private val listeners: MutableList = mutableListOf() fun registerListener(listener: ConfigFactoryUpdateListener) { listeners += listener 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 cd453b5534..c6a5eb026d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -156,7 +156,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), // Set up seed reminder view lifecycleScope.launchWhenStarted { binding.seedReminderView.setThemedContent { - if (!textSecurePreferences.getHasViewedSeed()) SeedReminder { start() } + if (!textSecurePreferences.hasViewedSeed()) SeedReminder { start() } } } // Set up recycler view @@ -185,7 +185,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 }.collect { + TextSecurePreferences.events.filter { it == TextSecurePreferences.HAS_RECEIVED_LEGACY_CONFIG.name }.collect { updateLegacyConfigView() } } @@ -225,7 +225,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), withContext(Dispatchers.Main) { updateProfileButton() - TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF }.collect { + TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF.name }.collect { updateProfileButton() } } @@ -325,7 +325,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), binding.sessionToolbar.isVisible = !isShown binding.recyclerView.isVisible = !isShown binding.emptyStateContainer.isVisible = (binding.recyclerView.adapter as HomeAdapter).itemCount == 0 && binding.recyclerView.isVisible - binding.seedReminderView.isVisible = !prefs.getHasViewedSeed() && !isShown + binding.seedReminderView.isVisible = !prefs.hasViewedSeed() && !isShown binding.globalSearchRecycler.isInvisible = !isShown binding.newConversationButton.isVisible = !isShown } @@ -341,7 +341,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), IdentityKeyUtil.checkUpdate(this) binding.profileButton.recycle() // clear cached image before update tje profilePictureView binding.profileButton.update() - if (textSecurePreferences.getHasViewedSeed()) { + if (textSecurePreferences.hasViewedSeed()) { binding.seedReminderView.isVisible = false } 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 dd6d24cd00..cbad1f976e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt @@ -61,7 +61,7 @@ class HomeViewModel @Inject constructor( ).stateIn(viewModelScope, SharingStarted.Eagerly, null) private fun hasHiddenMessageRequests() = TextSecurePreferences.events - .filter { it == TextSecurePreferences.HAS_HIDDEN_MESSAGE_REQUESTS } + .filter { it == TextSecurePreferences.HAS_HIDDEN_MESSAGE_REQUESTS.name } .map { prefs.hasHiddenMessageRequests() } .onStart { emit(prefs.hasHiddenMessageRequests()) } 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 b078a5ca15..ac8efaddfa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java @@ -51,7 +51,7 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui } public void setAlarms(@Nullable Uri ringtone, VibrateState vibrate) { - Uri defaultRingtone = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context) : MessagingModuleConfiguration.getShared().getPrefs().getNotificationRingtone(); + Uri defaultRingtone = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context) : MessagingModuleConfiguration.getShared().getPrefs().getNotificationRingtoneUri(); boolean defaultVibrate = NotificationChannels.supported() ? NotificationChannels.getMessageVibrate(context) : MessagingModuleConfiguration.getShared().getPrefs().isNotificationVibrateEnabled(); if (ringtone == null && !TextUtils.isEmpty(defaultRingtone.toString())) setSound(defaultRingtone); 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 a9a9e061d5..1ea2c95cb3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java @@ -436,7 +436,7 @@ public class NotificationChannels { messages.setGroup(CATEGORY_MESSAGES); messages.enableVibration(MessagingModuleConfiguration.getShared().getPrefs().isNotificationVibrateEnabled()); - messages.setSound(MessagingModuleConfiguration.getShared().getPrefs().getNotificationRingtone(), getRingtoneAudioAttributes()); + messages.setSound(MessagingModuleConfiguration.getShared().getPrefs().getNotificationRingtoneUri(), getRingtoneAudioAttributes()); setLedPreference(messages, MessagingModuleConfiguration.getShared().getPrefs().getNotificationLedColor()); calls.setShowBadge(false); 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 3c7a6f6a56..2bc3fb7831 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 @@ -30,7 +30,6 @@ class LoadAccountActivity : BaseActionBarActivity() { super.onCreate(savedInstanceState) supportActionBar?.setTitle(R.string.activity_link_load_account) prefs.setConfigurationMessageSynced(false) - prefs.setRestorationTime(System.currentTimeMillis()) prefs.setLastProfileUpdateTime(0) lifecycleScope.launch { diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingActivity.kt index 0b76dd829d..7788bf3b46 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/loading/LoadingActivity.kt @@ -29,8 +29,6 @@ class LoadingActivity: BaseActionBarActivity() { private val viewModel: LoadingViewModel by viewModels() private fun register(loadFailed: Boolean) { - prefs.setLastConfigurationSyncTime(System.currentTimeMillis()) - when { loadFailed -> startPickDisplayNameActivity(loadFailed = true) else -> startHomeActivity() 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 9cfa86c693..28d11f1d7a 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 @@ -45,8 +45,8 @@ internal class LoadingViewModel @Inject constructor( viewModelScope.launch(Dispatchers.IO) { try { TextSecurePreferences.events - .filter { it == TextSecurePreferences.CONFIGURATION_SYNCED } - .onStart { emit(TextSecurePreferences.CONFIGURATION_SYNCED) } + .filter { it == TextSecurePreferences.CONFIGURATION_SYNCED.name } + .onStart { emit(TextSecurePreferences.CONFIGURATION_SYNCED.name) } .filter { prefs.getConfigurationMessageSynced() } .timeout(TIMEOUT_TIME) .collectLatest { onSuccess() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/CreateAccountManager.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/CreateAccountManager.kt index 1e0a21d571..c80f154de3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/CreateAccountManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/CreateAccountManager.kt @@ -40,6 +40,5 @@ class CreateAccountManager @Inject constructor( val registrationID = KeyHelper.generateRegistrationId(false) prefs.setLocalRegistrationId(registrationID) prefs.setLocalNumber(userHexEncodedPublicKey) - prefs.setRestorationTime(0) } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadAccountManager.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadAccountManager.kt index 5a40103830..56be169b95 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadAccountManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/manager/LoadAccountManager.kt @@ -48,7 +48,6 @@ class LoadAccountManager @Inject constructor( prefs.apply { setLocalRegistrationId(registrationID) setLocalNumber(userHexEncodedPublicKey) - setRestorationTime(System.currentTimeMillis()) setHasViewedSeed(true) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/CorrectedPreferenceFragment.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/CorrectedPreferenceFragment.java index 8c3e6190ed..690a8b89fe 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/CorrectedPreferenceFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/CorrectedPreferenceFragment.java @@ -13,7 +13,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.core.view.ViewCompat; -import androidx.fragment.app.DialogFragment; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceFragmentCompat; @@ -22,7 +21,6 @@ import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceViewHolder; import androidx.recyclerview.widget.RecyclerView; -import org.thoughtcrime.securesms.components.CustomDefaultPreference; import org.thoughtcrime.securesms.conversation.v2.ViewUtil; import network.loki.messenger.R; @@ -54,22 +52,6 @@ public abstract class CorrectedPreferenceFragment extends PreferenceFragmentComp setDivider(null); } - @Override - public void onDisplayPreferenceDialog(Preference preference) { - DialogFragment dialogFragment = null; - - if (preference instanceof CustomDefaultPreference) { - dialogFragment = CustomDefaultPreference.CustomDefaultPreferenceDialogFragmentCompat.newInstance(preference.getKey()); - } - - if (dialogFragment != null) { - dialogFragment.setTargetFragment(this, 0); - dialogFragment.show(getFragmentManager(), "android.support.v7.preference.PreferenceFragment.DIALOG"); - } else { - super.onDisplayPreferenceDialog(preference); - } - } - @Override @SuppressLint("RestrictedApi") protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.kt index 6d0790247e..7458cd739f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.kt @@ -18,9 +18,8 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import network.loki.messenger.R -import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsession.utilities.prefs +import org.session.libsession.utilities.findPreference import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.components.SwitchPreferenceCompat import org.thoughtcrime.securesms.notifications.NotificationChannels @@ -74,7 +73,7 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() { } findPreference(TextSecurePreferences.RINGTONE_PREF)!!.onPreferenceClickListener = Preference.OnPreferenceClickListener { - val current = prefs.getNotificationRingtone() + val current = prefs.getNotificationRingtoneUri() val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER) intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true) intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true) @@ -152,7 +151,7 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() { private fun initializeRingtoneSummary(pref: Preference?) { val listener = pref!!.onPreferenceChangeListener as RingtoneSummaryListener? - val uri = prefs.getNotificationRingtone() + val uri = prefs.getNotificationRingtoneUri() listener!!.onPreferenceChange(pref, uri) } @@ -172,13 +171,4 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() { return super.onPreferenceChange(preference, value) } } - - companion object { - @Suppress("unused") - private val TAG = NotificationsPreferenceFragment::class.java.simpleName - fun getSummary(context: Context): CharSequence = when (context.prefs.isNotificationsEnabled()) { - true -> R.string.ApplicationPreferencesActivity_On - false -> R.string.ApplicationPreferencesActivity_Off - }.let(context::getString) - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.kt index 037c91443e..16eb25690b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.kt @@ -15,6 +15,7 @@ import network.loki.messenger.BuildConfig import network.loki.messenger.R import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.utilities.TextSecurePreferences +import org.session.libsession.utilities.findPreference import org.session.libsession.utilities.prefs import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.components.SwitchPreferenceCompat diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkReadyListener.java b/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkReadyListener.java deleted file mode 100644 index b764cc3d3c..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/service/UpdateApkReadyListener.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.thoughtcrime.securesms.service; - - -import android.app.DownloadManager; -import android.app.Notification; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; - -import androidx.annotation.Nullable; -import androidx.core.app.NotificationCompat; - -import org.session.libsession.messaging.MessagingModuleConfiguration; -import org.session.libsession.utilities.FileUtils; -import org.session.libsession.utilities.ServiceUtil; -import org.session.libsession.utilities.TextSecurePreferences; -import org.session.libsignal.utilities.Hex; -import org.session.libsignal.utilities.Log; -import org.thoughtcrime.securesms.notifications.NotificationChannels; -import org.thoughtcrime.securesms.util.FileProviderUtil; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.MessageDigest; - -import network.loki.messenger.R; - -public class UpdateApkReadyListener extends BroadcastReceiver { - - private static final String TAG = UpdateApkReadyListener.class.getSimpleName(); - - @Override - public void onReceive(Context context, Intent intent) { - Log.i(TAG, "onReceive()"); - - if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) { - long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -2); - - if (downloadId == MessagingModuleConfiguration.getShared().getPrefs().getUpdateApkDownloadId()) { - Uri uri = getLocalUriForDownloadId(context, downloadId); - String encodedDigest = MessagingModuleConfiguration.getShared().getPrefs().getUpdateApkDigest(); - - if (uri == null) { - Log.w(TAG, "Downloaded local URI is null?"); - return; - } - - if (isMatchingDigest(context, downloadId, encodedDigest)) { - displayInstallNotification(context, uri); - } else { - Log.w(TAG, "Downloaded APK doesn't match digest..."); - } - } - } - } - - private void displayInstallNotification(Context context, Uri uri) { - Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); - intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.setData(uri); - - PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE); - - Notification notification = new NotificationCompat.Builder(context, NotificationChannels.APP_UPDATES) - .setOngoing(true) - .setContentTitle(context.getString(R.string.UpdateApkReadyListener_Signal_update)) - .setContentText(context.getString(R.string.UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update)) - .setSmallIcon(R.drawable.ic_notification) - .setColor(context.getResources().getColor(R.color.textsecure_primary)) - .setPriority(NotificationCompat.PRIORITY_HIGH) - .setCategory(NotificationCompat.CATEGORY_REMINDER) - .setContentIntent(pendingIntent) - .build(); - - ServiceUtil.getNotificationManager(context).notify(666, notification); - } - - private @Nullable Uri getLocalUriForDownloadId(Context context, long downloadId) { - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager.Query query = new DownloadManager.Query(); - query.setFilterById(downloadId); - - Cursor cursor = downloadManager.query(query); - - try { - if (cursor != null && cursor.moveToFirst()) { - String localUri = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI)); - - if (localUri != null) { - File localFile = new File(Uri.parse(localUri).getPath()); - return FileProviderUtil.getUriFor(context, localFile); - } - } - } finally { - if (cursor != null) cursor.close(); - } - - return null; - } - - private boolean isMatchingDigest(Context context, long downloadId, String theirEncodedDigest) { - try { - if (theirEncodedDigest == null) return false; - - byte[] theirDigest = Hex.fromStringCondensed(theirEncodedDigest); - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - FileInputStream fin = new FileInputStream(downloadManager.openDownloadedFile(downloadId).getFileDescriptor()); - byte[] ourDigest = FileUtils.getFileDigest(fin); - - fin.close(); - - return MessageDigest.isEqual(ourDigest, theirDigest); - } catch (IOException e) { - Log.w(TAG, e); - return false; - } - } -} 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 f48a942c1f..34d236b3ca 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt @@ -8,6 +8,8 @@ import android.provider.Settings import androidx.annotation.ArrayRes import androidx.annotation.StyleRes import androidx.core.app.NotificationCompat +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceManager.getDefaultSharedPreferences import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.channels.BufferOverflow @@ -15,8 +17,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import org.session.libsession.R import org.session.libsession.utilities.TextSecurePreferences.Companion.instance -import org.session.libsignal.utilities.Log -import java.io.IOException import java.util.Date import javax.inject.Inject import javax.inject.Singleton @@ -31,19 +31,23 @@ class Pref( private val set: SharedPreferences.Editor.(String, T) -> SharedPreferences.Editor ) { fun get(prefs: SharedPreferences) = prefs.get(name, default) - fun set(value: T, prefs: SharedPreferences) = prefs.edit().set(name, value).apply() + fun get(prefs: SharedPreferences, default: T) = prefs.get(name, default) + fun set(value: T?, prefs: SharedPreferences) = prefs.edit().apply { value?.let { set(name, it) } ?: run { remove(name)} }.apply() } fun Pref(name: String, default: Boolean) = Pref(name, default, SharedPreferences::getBoolean, SharedPreferences.Editor::putBoolean) fun Pref(name: String, default: Int) = Pref(name, default, SharedPreferences::getInt, SharedPreferences.Editor::putInt) fun Pref(name: String, default: Long) = Pref(name, default, SharedPreferences::getLong, SharedPreferences.Editor::putLong) -fun Pref(name: String, default: String) = Pref(name, default, SharedPreferences::getString, SharedPreferences.Editor::putStringOrRemove) +fun Pref(name: String, default: String) = Pref(name, default, { _, _ -> getString(name, null) ?: default }, SharedPreferences.Editor::putStringOrRemove) 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) -operator fun SharedPreferences.set(pref: Pref, value: T) = pref.set(value, this) +operator fun SharedPreferences.get(pref: Pref, default: T): T = pref.get(this, default) +operator fun SharedPreferences.set(pref: Pref, value: T?) = pref.set(value, this) val Context.prefs get() = instance ?: TextSecurePreferences(this).also { instance = it } @@ -57,6 +61,16 @@ class TextSecurePreferences @Inject constructor( operator fun get(pref: Pref): T = sharedPreferences[pref] + val LED_COLOR_PREF_PRIMARY = Pref("pref_led_color_primary", ThemeUtil.getThemedColor(context, R.attr.colorAccent)) + + fun StringSetPref(name: String, @ArrayRes defaultValuesRes: Int): Pref?> { + return Pref(name, context.resources.getStringArray(defaultValuesRes).toSet()) + } + + val MEDIA_DOWNLOAD_MOBILE_PREF = StringSetPref("pref_media_download_mobile", R.array.pref_media_download_mobile_data_default) + val MEDIA_DOWNLOAD_WIFI_PREF = StringSetPref("pref_media_download_wifi", R.array.pref_media_download_wifi_default) + val MEDIA_DOWNLOAD_ROAMING_PREF = StringSetPref("pref_media_download_roaming", R.array.pref_media_download_roaming_default) + companion object { val TAG = TextSecurePreferences::class.simpleName @@ -69,77 +83,62 @@ class TextSecurePreferences @Inject constructor( var pushSuffix = "" val DISABLE_PASSPHRASE_PREF = Pref("pref_disable_passphrase", true) - const val LANGUAGE_PREF = "pref_language" - const val LAST_VERSION_CODE_PREF = "last_version_code" - const val RINGTONE_PREF = "pref_key_ringtone" - const val VIBRATE_PREF = "pref_key_vibrate" - const val NOTIFICATION_PREF = "pref_key_enable_notifications" - const val LED_COLOR_PREF_PRIMARY = "pref_led_color_primary" - const val PASSPHRASE_TIMEOUT_INTERVAL_PREF = "pref_timeout_interval" - const val PASSPHRASE_TIMEOUT_PREF = "pref_timeout_passphrase" - const val SCREEN_SECURITY_PREF = "pref_screen_security" - const val ENTER_SENDS_PREF = "pref_enter_sends" - const val THREAD_TRIM_ENABLED = "pref_trim_threads" - const val LOCAL_NUMBER_PREF = "pref_local_number" - const val UPDATE_APK_REFRESH_TIME_PREF = "pref_update_apk_refresh_time" - const val UPDATE_APK_DOWNLOAD_ID = "pref_update_apk_download_id" - const val UPDATE_APK_DIGEST = "pref_update_apk_digest" - const val IN_THREAD_NOTIFICATION_PREF = "pref_key_inthread_notifications" - const val MESSAGE_BODY_TEXT_SIZE_PREF = "pref_message_body_text_size" - const val LOCAL_REGISTRATION_ID_PREF = "pref_local_registration_id" - const val REPEAT_ALERTS_PREF = "pref_repeat_alerts" - const val NOTIFICATION_PRIVACY_PREF = "pref_notification_privacy" - const val NOTIFICATION_PRIORITY_PREF = "pref_notification_priority" - const val MEDIA_DOWNLOAD_MOBILE_PREF = "pref_media_download_mobile" - const val MEDIA_DOWNLOAD_WIFI_PREF = "pref_media_download_wifi" - const val MEDIA_DOWNLOAD_ROAMING_PREF = "pref_media_download_roaming" - const val SYSTEM_EMOJI_PREF = "pref_system_emoji" - const val DIRECT_CAPTURE_CAMERA_ID = "pref_direct_capture_camera_id" - const val PROFILE_KEY_PREF = "pref_profile_key" - const val PROFILE_NAME_PREF = "pref_profile_name" - const val PROFILE_AVATAR_ID_PREF = "pref_profile_avatar_id" - const val PROFILE_AVATAR_URL_PREF = "pref_profile_avatar_url" - const val READ_RECEIPTS_PREF = "pref_read_receipts" - const val INCOGNITO_KEYBORAD_PREF = "pref_incognito_keyboard" - const val DATABASE_ENCRYPTED_SECRET = "pref_database_encrypted_secret" - const val DATABASE_UNENCRYPTED_SECRET = "pref_database_unencrypted_secret" - const val ATTACHMENT_ENCRYPTED_SECRET = "pref_attachment_encrypted_secret" - const val ATTACHMENT_UNENCRYPTED_SECRET = "pref_attachment_unencrypted_secret" - const val NEEDS_SQLCIPHER_MIGRATION = "pref_needs_sql_cipher_migration" - const val BACKUP_ENABLED = "pref_backup_enabled_v3" - const val BACKUP_PASSPHRASE = "pref_backup_passphrase" - const val ENCRYPTED_BACKUP_PASSPHRASE = "pref_encrypted_backup_passphrase" - const val BACKUP_TIME = "pref_backup_next_time" - const val BACKUP_SAVE_DIR = "pref_save_dir" - const val SCREEN_LOCK = "pref_android_screen_lock" - const val SCREEN_LOCK_TIMEOUT = "pref_android_screen_lock_timeout" - const val LOG_ENCRYPTED_SECRET = "pref_log_encrypted_secret" - const val LOG_UNENCRYPTED_SECRET = "pref_log_unencrypted_secret" - const val NOTIFICATION_CHANNEL_VERSION = "pref_notification_channel_version" - const val NOTIFICATION_MESSAGES_CHANNEL_VERSION = "pref_notification_messages_channel_version" - const val UNIVERSAL_UNIDENTIFIED_ACCESS = "pref_universal_unidentified_access" - const val TYPING_INDICATORS = "pref_typing_indicators" - const val LINK_PREVIEWS = "pref_link_previews" - const val GIF_METADATA_WARNING = "has_seen_gif_metadata_warning" - const val GIF_GRID_LAYOUT = "pref_gif_grid_layout" - val IS_PUSH_ENABLED get() = "pref_is_using_fcm$pushSuffix" - val PUSH_TOKEN get() = "pref_fcm_token_2$pushSuffix" - val PUSH_REGISTER_TIME get() = "pref_last_fcm_token_upload_time_2$pushSuffix" - const val LAST_CONFIGURATION_SYNC_TIME = "pref_last_configuration_sync_time" - const val CONFIGURATION_SYNCED = "pref_configuration_synced" - const val LAST_PROFILE_UPDATE_TIME = "pref_last_profile_update_time" - const val LAST_OPEN_DATE = "pref_last_open_date" - const val HAS_HIDDEN_MESSAGE_REQUESTS = "pref_message_requests_hidden" - const val CALL_NOTIFICATIONS_ENABLED = "pref_call_notifications_enabled" - const val SHOWN_CALL_WARNING = "pref_shown_call_warning" // call warning is user-facing warning of enabling calls - const val SHOWN_CALL_NOTIFICATION = "pref_shown_call_notification" // call notification is a prompt to check privacy settings - const val LAST_VACUUM_TIME = "pref_last_vacuum_time" - const val AUTOPLAY_AUDIO_MESSAGES = "pref_autoplay_audio" - const val FINGERPRINT_KEY_GENERATED = "fingerprint_key_generated" - const val SELECTED_ACCENT_COLOR = "selected_accent_color" + val LANGUAGE_PREF = Pref("pref_language", "zz") + val LAST_VERSION_CODE_PREF = Pref("last_version_code", 0) + val RINGTONE_PREF = Pref("pref_key_ringtone", Settings.System.DEFAULT_NOTIFICATION_URI.toString()) + val VIBRATE_PREF = Pref("pref_key_vibrate", true) + val NOTIFICATION_PREF = Pref("pref_key_enable_notifications", true) + val PASSPHRASE_TIMEOUT_INTERVAL_PREF = Pref("pref_timeout_interval", 5 * 60) + val PASSPHRASE_TIMEOUT_PREF = Pref("pref_timeout_passphrase", false) + val SCREEN_SECURITY_PREF = Pref("pref_screen_security", true) + val ENTER_SENDS_PREF = Pref("pref_enter_sends", false) + val THREAD_TRIM_ENABLED = Pref("pref_trim_threads", true) + val LOCAL_NUMBER_PREF = Pref("pref_local_number") + val LOCAL_REGISTRATION_ID_PREF = Pref("pref_local_registration_id", 0) + val REPEAT_ALERTS_PREF = Pref("pref_repeat_alerts") + val NOTIFICATION_PRIVACY_PREF = Pref("pref_notification_privacy", "all") + val NOTIFICATION_PRIORITY_PREF = Pref("pref_notification_priority", NotificationCompat.PRIORITY_HIGH.toString()) + val SYSTEM_EMOJI_PREF = Pref("pref_system_emoji", false) + val DIRECT_CAPTURE_CAMERA_ID = Pref("pref_direct_capture_camera_id", Camera.CameraInfo.CAMERA_FACING_BACK) + val PROFILE_KEY_PREF = Pref("pref_profile_key") + val PROFILE_NAME_PREF = Pref("pref_profile_name") + val PROFILE_AVATAR_ID_PREF = Pref("pref_profile_avatar_id", 0) + val PROFILE_AVATAR_URL_PREF = Pref("pref_profile_avatar_url") + val READ_RECEIPTS_PREF = Pref("pref_read_receipts", false) + val INCOGNITO_KEYBORAD_PREF = Pref("pref_incognito_keyboard", true) + val DATABASE_ENCRYPTED_SECRET = Pref("pref_database_encrypted_secret") + val DATABASE_UNENCRYPTED_SECRET = Pref("pref_database_unencrypted_secret") + val ATTACHMENT_ENCRYPTED_SECRET = Pref("pref_attachment_encrypted_secret") + val ATTACHMENT_UNENCRYPTED_SECRET = Pref("pref_attachment_unencrypted_secret") + val SCREEN_LOCK = Pref("pref_android_screen_lock", false) + val SCREEN_LOCK_TIMEOUT = Pref("pref_android_screen_lock_timeout", 0L) + val LOG_ENCRYPTED_SECRET = Pref("pref_log_encrypted_secret") + val LOG_UNENCRYPTED_SECRET = Pref("pref_log_unencrypted_secret") + val NOTIFICATION_CHANNEL_VERSION = Pref("pref_notification_channel_version", 1) + val NOTIFICATION_MESSAGES_CHANNEL_VERSION = Pref("pref_notification_messages_channel_version", 1) + val HAS_VIEWED_SEED = Pref("has_viewed_seed", false) + val LAST_PROFILE_PICTURE_UPLOAD = Pref("last_profile_picture_upload", 0L) + val LAST_SNODE_POOL_REFRESH_DATE = Pref("last_snode_pool_refresh_date", 0L) + val TYPING_INDICATORS = Pref("pref_typing_indicators", false) + val LINK_PREVIEWS = Pref("pref_link_previews", false) + val GIF_METADATA_WARNING = Pref("has_seen_gif_metadata_warning", false) + val GIF_GRID_LAYOUT = Pref("pref_gif_grid_layout", false) + val IS_PUSH_ENABLED get() = Pref("pref_is_using_fcm$pushSuffix", false) + val PUSH_TOKEN get() = Pref("pref_fcm_token_2$pushSuffix", "") + val PUSH_REGISTER_TIME get() = Pref("pref_last_fcm_token_upload_time_2$pushSuffix", 0L) + val CONFIGURATION_SYNCED = Pref("pref_configuration_synced", false) + val LAST_PROFILE_UPDATE_TIME = Pref("pref_last_profile_update_time", 0L) + val LAST_OPEN_DATE = Pref("pref_last_open_date", 0L) + val HAS_SEEN_LINK_PREVIEW_SUGGESTION_DIALOG = Pref("has_seen_link_preview_suggestion_dialog", false) + val HAS_HIDDEN_MESSAGE_REQUESTS = Pref("pref_message_requests_hidden", false) + val CALL_NOTIFICATIONS_ENABLED = Pref("pref_call_notifications_enabled", false) + val SHOWN_CALL_NOTIFICATION = Pref("pref_shown_call_notification", false) // call notification is a prompt to check privacy settings + val LAST_VACUUM_TIME = Pref("pref_last_vacuum_time", 0L) + val AUTOPLAY_AUDIO_MESSAGES = Pref("pref_autoplay_audio", false) + val FINGERPRINT_KEY_GENERATED = Pref("fingerprint_key_generated", false) + val SELECTED_ACCENT_COLOR = Pref("selected_accent_color") - const val HAS_RECEIVED_LEGACY_CONFIG = "has_received_legacy_config" - const val HAS_FORCED_NEW_CONFIG = "has_forced_new_config" + val HAS_RECEIVED_LEGACY_CONFIG = Pref("has_received_legacy_config", false) const val GREEN_ACCENT = "accent_green" const val BLUE_ACCENT = "accent_blue" @@ -149,710 +148,201 @@ class TextSecurePreferences @Inject constructor( const val ORANGE_ACCENT = "accent_orange" const val YELLOW_ACCENT = "accent_yellow" - const val SELECTED_STYLE = "pref_selected_style" // classic_dark/light, ocean_dark/light - const val FOLLOW_SYSTEM_SETTINGS = "pref_follow_system" // follow system day/night - const val HIDE_PASSWORD = "pref_hide_password" - - const val LEGACY_PREF_KEY_SELECTED_UI_MODE = "SELECTED_UI_MODE" // this will be cleared upon launching app, for users migrating to theming build 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: Pref = Pref("pref_selected_style", CLASSIC_DARK) // classic_dark/light, ocean_dark/light + val FOLLOW_SYSTEM_SETTINGS = Pref("pref_follow_system", false) // follow system day/night + val HIDE_PASSWORD = Pref("pref_hide_password", false) + + val LEGACY_PREF_KEY_SELECTED_UI_MODE = Pref("SELECTED_UI_MODE") // this will be cleared upon launching app, for users migrating to theming build + const val ALLOW_MESSAGE_REQUESTS = "libsession.ALLOW_MESSAGE_REQUESTS" } - fun getLastConfigurationSyncTime(): Long { - return getLongPreference(LAST_CONFIGURATION_SYNC_TIME, 0) - } + 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 setLastConfigurationSyncTime(value: Long) { - setLongPreference(LAST_CONFIGURATION_SYNC_TIME, value) - } - - fun getConfigurationMessageSynced(): Boolean { - return getBooleanPreference(CONFIGURATION_SYNCED, false) - } + fun getConfigurationMessageSynced(): Boolean = sharedPreferences[CONFIGURATION_SYNCED] fun setConfigurationMessageSynced(value: Boolean) { - setBooleanPreference(CONFIGURATION_SYNCED, value) - _events.tryEmit(CONFIGURATION_SYNCED) - } - - fun isPushEnabled(): Boolean { - return getBooleanPreference(IS_PUSH_ENABLED, false) - } - - fun setPushEnabled(value: Boolean) { - setBooleanPreference(IS_PUSH_ENABLED, value) - } - - fun getPushToken(): String? { - return getStringPreference(PUSH_TOKEN, "") - } - - fun setPushToken(value: String) { - setStringPreference(PUSH_TOKEN, value) - } - - fun getPushRegisterTime(): Long { - return getLongPreference(PUSH_REGISTER_TIME, 0) - } - - fun setPushRegisterTime(value: Long) { - setLongPreference(PUSH_REGISTER_TIME, value) - } - - fun isScreenLockEnabled(): Boolean { - return getBooleanPreference(SCREEN_LOCK, false) - } - - fun setScreenLockEnabled(value: Boolean) { - setBooleanPreference(SCREEN_LOCK, value) - } - - fun getScreenLockTimeout(): Long { - return getLongPreference(SCREEN_LOCK_TIMEOUT, 0) - } - - fun setScreenLockTimeout(value: Long) { - setLongPreference(SCREEN_LOCK_TIMEOUT, value) - } - - fun setBackupPassphrase(passphrase: String?) { - setStringPreference(BACKUP_PASSPHRASE, passphrase) - } - - fun getBackupPassphrase(): String? { - return getStringPreference(BACKUP_PASSPHRASE, null) - } - - fun setEncryptedBackupPassphrase(encryptedPassphrase: String?) { - setStringPreference(ENCRYPTED_BACKUP_PASSPHRASE, encryptedPassphrase) - } - - fun getEncryptedBackupPassphrase(): String? { - return getStringPreference(ENCRYPTED_BACKUP_PASSPHRASE, null) - } - - fun setBackupEnabled(value: Boolean) { - setBooleanPreference(BACKUP_ENABLED, value) - } - - fun isBackupEnabled(): Boolean { - return getBooleanPreference(BACKUP_ENABLED, false) - } - - fun setNextBackupTime(time: Long) { - setLongPreference(BACKUP_TIME, time) - } - - fun getNextBackupTime(): Long { - return getLongPreference(BACKUP_TIME, -1) - } - - fun setBackupSaveDir(dirUri: String?) { - setStringPreference(BACKUP_SAVE_DIR, dirUri) - } - - fun getBackupSaveDir(): String? { - return getStringPreference(BACKUP_SAVE_DIR, null) - } - - fun getNeedsSqlCipherMigration(): Boolean { - return getBooleanPreference(NEEDS_SQLCIPHER_MIGRATION, false) - } - - fun setAttachmentEncryptedSecret(secret: String) { - setStringPreference(ATTACHMENT_ENCRYPTED_SECRET, secret) - } - - fun setAttachmentUnencryptedSecret(secret: String?) { - setStringPreference(ATTACHMENT_UNENCRYPTED_SECRET, secret) - } - - fun getAttachmentEncryptedSecret(): String? { - return getStringPreference(ATTACHMENT_ENCRYPTED_SECRET, null) - } - - fun getAttachmentUnencryptedSecret(): String? { - return getStringPreference(ATTACHMENT_UNENCRYPTED_SECRET, null) - } - - fun setDatabaseEncryptedSecret(secret: String) { - setStringPreference(DATABASE_ENCRYPTED_SECRET, secret) - } - - fun setDatabaseUnencryptedSecret(secret: String?) { - setStringPreference(DATABASE_UNENCRYPTED_SECRET, secret) - } - - fun getDatabaseUnencryptedSecret(): String? { - return getStringPreference(DATABASE_UNENCRYPTED_SECRET, null) - } - - fun getDatabaseEncryptedSecret(): String? { - return getStringPreference(DATABASE_ENCRYPTED_SECRET, null) - } - - fun isIncognitoKeyboardEnabled(): Boolean { - return getBooleanPreference(INCOGNITO_KEYBORAD_PREF, true) - } - - fun isReadReceiptsEnabled(): Boolean { - return getBooleanPreference(READ_RECEIPTS_PREF, false) - } - - fun setReadReceiptsEnabled(enabled: Boolean) { - setBooleanPreference(READ_RECEIPTS_PREF, enabled) - } - - fun isTypingIndicatorsEnabled(): Boolean { - return getBooleanPreference(TYPING_INDICATORS, false) - } - - fun setTypingIndicatorsEnabled(enabled: Boolean) { - setBooleanPreference(TYPING_INDICATORS, enabled) - } - - fun isLinkPreviewsEnabled(): Boolean { - return getBooleanPreference(LINK_PREVIEWS, false) - } - - fun setLinkPreviewsEnabled(enabled: Boolean) { - setBooleanPreference(LINK_PREVIEWS, enabled) - } - - fun hasSeenGIFMetaDataWarning(): Boolean { - return getBooleanPreference(GIF_METADATA_WARNING, false) - } - - fun setHasSeenGIFMetaDataWarning() { - setBooleanPreference(GIF_METADATA_WARNING, true) - } - - fun isGifSearchInGridLayout(): Boolean { - return getBooleanPreference(GIF_GRID_LAYOUT, false) - } - - fun setIsGifSearchInGridLayout(isGrid: Boolean) { - setBooleanPreference(GIF_GRID_LAYOUT, isGrid) - } - - fun getProfileKey(): String? { - return getStringPreference(PROFILE_KEY_PREF, null) - } - - fun setProfileKey(key: String?) { - setStringPreference(PROFILE_KEY_PREF, key) + set(CONFIGURATION_SYNCED, value) + _events.tryEmit(CONFIGURATION_SYNCED.name) } + 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) + fun getScreenLockTimeout(): Long = sharedPreferences[SCREEN_LOCK_TIMEOUT] + fun setScreenLockTimeout(value: Long) = set(SCREEN_LOCK_TIMEOUT, value) + fun setAttachmentEncryptedSecret(secret: String) = set(ATTACHMENT_ENCRYPTED_SECRET, secret) + fun setAttachmentUnencryptedSecret(secret: String?) = set(ATTACHMENT_UNENCRYPTED_SECRET, secret) + fun getAttachmentEncryptedSecret(): String? = sharedPreferences[ATTACHMENT_ENCRYPTED_SECRET] + fun getAttachmentUnencryptedSecret(): String? = sharedPreferences[ATTACHMENT_UNENCRYPTED_SECRET] + fun setDatabaseEncryptedSecret(secret: String) = set(DATABASE_ENCRYPTED_SECRET, secret) + fun setDatabaseUnencryptedSecret(secret: String?) = set(DATABASE_UNENCRYPTED_SECRET, secret) + fun getDatabaseUnencryptedSecret(): String? = sharedPreferences[DATABASE_UNENCRYPTED_SECRET] + fun getDatabaseEncryptedSecret(): String? = sharedPreferences[DATABASE_ENCRYPTED_SECRET] + fun isIncognitoKeyboardEnabled() = sharedPreferences[INCOGNITO_KEYBORAD_PREF] + fun isReadReceiptsEnabled(): Boolean = sharedPreferences[READ_RECEIPTS_PREF] + fun isTypingIndicatorsEnabled() = sharedPreferences[TYPING_INDICATORS] + fun isLinkPreviewsEnabled(): Boolean = sharedPreferences[LINK_PREVIEWS] + fun setLinkPreviewsEnabled(enabled: Boolean) = set(LINK_PREVIEWS, enabled) + fun hasSeenGIFMetaDataWarning(): Boolean = sharedPreferences[GIF_METADATA_WARNING] + fun setHasSeenGIFMetaDataWarning() = set(GIF_METADATA_WARNING, true) + fun isGifSearchInGridLayout() = sharedPreferences[GIF_GRID_LAYOUT] + 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?) { - setStringPreference(PROFILE_NAME_PREF, name) - _events.tryEmit(PROFILE_NAME_PREF) + sharedPreferences[PROFILE_NAME_PREF] = name + _events.tryEmit(PROFILE_NAME_PREF.name) } - - fun getProfileName(): String? { - return getStringPreference(PROFILE_NAME_PREF, null) - } - - fun setProfileAvatarId(id: Int) { - setIntegerPreference(PROFILE_AVATAR_ID_PREF, id) - } - - fun getProfileAvatarId(): Int { - return getIntegerPreference(PROFILE_AVATAR_ID_PREF, 0) - } - - fun setProfilePictureURL(url: String?) { - setStringPreference(PROFILE_AVATAR_URL_PREF, url) - } - - fun getProfilePictureURL(): String? { - return getStringPreference(PROFILE_AVATAR_URL_PREF, null) - } - - fun getNotificationPriority(): Int { - return getStringPreference( - NOTIFICATION_PRIORITY_PREF, NotificationCompat.PRIORITY_HIGH.toString())!!.toInt() - } - - fun getMessageBodyTextSize(): Int { - return getStringPreference(MESSAGE_BODY_TEXT_SIZE_PREF, "16")!!.toInt() - } - - fun setDirectCaptureCameraId(value: Int) { - setIntegerPreference(DIRECT_CAPTURE_CAMERA_ID, value) - } - - fun getDirectCaptureCameraId(): Int { - return getIntegerPreference(DIRECT_CAPTURE_CAMERA_ID, Camera.CameraInfo.CAMERA_FACING_BACK) - } - - fun getNotificationPrivacy(): NotificationPrivacyPreference { - return NotificationPrivacyPreference(getStringPreference( - NOTIFICATION_PRIVACY_PREF, "all")) - } - - fun getRepeatAlertsCount(): Int { - return try { - getStringPreference(REPEAT_ALERTS_PREF, "0")!!.toInt() - } catch (e: NumberFormatException) { - Log.w(TAG, e) - 0 - } - } - - fun getLocalRegistrationId(): Int { - return getIntegerPreference(LOCAL_REGISTRATION_ID_PREF, 0) - } - - fun setLocalRegistrationId(registrationId: Int) { - setIntegerPreference(LOCAL_REGISTRATION_ID_PREF, registrationId) - } - - fun isInThreadNotifications(): Boolean { - return getBooleanPreference(IN_THREAD_NOTIFICATION_PREF, true) - } - - fun isUniversalUnidentifiedAccess(): Boolean { - return getBooleanPreference(UNIVERSAL_UNIDENTIFIED_ACCESS, false) - } - - fun getUpdateApkRefreshTime(): Long { - return getLongPreference(UPDATE_APK_REFRESH_TIME_PREF, 0L) - } - - fun setUpdateApkRefreshTime(value: Long) { - setLongPreference(UPDATE_APK_REFRESH_TIME_PREF, value) - } - - fun setUpdateApkDownloadId(value: Long) { - setLongPreference(UPDATE_APK_DOWNLOAD_ID, value) - } - - fun getUpdateApkDownloadId(): Long { - return getLongPreference(UPDATE_APK_DOWNLOAD_ID, -1) - } - - fun setUpdateApkDigest(value: String?) { - setStringPreference(UPDATE_APK_DIGEST, value) - } - - fun getUpdateApkDigest(): String? { - return getStringPreference(UPDATE_APK_DIGEST, null) - } - - fun getLocalNumber(): String? { - return getStringPreference(LOCAL_NUMBER_PREF, null) - } - - fun getHasLegacyConfig(): Boolean { - return getBooleanPreference(HAS_RECEIVED_LEGACY_CONFIG, false) - } - + fun getProfileName(): String? = sharedPreferences[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) + fun getProfilePictureURL(): String? = sharedPreferences[PROFILE_AVATAR_URL_PREF] + fun getNotificationPriority(): Int = sharedPreferences[NOTIFICATION_PRIORITY_PREF]!!.toInt() + fun setDirectCaptureCameraId(value: Int) = set(DIRECT_CAPTURE_CAMERA_ID, value) + fun getDirectCaptureCameraId(): Int = sharedPreferences[DIRECT_CAPTURE_CAMERA_ID] + fun getNotificationPrivacy(): NotificationPrivacyPreference = NotificationPrivacyPreference(sharedPreferences[NOTIFICATION_PRIVACY_PREF]) + fun getRepeatAlertsCount(): Int = runCatching { sharedPreferences[REPEAT_ALERTS_PREF] }.getOrNull()?.toInt() ?: 0 + fun getLocalRegistrationId(): Int = sharedPreferences[LOCAL_REGISTRATION_ID_PREF] + 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) { - setBooleanPreference(HAS_RECEIVED_LEGACY_CONFIG, newValue) - _events.tryEmit(HAS_RECEIVED_LEGACY_CONFIG) + sharedPreferences[HAS_RECEIVED_LEGACY_CONFIG] = newValue + _events.tryEmit(HAS_RECEIVED_LEGACY_CONFIG.name) } - - fun setLocalNumber(localNumber: String) { - setStringPreference(LOCAL_NUMBER_PREF, localNumber.toLowerCase()) - } - - fun removeLocalNumber() { - removePreference(LOCAL_NUMBER_PREF) - } - - fun isEnterSendsEnabled(): Boolean { - return getBooleanPreference(ENTER_SENDS_PREF, false) - } - + fun setLocalNumber(localNumber: String) = set(LOCAL_NUMBER_PREF, localNumber.lowercase()) + fun isEnterSendsEnabled() = sharedPreferences[ENTER_SENDS_PREF] fun isPasswordDisabled(): Boolean = sharedPreferences[DISABLE_PASSPHRASE_PREF] - - fun setPasswordDisabled(disabled: Boolean) { - sharedPreferences[DISABLE_PASSPHRASE_PREF] = disabled - } - - fun isScreenSecurityEnabled(): Boolean { - return getBooleanPreference(SCREEN_SECURITY_PREF, true) - } - - fun getLastVersionCode(): Int { - return getIntegerPreference(LAST_VERSION_CODE_PREF, 0) - } - - @Throws(IOException::class) - fun setLastVersionCode(versionCode: Int) { - if (!setIntegerPreferenceBlocking(LAST_VERSION_CODE_PREF, versionCode)) { - throw IOException("couldn't write version code to sharedpreferences") + fun setPasswordDisabled(disabled: Boolean) = set(DISABLE_PASSPHRASE_PREF, disabled) + fun isScreenSecurityEnabled() = sharedPreferences[SCREEN_SECURITY_PREF] + fun getLastVersionCode(): Int = sharedPreferences[LAST_VERSION_CODE_PREF] + fun setLastVersionCode(versionCode: Int) = set(LAST_VERSION_CODE_PREF, versionCode) + fun isPassphraseTimeoutEnabled() = sharedPreferences[PASSPHRASE_TIMEOUT_PREF] + fun getPassphraseTimeoutInterval() = sharedPreferences[PASSPHRASE_TIMEOUT_INTERVAL_PREF] + fun getLanguage(): String? = sharedPreferences[LANGUAGE_PREF] + fun isNotificationsEnabled() = sharedPreferences[NOTIFICATION_PREF] + fun getNotificationRingtone(): String? = sharedPreferences[RINGTONE_PREF]?.takeUnless { it.startsWith("file:") } ?: RINGTONE_PREF.default + fun getNotificationRingtoneUri(): Uri = getNotificationRingtone().let(Uri::parse) + fun removeNotificationRingtone() = remove(RINGTONE_PREF) + fun setNotificationRingtone(ringtone: String?) = set(RINGTONE_PREF, ringtone) + fun setNotificationVibrateEnabled(enabled: Boolean) = set(VIBRATE_PREF, enabled) + fun isNotificationVibrateEnabled(): Boolean = sharedPreferences[VIBRATE_PREF] + fun getNotificationLedColor(): Int = sharedPreferences[LED_COLOR_PREF_PRIMARY] + fun isThreadLengthTrimmingEnabled() = sharedPreferences[THREAD_TRIM_ENABLED] + fun isSystemEmojiPreferred() = sharedPreferences[SYSTEM_EMOJI_PREF] + fun getMobileMediaDownloadAllowed(): Set? = sharedPreferences[MEDIA_DOWNLOAD_MOBILE_PREF] + fun getWifiMediaDownloadAllowed(): Set? = sharedPreferences[MEDIA_DOWNLOAD_WIFI_PREF] + fun getRoamingMediaDownloadAllowed(): Set? = sharedPreferences[MEDIA_DOWNLOAD_ROAMING_PREF] + fun getLogEncryptedSecret(): String? = sharedPreferences[LOG_ENCRYPTED_SECRET] + fun setLogEncryptedSecret(base64Secret: String?) = set(LOG_ENCRYPTED_SECRET, base64Secret) + fun getLogUnencryptedSecret(): String? = sharedPreferences[LOG_UNENCRYPTED_SECRET] + fun getNotificationChannelVersion(): Int = sharedPreferences[NOTIFICATION_CHANNEL_VERSION] + fun setNotificationChannelVersion(version: Int) = set(NOTIFICATION_CHANNEL_VERSION, version) + fun getNotificationMessagesChannelVersion(): Int = sharedPreferences[NOTIFICATION_MESSAGES_CHANNEL_VERSION] + fun setNotificationMessagesChannelVersion(version: Int) = set(NOTIFICATION_MESSAGES_CHANNEL_VERSION, version) + fun hasViewedSeed(): Boolean = sharedPreferences[HAS_VIEWED_SEED] + fun setHasViewedSeed(hasViewedSeed: Boolean) = set(HAS_VIEWED_SEED, hasViewedSeed) + fun getLastProfilePictureUpload(): Long = sharedPreferences[LAST_PROFILE_PICTURE_UPLOAD] + fun setLastProfilePictureUpload(newValue: Long) = set(LAST_PROFILE_PICTURE_UPLOAD, newValue) + fun getLastSnodePoolRefreshDate(): Long = sharedPreferences[LAST_SNODE_POOL_REFRESH_DATE] + fun setLastSnodePoolRefreshDate(date: Date) = set(LAST_SNODE_POOL_REFRESH_DATE, date.time) + fun shouldUpdateProfile(profileUpdateTime: Long): Boolean = profileUpdateTime > sharedPreferences[LAST_PROFILE_UPDATE_TIME] + fun setLastProfileUpdateTime(profileUpdateTime: Long) = set(LAST_PROFILE_UPDATE_TIME, profileUpdateTime) + fun getLastOpenTimeDate(): Long = sharedPreferences[LAST_OPEN_DATE] + fun setLastOpenDate() = set(LAST_OPEN_DATE, System.currentTimeMillis()) + fun hasSeenLinkPreviewSuggestionDialog(): Boolean = sharedPreferences[HAS_SEEN_LINK_PREVIEW_SUGGESTION_DIALOG] + fun setHasSeenLinkPreviewSuggestionDialog() = set(HAS_SEEN_LINK_PREVIEW_SUGGESTION_DIALOG, true) + fun isCallNotificationsEnabled(): Boolean = sharedPreferences[CALL_NOTIFICATIONS_ENABLED] + fun setCallNotificationsEnabled(enabled: Boolean) = set(CALL_NOTIFICATIONS_ENABLED, enabled) + fun getLastVacuumTime(): Long = sharedPreferences[LAST_VACUUM_TIME] + fun setLastVacuumNow() = set(LAST_VACUUM_TIME, System.currentTimeMillis()) + fun setShownCallNotification(): Boolean = when { + sharedPreferences[SHOWN_CALL_NOTIFICATION] -> false + else -> { + set(SHOWN_CALL_NOTIFICATION, true) + true } } + fun hasHiddenMessageRequests(): Boolean = sharedPreferences[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] + fun setFingerprintKeyGenerated() = set(FINGERPRINT_KEY_GENERATED, true) - fun isPassphraseTimeoutEnabled(): Boolean { - return getBooleanPreference(PASSPHRASE_TIMEOUT_PREF, false) - } - - fun getPassphraseTimeoutInterval(): Int { - return getIntegerPreference(PASSPHRASE_TIMEOUT_INTERVAL_PREF, 5 * 60) - } - - fun getLanguage(): String? { - return getStringPreference(LANGUAGE_PREF, "zz") - } - - fun isNotificationsEnabled(): Boolean { - return getBooleanPreference(NOTIFICATION_PREF, true) - } - - fun getNotificationRingtone(): Uri { - var result = getStringPreference(RINGTONE_PREF, Settings.System.DEFAULT_NOTIFICATION_URI.toString()) - if (result != null && result.startsWith("file:")) { - result = Settings.System.DEFAULT_NOTIFICATION_URI.toString() - } - return Uri.parse(result) - } - - fun removeNotificationRingtone() { - removePreference(RINGTONE_PREF) - } - - fun setNotificationRingtone(ringtone: String?) { - setStringPreference(RINGTONE_PREF, ringtone) - } - - fun setNotificationVibrateEnabled(enabled: Boolean) { - setBooleanPreference(VIBRATE_PREF, enabled) - } - - fun isNotificationVibrateEnabled(): Boolean { - return getBooleanPreference(VIBRATE_PREF, true) - } - - fun getNotificationLedColor(): Int { - return getIntegerPreference(LED_COLOR_PREF_PRIMARY, context.getColor(R.color.accent_green)) - } - - fun isThreadLengthTrimmingEnabled(): Boolean { - return getBooleanPreference(THREAD_TRIM_ENABLED, true) - } - - fun isSystemEmojiPreferred(): Boolean { - return getBooleanPreference(SYSTEM_EMOJI_PREF, false) - } - - fun getMobileMediaDownloadAllowed(): Set? { - return getMediaDownloadAllowed(MEDIA_DOWNLOAD_MOBILE_PREF, R.array.pref_media_download_mobile_data_default) - } - - fun getWifiMediaDownloadAllowed(): Set? { - return getMediaDownloadAllowed(MEDIA_DOWNLOAD_WIFI_PREF, R.array.pref_media_download_wifi_default) - } - - fun getRoamingMediaDownloadAllowed(): Set? { - return getMediaDownloadAllowed(MEDIA_DOWNLOAD_ROAMING_PREF, R.array.pref_media_download_roaming_default) - } - - fun getMediaDownloadAllowed(key: String, @ArrayRes defaultValuesRes: Int): Set? { - return getStringSetPreference(key, HashSet(listOf(*context.resources.getStringArray(defaultValuesRes)))) - } - - fun getLogEncryptedSecret(): String? { - return getStringPreference(LOG_ENCRYPTED_SECRET, null) - } - - fun setLogEncryptedSecret(base64Secret: String?) { - setStringPreference(LOG_ENCRYPTED_SECRET, base64Secret) - } - - fun getLogUnencryptedSecret(): String? { - return getStringPreference(LOG_UNENCRYPTED_SECRET, null) - } - - fun setLogUnencryptedSecret(base64Secret: String?) { - setStringPreference(LOG_UNENCRYPTED_SECRET, base64Secret) - } - - fun getNotificationChannelVersion(): Int { - return getIntegerPreference(NOTIFICATION_CHANNEL_VERSION, 1) - } - - fun setNotificationChannelVersion(version: Int) { - setIntegerPreference(NOTIFICATION_CHANNEL_VERSION, version) - } - - fun getNotificationMessagesChannelVersion(): Int { - return getIntegerPreference(NOTIFICATION_MESSAGES_CHANNEL_VERSION, 1) - } - - fun setNotificationMessagesChannelVersion(version: Int) { - setIntegerPreference(NOTIFICATION_MESSAGES_CHANNEL_VERSION, version) - } - - fun hasForcedNewConfig(): Boolean = - getBooleanPreference(HAS_FORCED_NEW_CONFIG, false) - - fun getBooleanPreference(key: String?, defaultValue: Boolean): Boolean { - return getDefaultSharedPreferences(context).getBoolean(key, defaultValue) - } - - fun setBooleanPreference(key: String?, value: Boolean) { - getDefaultSharedPreferences(context).edit().putBoolean(key, value).apply() - } - - fun getStringPreference(key: String, defaultValue: String?): String? { - return getDefaultSharedPreferences(context).getString(key, defaultValue) - } - - fun setStringPreference(key: String?, value: String?) { - getDefaultSharedPreferences(context).edit().putString(key, value).apply() - } - - fun getIntegerPreference(key: String, defaultValue: Int): Int { - return getDefaultSharedPreferences(context).getInt(key, defaultValue) - } - - fun setIntegerPreference(key: String, value: Int) { - getDefaultSharedPreferences(context).edit().putInt(key, value).apply() - } - - fun setIntegerPreferenceBlocking(key: String, value: Int): Boolean { - return getDefaultSharedPreferences(context).edit().putInt(key, value).commit() - } - - fun getLongPreference(key: String, defaultValue: Long): Long { - return getDefaultSharedPreferences(context).getLong(key, defaultValue) - } - - fun setLongPreference(key: String, value: Long) { - getDefaultSharedPreferences(context).edit().putLong(key, value).apply() - } - - fun hasPreference(key: String): Boolean { - return getDefaultSharedPreferences(context).contains(key) - } - - fun removePreference(key: String) { - getDefaultSharedPreferences(context).edit().remove(key).apply() - } - - fun getStringSetPreference(key: String, defaultValues: Set): Set? { - val prefs = getDefaultSharedPreferences(context) - return if (prefs.contains(key)) { - prefs.getStringSet(key, emptySet()) - } else { - defaultValues - } - } - - fun getHasViewedSeed(): Boolean { - return getBooleanPreference("has_viewed_seed", false) - } - - fun setHasViewedSeed(hasViewedSeed: Boolean) { - setBooleanPreference("has_viewed_seed", hasViewedSeed) - } - - fun setRestorationTime(time: Long) { - setLongPreference("restoration_time", time) - } - - fun getLastProfilePictureUpload(): Long { - return getLongPreference("last_profile_picture_upload", 0) - } - - fun setLastProfilePictureUpload(newValue: Long) { - setLongPreference("last_profile_picture_upload", newValue) - } - - fun getLastSnodePoolRefreshDate(): Long { - return getLongPreference("last_snode_pool_refresh_date", 0) - } - - fun setLastSnodePoolRefreshDate(date: Date) { - setLongPreference("last_snode_pool_refresh_date", date.time) - } - - fun shouldUpdateProfile(profileUpdateTime: Long): Boolean { - return profileUpdateTime > getLongPreference(LAST_PROFILE_UPDATE_TIME, 0) - } - - fun setLastProfileUpdateTime(profileUpdateTime: Long) { - setLongPreference(LAST_PROFILE_UPDATE_TIME, profileUpdateTime) - } - - fun getLastOpenTimeDate(): Long { - return getLongPreference(LAST_OPEN_DATE, 0) - } - - fun setLastOpenDate() { - setLongPreference(LAST_OPEN_DATE, System.currentTimeMillis()) - } - - fun hasSeenLinkPreviewSuggestionDialog(): Boolean { - return getBooleanPreference("has_seen_link_preview_suggestion_dialog", false) - } - - fun setHasSeenLinkPreviewSuggestionDialog() { - setBooleanPreference("has_seen_link_preview_suggestion_dialog", true) - } - - fun isCallNotificationsEnabled(): Boolean { - return getBooleanPreference(CALL_NOTIFICATIONS_ENABLED, false) - } - - fun setCallNotificationsEnabled(enabled: Boolean) { - setBooleanPreference(CALL_NOTIFICATIONS_ENABLED, enabled) - } - - fun getLastVacuumTime(): Long { - return getLongPreference(LAST_VACUUM_TIME, 0) - } - - fun getLastVacuum(): Long { - return getLongPreference(LAST_VACUUM_TIME, 0) - } - - fun setLastVacuumNow() { - setLongPreference(LAST_VACUUM_TIME, System.currentTimeMillis()) - } - - 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) - */ - 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 - } - - fun hasHiddenMessageRequests(): Boolean { - return getBooleanPreference(HAS_HIDDEN_MESSAGE_REQUESTS, false) - } - - fun setHasHiddenMessageRequests() { - setBooleanPreference(HAS_HIDDEN_MESSAGE_REQUESTS, true) - } - - fun removeHasHiddenMessageRequests() { - removePreference(HAS_HIDDEN_MESSAGE_REQUESTS) - } - - fun getFingerprintKeyGenerated(): Boolean { - return getBooleanPreference(FINGERPRINT_KEY_GENERATED, false) - } - - fun setFingerprintKeyGenerated() { - setBooleanPreference(FINGERPRINT_KEY_GENERATED, true) - } - - fun getSelectedAccentColor(): String? = - getStringPreference(SELECTED_ACCENT_COLOR, null) + fun hasSelectedAccentColor() = has(SELECTED_ACCENT_COLOR) + fun getSelectedAccentColor(): String? = sharedPreferences[SELECTED_ACCENT_COLOR] @StyleRes - fun getAccentColorStyle(): Int? { - return when (getSelectedAccentColor()) { - GREEN_ACCENT -> R.style.PrimaryGreen - BLUE_ACCENT -> R.style.PrimaryBlue - PURPLE_ACCENT -> R.style.PrimaryPurple - PINK_ACCENT -> R.style.PrimaryPink - RED_ACCENT -> R.style.PrimaryRed - ORANGE_ACCENT -> R.style.PrimaryOrange - YELLOW_ACCENT -> R.style.PrimaryYellow - else -> null - } + fun getAccentColorStyle(): Int? = when (getSelectedAccentColor()) { + GREEN_ACCENT -> R.style.PrimaryGreen + BLUE_ACCENT -> R.style.PrimaryBlue + PURPLE_ACCENT -> R.style.PrimaryPurple + PINK_ACCENT -> R.style.PrimaryPink + RED_ACCENT -> R.style.PrimaryRed + ORANGE_ACCENT -> R.style.PrimaryOrange + YELLOW_ACCENT -> R.style.PrimaryYellow + else -> null } - fun setAccentColorStyle(@StyleRes newColorStyle: Int?) { - setStringPreference( - SELECTED_ACCENT_COLOR, when (newColorStyle) { - R.style.PrimaryGreen -> GREEN_ACCENT - R.style.PrimaryBlue -> BLUE_ACCENT - R.style.PrimaryPurple -> PURPLE_ACCENT - R.style.PrimaryPink -> PINK_ACCENT - R.style.PrimaryRed -> RED_ACCENT - R.style.PrimaryOrange -> ORANGE_ACCENT - R.style.PrimaryYellow -> YELLOW_ACCENT - else -> null - } - ) - } + fun setAccentColorStyle(@StyleRes newColorStyle: Int?) = when (newColorStyle) { + R.style.PrimaryGreen -> GREEN_ACCENT + R.style.PrimaryBlue -> BLUE_ACCENT + R.style.PrimaryPurple -> PURPLE_ACCENT + R.style.PrimaryPink -> PINK_ACCENT + R.style.PrimaryRed -> RED_ACCENT + R.style.PrimaryOrange -> ORANGE_ACCENT + R.style.PrimaryYellow -> YELLOW_ACCENT + else -> null + }.let { set(SELECTED_ACCENT_COLOR, it) } fun getThemeStyle(): String { - val hasLegacy = getStringPreference(LEGACY_PREF_KEY_SELECTED_UI_MODE, null) - if (!hasLegacy.isNullOrEmpty()) { - migrateLegacyUiPref() - } - - return getStringPreference(SELECTED_STYLE, CLASSIC_DARK)!! + migrateLegacyUiPrefIfNecessary() + return sharedPreferences[SELECTED_STYLE] } 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) + sharedPreferences[SELECTED_STYLE] = if (themeStyle !in listOf(CLASSIC_DARK, CLASSIC_LIGHT, OCEAN_DARK, OCEAN_LIGHT)) CLASSIC_DARK else themeStyle } fun getFollowSystemSettings(): Boolean { - val hasLegacy = getStringPreference(LEGACY_PREF_KEY_SELECTED_UI_MODE, null) - if (!hasLegacy.isNullOrEmpty()) { - migrateLegacyUiPref() - } - - return getBooleanPreference(FOLLOW_SYSTEM_SETTINGS, false) + migrateLegacyUiPrefIfNecessary() + return sharedPreferences[FOLLOW_SYSTEM_SETTINGS] } - private fun migrateLegacyUiPref() { - val legacy = getStringPreference(LEGACY_PREF_KEY_SELECTED_UI_MODE, null) ?: return + private fun migrateLegacyUiPrefIfNecessary() { + val legacy = sharedPreferences[LEGACY_PREF_KEY_SELECTED_UI_MODE] ?: return val (mode, followSystem) = when (legacy) { - "DAY" -> { - CLASSIC_LIGHT to false - } - "NIGHT" -> { - CLASSIC_DARK to false - } - "SYSTEM_DEFAULT" -> { - CLASSIC_DARK to true - } - else -> { - CLASSIC_DARK to false - } + "DAY" -> CLASSIC_LIGHT to false + "NIGHT" -> CLASSIC_DARK to false + "SYSTEM_DEFAULT" -> CLASSIC_DARK to true + else -> CLASSIC_DARK to false } - if (!hasPreference(FOLLOW_SYSTEM_SETTINGS) && !hasPreference(SELECTED_STYLE)) { + if (!has(FOLLOW_SYSTEM_SETTINGS) && !has(SELECTED_STYLE)) { setThemeStyle(mode) setFollowSystemSettings(followSystem) } - removePreference(LEGACY_PREF_KEY_SELECTED_UI_MODE) + remove(LEGACY_PREF_KEY_SELECTED_UI_MODE) } - fun setFollowSystemSettings(followSystemSettings: Boolean) { - setBooleanPreference(FOLLOW_SYSTEM_SETTINGS, followSystemSettings) - } - - fun autoplayAudioMessages(): Boolean { - return getBooleanPreference(AUTOPLAY_AUDIO_MESSAGES, false) - } - - fun clearAll() { - getDefaultSharedPreferences(context).edit().clear().commit() - } - - fun getHidePassword() = getBooleanPreference(HIDE_PASSWORD, false) - - fun setHidePassword(value: Boolean) { - setBooleanPreference(HIDE_PASSWORD, value) - } + fun setFollowSystemSettings(followSystemSettings: Boolean) = set(FOLLOW_SYSTEM_SETTINGS, followSystemSettings) + fun autoplayAudioMessages(): Boolean = sharedPreferences[AUTOPLAY_AUDIO_MESSAGES] + fun clearAll() = getDefaultSharedPreferences(context).edit().clear().commit() + fun getHidePassword() = sharedPreferences[HIDE_PASSWORD] + fun setHidePassword(value: Boolean) = set(HIDE_PASSWORD, value) } + +fun

PreferenceFragmentCompat.findPreference(pref: Pref<*>) = findPreference

(pref.name)