mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-10-01 17:31:14 +01:00
Remove TextSecurePreferences.
This commit is contained in:
committed by
Alex Hart
parent
e6632ff8e0
commit
d57b928c6f
+1
-1
@@ -44,7 +44,7 @@ class InstrumentationApplicationDependencyProvider(val application: Application,
|
||||
private var archiveService: ArchiveService = mockk(relaxed = true)
|
||||
|
||||
init {
|
||||
recipientCache = LiveRecipientCache(application) { r -> r.run() }
|
||||
recipientCache = LiveRecipientCache { r -> r.run() }
|
||||
}
|
||||
|
||||
override fun provideBillingApi(): BillingApi = billingApi
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager
|
||||
import org.thoughtcrime.securesms.jobmanager.JobMigrator
|
||||
import org.thoughtcrime.securesms.jobmanager.JobTracker
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import kotlin.random.Random
|
||||
|
||||
@@ -90,7 +90,7 @@ class JobManagerPerformanceTests {
|
||||
.setConstraintFactories(JobManagerFactories.getConstraintFactories(context))
|
||||
.setConstraintObservers(JobManagerFactories.getConstraintObservers(context))
|
||||
.setJobStorage(FastJobStorage(getInstance(context)))
|
||||
.setJobMigrator(JobMigrator(TextSecurePreferences.getJobManagerVersion(context), JobManager.CURRENT_VERSION, JobManagerFactories.getJobMigrations(context)))
|
||||
.setJobMigrator(JobMigrator(SignalStore.misc.jobManagerVersion, JobManager.CURRENT_VERSION, JobManagerFactories.getJobMigrations(context)))
|
||||
.build()
|
||||
|
||||
return JobManager(context, config)
|
||||
|
||||
@@ -34,7 +34,6 @@ import org.thoughtcrime.securesms.registration.data.LocalRegistrationMetadataUti
|
||||
import org.thoughtcrime.securesms.registration.data.RegistrationData
|
||||
import org.thoughtcrime.securesms.registration.data.RegistrationRepository
|
||||
import org.thoughtcrime.securesms.registration.util.RegistrationUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import java.util.UUID
|
||||
@@ -88,8 +87,8 @@ object TestUsers {
|
||||
SignalStore.registration.restoreDecisionState = RestoreDecisionState.Skipped
|
||||
RegistrationUtil.maybeMarkRegistrationComplete()
|
||||
SignalDatabase.recipients.setProfileName(Recipient.self().id, ProfileName.fromParts("Tester", "McTesterson"))
|
||||
TextSecurePreferences.setPromptedOptimizeDoze(application, true)
|
||||
TextSecurePreferences.setRatingEnabled(application, false)
|
||||
SignalStore.uiHints.setHasPromptedOptimizeDoze(true)
|
||||
SignalStore.misc.ratingEnabled = false
|
||||
|
||||
PreKeyUtil.generateAndStoreSignedPreKey(AppDependencies.protocolStore.aci(), SignalStore.account.aciPreKeys)
|
||||
PreKeyUtil.generateAndStoreOneTimeEcPreKeys(AppDependencies.protocolStore.aci(), SignalStore.account.aciPreKeys)
|
||||
|
||||
@@ -16,9 +16,9 @@ import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
|
||||
import org.thoughtcrime.securesms.migrations.QuoteThumbnailBackfillMigrationJob;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.stickers.BlessedPacks;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.signal.core.util.Util;
|
||||
|
||||
/**
|
||||
@@ -36,9 +36,9 @@ public final class AppInitialization {
|
||||
Log.i(TAG, "onFirstEverAppLaunch()");
|
||||
|
||||
PlainTextKeyValueStore.setAppMigrationVersion(ApplicationMigrations.CURRENT_VERSION);
|
||||
TextSecurePreferences.setJobManagerVersion(context, JobManager.CURRENT_VERSION);
|
||||
SignalStore.misc().setJobManagerVersion(JobManager.CURRENT_VERSION);
|
||||
PlainTextKeyValueStore.setLastVersionCode(BuildConfig.VERSION_CODE);
|
||||
TextSecurePreferences.setHasSeenStickerIntroTooltip(context, true);
|
||||
SignalStore.tooltips().markStickerIntroTooltipSeen();
|
||||
SignalStore.settings().setPassphraseDisabled(true);
|
||||
SignalStore.settings().setReadReceiptsEnabled(true);
|
||||
SignalStore.settings().setTypingIndicatorsEnabled(true);
|
||||
@@ -56,7 +56,9 @@ public final class AppInitialization {
|
||||
SignalStore.onboarding().clearAll();
|
||||
SignalStore.settings().setPassphraseDisabled(true);
|
||||
SignalStore.notificationProfile().setHasSeenTooltip(true);
|
||||
TextSecurePreferences.onPostBackupRestore(context);
|
||||
if (NotificationChannels.supported()) {
|
||||
NotificationChannels.getInstance().updateMessageVibrate(SignalStore.settings().isMessageVibrateEnabled());
|
||||
}
|
||||
SignalStore.settings().setPassphraseDisabled(true);
|
||||
AppDependencies.getJobManager().addAll(BlessedPacks.getFirstInstallJobs());
|
||||
EmojiSearchIndexDownloadJob.scheduleImmediately();
|
||||
@@ -82,9 +84,9 @@ public final class AppInitialization {
|
||||
Log.w(TAG, "onRepairFirstEverAppLaunch()");
|
||||
|
||||
PlainTextKeyValueStore.setAppMigrationVersion(ApplicationMigrations.CURRENT_VERSION);
|
||||
TextSecurePreferences.setJobManagerVersion(context, JobManager.CURRENT_VERSION);
|
||||
SignalStore.misc().setJobManagerVersion(JobManager.CURRENT_VERSION);
|
||||
PlainTextKeyValueStore.setLastVersionCode(BuildConfig.VERSION_CODE);
|
||||
TextSecurePreferences.setHasSeenStickerIntroTooltip(context, true);
|
||||
SignalStore.tooltips().markStickerIntroTooltipSeen();
|
||||
SignalStore.settings().setPassphraseDisabled(true);
|
||||
AppDependencies.getMegaphoneRepository().onFirstEverAppLaunch();
|
||||
SignalStore.onFirstEverAppLaunch();
|
||||
|
||||
@@ -132,7 +132,6 @@ import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
|
||||
import org.thoughtcrime.securesms.util.SignalUncaughtExceptionHandler;
|
||||
import org.thoughtcrime.securesms.util.SqlCipherLogTarget;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.VersionTracker;
|
||||
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket;
|
||||
@@ -459,14 +458,14 @@ public class ApplicationContext extends Application implements AppForegroundObse
|
||||
}
|
||||
|
||||
private void initializeFirstEverAppLaunch() {
|
||||
if (TextSecurePreferences.getFirstInstallVersion(this) == -1) {
|
||||
if (SignalStore.misc().getFirstInstallVersion() == -1) {
|
||||
if (!SignalDatabase.databaseFileExists(this) || VersionTracker.getDaysSinceFirstInstalled(this) < 365) {
|
||||
Log.i(TAG, "First ever app launch!");
|
||||
AppInitialization.onFirstEverAppLaunch(this);
|
||||
}
|
||||
|
||||
Log.i(TAG, "Setting first install version to " + BuildConfig.CANONICAL_VERSION_CODE);
|
||||
TextSecurePreferences.setFirstInstallVersion(this, BuildConfig.CANONICAL_VERSION_CODE);
|
||||
SignalStore.misc().setFirstInstallVersion(BuildConfig.CANONICAL_VERSION_CODE);
|
||||
} else if (!SignalStore.settings().getPassphraseDisabled() && VersionTracker.getDaysSinceFirstInstalled(this) < 90) {
|
||||
Log.i(TAG, "Detected a new install that doesn't have passphrases disabled -- assuming bad initialization.");
|
||||
AppInitialization.onRepairFirstEverAppLaunch(this);
|
||||
@@ -586,7 +585,7 @@ public class ApplicationContext extends Application implements AppForegroundObse
|
||||
}
|
||||
|
||||
private void executePendingContactSync() {
|
||||
if (TextSecurePreferences.needsFullContactSync(this)) {
|
||||
if (SignalStore.misc().getNeedsFullContactSync()) {
|
||||
AppDependencies.getJobManager().add(new MultiDeviceContactUpdateJob(true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.search.SearchRepository;
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModelList;
|
||||
@@ -222,7 +221,7 @@ public final class ContactSelectionListFragment extends LoggingFragment {
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
if (hasContactsPermissions(requireContext()) && !TextSecurePreferences.hasSuccessfullyRetrievedDirectory(getActivity())) {
|
||||
if (hasContactsPermissions(requireContext()) && !SignalStore.misc().getHasSuccessfullyRetrievedDirectory()) {
|
||||
handleContactPermissionGranted();
|
||||
} else {
|
||||
requireActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
||||
@@ -441,7 +440,7 @@ public final class ContactSelectionListFragment extends LoggingFragment {
|
||||
.ifNecessary()
|
||||
.onAllGranted(() -> {
|
||||
contactSearchView.setAlpha(0.5f);
|
||||
if (!TextSecurePreferences.hasSuccessfullyRetrievedDirectory(getActivity())) {
|
||||
if (!SignalStore.misc().getHasSuccessfullyRetrievedDirectory()) {
|
||||
handleContactPermissionGranted();
|
||||
} else {
|
||||
contactSearchViewModel.refresh();
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.thoughtcrime.securesms.restore.RestoreActivity;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.AppStartup;
|
||||
import org.thoughtcrime.securesms.util.Environment;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -175,7 +174,7 @@ public abstract class PassphraseRequiredActivity extends BaseActivity implements
|
||||
return STATE_PROMPT_PASSPHRASE;
|
||||
} else if (ApplicationMigrations.isUpdate(this) && ApplicationMigrations.isUiBlockingMigrationRunning()) {
|
||||
return STATE_UI_BLOCKING_UPGRADE;
|
||||
} else if (!TextSecurePreferences.hasPromptedPushRegistration(this)) {
|
||||
} else if (!SignalStore.registration().getHasPromptedPushRegistration()) {
|
||||
return STATE_WELCOME_PUSH_SCREEN;
|
||||
} else if (shouldResumeLinkingRegistration()) {
|
||||
return STATE_RESUME_LINKING_REG;
|
||||
@@ -251,7 +250,7 @@ public abstract class PassphraseRequiredActivity extends BaseActivity implements
|
||||
|
||||
private Intent getUiBlockingUpgradeIntent() {
|
||||
return getRoutedIntent(ApplicationMigrationActivity.class,
|
||||
TextSecurePreferences.hasPromptedPushRegistration(this)
|
||||
SignalStore.registration().getHasPromptedPushRegistration()
|
||||
? getConversationListIntent()
|
||||
: getPushRegistrationIntent());
|
||||
}
|
||||
|
||||
+3
-3
@@ -12,9 +12,9 @@ import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||
import org.thoughtcrime.securesms.jobs.ApkUpdateJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.service.PersistentAlarmManagerListener;
|
||||
import org.thoughtcrime.securesms.util.Environment;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -26,7 +26,7 @@ public class ApkUpdateRefreshListener extends PersistentAlarmManagerListener {
|
||||
|
||||
@Override
|
||||
protected long getNextScheduledExecutionTime(Context context) {
|
||||
return TextSecurePreferences.getUpdateApkRefreshTime(context);
|
||||
return SignalStore.apkUpdate().getRefreshTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -39,7 +39,7 @@ public class ApkUpdateRefreshListener extends PersistentAlarmManagerListener {
|
||||
}
|
||||
|
||||
long newTime = System.currentTimeMillis() + INTERVAL;
|
||||
TextSecurePreferences.setUpdateApkRefreshTime(context, newTime);
|
||||
SignalStore.apkUpdate().setRefreshTime(newTime);
|
||||
|
||||
return newTime;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class BackupDialog {
|
||||
.takePersistableUriPermission(backupDirectoryUri, takeFlags);
|
||||
}
|
||||
|
||||
BackupPassphrase.set(context, Util.join(password, " "));
|
||||
SignalStore.backup().setV1BackupPassphrase(Util.join(password, " "));
|
||||
SignalStore.settings().setLocalBackupNextTime(0);
|
||||
SignalStore.settings().setBackupEnabled(true);
|
||||
LocalBackupListener.schedule(context);
|
||||
@@ -177,7 +177,7 @@ public class BackupDialog {
|
||||
|
||||
positiveButton.setOnClickListener(v -> {
|
||||
String passphrase = prompt.getText().toString();
|
||||
if (passphrase.equals(BackupPassphrase.get(context))) {
|
||||
if (passphrase.equals(SignalStore.backup().getV1BackupPassphrase())) {
|
||||
Toast.makeText(context, R.string.BackupDialog_you_successfully_entered_your_backup_passphrase, Toast.LENGTH_SHORT).show();
|
||||
dialog.dismiss();
|
||||
} else {
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package org.thoughtcrime.securesms.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.core.util.crypto.KeyStoreHelper;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
/**
|
||||
* Allows the getting and setting of the backup passphrase, which is stored encrypted on API >= 23.
|
||||
*/
|
||||
public final class BackupPassphrase {
|
||||
|
||||
private BackupPassphrase() {
|
||||
}
|
||||
|
||||
private static final String TAG = Log.tag(BackupPassphrase.class);
|
||||
|
||||
public static @Nullable String get(@NonNull Context context) {
|
||||
String passphrase = TextSecurePreferences.getBackupPassphrase(context);
|
||||
String encryptedPassphrase = TextSecurePreferences.getEncryptedBackupPassphrase(context);
|
||||
|
||||
if (passphrase == null && encryptedPassphrase == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (encryptedPassphrase == null) {
|
||||
Log.i(TAG, "Migrating to encrypted passphrase.");
|
||||
set(context, passphrase);
|
||||
encryptedPassphrase = TextSecurePreferences.getEncryptedBackupPassphrase(context);
|
||||
if (encryptedPassphrase == null) throw new AssertionError("Passphrase migration failed");
|
||||
}
|
||||
|
||||
KeyStoreHelper.SealedData data = KeyStoreHelper.SealedData.fromString(encryptedPassphrase);
|
||||
return stripSpaces(new String(KeyStoreHelper.unseal(data)));
|
||||
}
|
||||
|
||||
public static void set(@NonNull Context context, @Nullable String passphrase) {
|
||||
if (passphrase == null) {
|
||||
TextSecurePreferences.setBackupPassphrase(context, null);
|
||||
TextSecurePreferences.setEncryptedBackupPassphrase(context, null);
|
||||
} else {
|
||||
KeyStoreHelper.SealedData encryptedPassphrase = KeyStoreHelper.seal(passphrase.getBytes());
|
||||
TextSecurePreferences.setEncryptedBackupPassphrase(context, encryptedPassphrase.serialize());
|
||||
TextSecurePreferences.setBackupPassphrase(context, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static String stripSpaces(@Nullable String passphrase) {
|
||||
return passphrase != null ? passphrase.replace(" ", "") : null;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import org.signal.core.util.Stopwatch;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.core.models.database.AttachmentId;
|
||||
import org.thoughtcrime.securesms.backup.proto.KeyValue;
|
||||
import org.thoughtcrime.securesms.backup.proto.SharedPreference;
|
||||
import org.thoughtcrime.securesms.backup.proto.SqlStatement;
|
||||
import org.signal.core.util.crypto.AttachmentSecret;
|
||||
import org.signal.core.util.crypto.ClassicDecryptingPartInputStream;
|
||||
|
||||
@@ -151,7 +151,6 @@ import org.thoughtcrime.securesms.service.BackupMediaRestoreService
|
||||
import org.thoughtcrime.securesms.service.BackupProgressService
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.toMillis
|
||||
import org.whispersystems.signalservice.api.link.TransferArchiveResponse
|
||||
import org.whispersystems.signalservice.api.messages.AttachmentTransferProgress
|
||||
@@ -485,7 +484,7 @@ object BackupRepository {
|
||||
return false
|
||||
}
|
||||
|
||||
val isRegistered = SignalStore.account.isRegistered && !TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application)
|
||||
val isRegistered = SignalStore.account.isRegistered && !SignalStore.account.isUnauthorizedReceived
|
||||
if (!isRegistered) {
|
||||
Log.d(TAG, "[shouldDisplayCouldNotCompleteBackupSheet] Not displaying sheet for unregistered user.")
|
||||
return false
|
||||
|
||||
-2
@@ -60,8 +60,6 @@ object AccountDataArchiveProcessor {
|
||||
private val TAG = Log.tag(AccountDataArchiveProcessor::class)
|
||||
|
||||
fun export(db: SignalDatabase, signalStore: SignalStore, exportState: ExportState, emitter: BackupFrameEmitter) {
|
||||
val context = AppDependencies.application
|
||||
|
||||
val selfId = db.recipientTable.getByAci(signalStore.accountValues.aci!!).get()
|
||||
val selfRecord = db.recipientTable.getRecordForSync(selfId)!!
|
||||
|
||||
|
||||
@@ -25,12 +25,11 @@ import org.thoughtcrime.securesms.banner.ui.compose.Action
|
||||
import org.thoughtcrime.securesms.banner.ui.compose.DefaultBanner
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.PowerManagerCompat
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
|
||||
class DozeBanner(private val context: Context) : Banner<Unit>() {
|
||||
|
||||
override val enabled: Boolean
|
||||
get() = !SignalStore.account.fcmEnabled && !TextSecurePreferences.hasPromptedOptimizeDoze(context) && !ServiceUtil.getPowerManager(context).isIgnoringBatteryOptimizations(context.packageName)
|
||||
get() = !SignalStore.account.fcmEnabled && !SignalStore.uiHints.hasPromptedOptimizeDoze() && !ServiceUtil.getPowerManager(context).isIgnoringBatteryOptimizations(context.packageName)
|
||||
|
||||
override val dataFlow: Flow<Unit>
|
||||
get() = flowOf(Unit)
|
||||
@@ -62,7 +61,7 @@ class DozeBanner(private val context: Context) : Banner<Unit>() {
|
||||
}
|
||||
|
||||
private fun markAsPrompted() {
|
||||
TextSecurePreferences.setPromptedOptimizeDoze(context, true)
|
||||
SignalStore.uiHints.setHasPromptedOptimizeDoze(true)
|
||||
enabledState.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.banner.Banner
|
||||
import org.thoughtcrime.securesms.banner.ui.compose.DefaultBanner
|
||||
import org.thoughtcrime.securesms.banner.ui.compose.Importance
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
|
||||
class ServiceOutageBanner(val context: Context) : Banner<Unit>() {
|
||||
|
||||
override val enabled: Boolean
|
||||
get() = TextSecurePreferences.getServiceOutage(context)
|
||||
get() = SignalStore.misc.serviceOutage
|
||||
|
||||
override val dataFlow: Flow<Unit> = flowOf(Unit)
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.net.DeviceTransferBlockingInterceptor
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.registration.ui.RegistrationActivity
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
|
||||
/**
|
||||
* A banner displayed when the client is unauthorized (deregistered).
|
||||
@@ -35,7 +34,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
class UnauthorizedBanner(val context: Context) : Banner<Unit>() {
|
||||
|
||||
override val enabled: Boolean
|
||||
get() = TextSecurePreferences.isUnauthorizedReceived(context) || !SignalStore.account.isRegistered
|
||||
get() = SignalStore.account.isUnauthorizedReceived || !SignalStore.account.isRegistered
|
||||
|
||||
override val dataFlow: Flow<Unit>
|
||||
get() = flowOf(Unit)
|
||||
|
||||
@@ -1,260 +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 android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
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 androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.DialogPreference;
|
||||
import androidx.preference.PreferenceDialogFragmentCompat;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.CustomDefaultPreference.CustomDefaultPreferenceDialogFragmentCompat.CustomPreferenceValidator;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
|
||||
public class CustomDefaultPreference extends DialogPreference {
|
||||
|
||||
private static final String TAG = Log.tag(CustomDefaultPreference.class);
|
||||
|
||||
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 TextSecurePreferences.getBooleanPreference(getContext(), customToggle, false);
|
||||
}
|
||||
|
||||
private void setCustom(boolean custom) {
|
||||
TextSecurePreferences.setBooleanPreference(getContext(), customToggle, custom);
|
||||
}
|
||||
|
||||
private String getCustomValue() {
|
||||
return TextSecurePreferences.getStringPreference(getContext(), customPreference, "");
|
||||
}
|
||||
|
||||
private void setCustomValue(String value) {
|
||||
TextSecurePreferences.setStringPreference(getContext(), 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -8,8 +8,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.util.PlayStoreUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.VersionTracker;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -22,10 +22,10 @@ public class RatingManager {
|
||||
private static final String TAG = Log.tag(RatingManager.class);
|
||||
|
||||
public static void showRatingDialogIfNecessary(Context context) {
|
||||
if (!TextSecurePreferences.isRatingEnabled(context) || BuildConfig.MANAGES_APP_UPDATES) return;
|
||||
if (!SignalStore.misc().getRatingEnabled() || BuildConfig.MANAGES_APP_UPDATES) return;
|
||||
|
||||
long daysSinceInstall = VersionTracker.getDaysSinceFirstInstalled(context);
|
||||
long laterTimestamp = TextSecurePreferences.getRatingLaterTimestamp(context);
|
||||
long laterTimestamp = SignalStore.misc().getRatingLaterTimestamp();
|
||||
|
||||
if (daysSinceInstall >= DAYS_SINCE_INSTALL_THRESHOLD &&
|
||||
System.currentTimeMillis() >= laterTimestamp)
|
||||
@@ -41,21 +41,21 @@ public class RatingManager {
|
||||
.setPositiveButton(R.string.RatingManager_rate_now, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
TextSecurePreferences.setRatingEnabled(context, false);
|
||||
SignalStore.misc().setRatingEnabled(false);
|
||||
PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(context);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.RatingManager_no_thanks, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
TextSecurePreferences.setRatingEnabled(context, false);
|
||||
SignalStore.misc().setRatingEnabled(false);
|
||||
}
|
||||
})
|
||||
.setNeutralButton(R.string.RatingManager_later, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
long waitUntil = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(DAYS_UNTIL_REPROMPT_THRESHOLD);
|
||||
TextSecurePreferences.setRatingLaterTimestamp(context, waitUntil);
|
||||
SignalStore.misc().setRatingLaterTimestamp(waitUntil);
|
||||
}
|
||||
})
|
||||
.show();
|
||||
|
||||
+3
@@ -32,6 +32,9 @@ public class RecentEmojiPageModel implements EmojiPageModel {
|
||||
private static final int EMOJI_LRU_SIZE = 50;
|
||||
public static final String KEY = "Recents";
|
||||
|
||||
/** The shared-prefs entry this model persists its LRU into. */
|
||||
public static final String RECENT_STORAGE_KEY = "pref_recent_emoji2";
|
||||
|
||||
private final SharedPreferences prefs;
|
||||
private final String preferenceName;
|
||||
private final LinkedHashSet<String> recentlyUsed;
|
||||
|
||||
+2
-4
@@ -10,10 +10,8 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.InAppDona
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.RecurringInAppPaymentRepository
|
||||
import org.thoughtcrime.securesms.conversationlist.model.UnreadPaymentsLiveData
|
||||
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.livedata.Store
|
||||
|
||||
class AppSettingsViewModel : ViewModel() {
|
||||
@@ -24,7 +22,7 @@ class AppSettingsViewModel : ViewModel() {
|
||||
unreadPaymentsCount = 0,
|
||||
hasExpiredGiftBadge = SignalStore.inAppPayments.getExpiredGiftBadge() != null,
|
||||
allowUserToGoToDonationManagementScreen = SignalStore.inAppPayments.isLikelyASustainer() || InAppDonations.hasAtLeastOnePaymentMethodAvailable(),
|
||||
userUnregistered = TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application) || !SignalStore.account.isRegistered,
|
||||
userUnregistered = SignalStore.account.isUnauthorizedReceived || !SignalStore.account.isRegistered,
|
||||
clientDeprecated = SignalStore.misc.isClientDeprecated
|
||||
)
|
||||
)
|
||||
@@ -56,7 +54,7 @@ class AppSettingsViewModel : ViewModel() {
|
||||
store.update {
|
||||
it.copy(
|
||||
clientDeprecated = SignalStore.misc.isClientDeprecated,
|
||||
userUnregistered = TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application) || !SignalStore.account.isRegistered
|
||||
userUnregistered = SignalStore.account.isUnauthorizedReceived || !SignalStore.account.isRegistered
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -12,11 +12,9 @@ import org.signal.core.util.concurrent.SignalDispatchers
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpRepository
|
||||
import org.thoughtcrime.securesms.components.settings.app.account.passkeys.AppPasskeysRepository
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.lock.v2.PinKeyboardType
|
||||
import org.thoughtcrime.securesms.pin.SvrRepository
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.kbs.PinHashUtil
|
||||
import java.io.IOException
|
||||
|
||||
@@ -42,7 +40,7 @@ class AccountSettingsRepository {
|
||||
|
||||
fun isRegistrationLockEnabled(): Boolean = SignalStore.svr.isRegistrationLockEnabled
|
||||
|
||||
fun isUserUnregistered(): Boolean = TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application)
|
||||
fun isUserUnregistered(): Boolean = SignalStore.account.isUnauthorizedReceived
|
||||
|
||||
fun isClientDeprecated(): Boolean = SignalStore.misc.isClientDeprecated
|
||||
|
||||
|
||||
+2
-4
@@ -17,7 +17,6 @@ import kotlinx.coroutines.withContext
|
||||
import org.signal.core.ui.util.StorageUtil
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.backup.BackupPassphrase
|
||||
import org.thoughtcrime.securesms.backup.LocalExportProgress
|
||||
import org.thoughtcrime.securesms.components.settings.app.backups.remote.BackupKeyCredentialManagerHandler
|
||||
import org.thoughtcrime.securesms.components.settings.app.backups.remote.BackupKeySaveState
|
||||
@@ -27,7 +26,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.keyvalue.protos.LocalBackupCreationProgress
|
||||
import org.thoughtcrime.securesms.util.BackupUtil
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.formatHours
|
||||
import java.time.LocalTime
|
||||
import java.util.Locale
|
||||
@@ -85,7 +83,7 @@ class LocalBackupsViewModel : ViewModel(), BackupKeyCredentialManagerHandler {
|
||||
val context = AppDependencies.application
|
||||
val backupTime = LocalTime.of(SignalStore.settings.backupHour, SignalStore.settings.backupMinute).formatHours(context)
|
||||
|
||||
val userUnregistered = TextSecurePreferences.isUnauthorizedReceived(context) || !SignalStore.account.isRegistered
|
||||
val userUnregistered = SignalStore.account.isUnauthorizedReceived || !SignalStore.account.isRegistered
|
||||
val clientDeprecated = SignalStore.misc.isClientDeprecated
|
||||
val legacyLocalBackupsEnabled = SignalStore.settings.isBackupEnabled && BackupUtil.canUserAccessBackupDirectory(context)
|
||||
val canTurnOn = legacyLocalBackupsEnabled || (!userUnregistered && !clientDeprecated)
|
||||
@@ -143,7 +141,7 @@ class LocalBackupsViewModel : ViewModel(), BackupKeyCredentialManagerHandler {
|
||||
|
||||
SignalStore.backup.newLocalBackupsDirectory = SignalStore.settings.signalBackupDirectory?.toString()
|
||||
|
||||
BackupPassphrase.set(context, null)
|
||||
SignalStore.backup.v1BackupPassphrase = null
|
||||
SignalStore.settings.isBackupEnabled = false
|
||||
BackupUtil.deleteAllBackups()
|
||||
}
|
||||
|
||||
+1
-2
@@ -50,7 +50,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.keyvalue.protos.ArchiveUploadProgressState
|
||||
import org.thoughtcrime.securesms.util.Environment
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@@ -71,7 +70,7 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
backupState = BackupStateObserver.getNonIOBackupState(),
|
||||
backupsEnabled = SignalStore.backup.areBackupsEnabled,
|
||||
canBackupMessagesJobRun = BackupMessagesConstraint.isMet(AppDependencies.application),
|
||||
canViewBackupKey = !TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application),
|
||||
canViewBackupKey = !SignalStore.account.isUnauthorizedReceived,
|
||||
lastBackupTimestamp = SignalStore.backup.lastBackupTime,
|
||||
canBackUpUsingCellular = SignalStore.backup.backupWithCellular,
|
||||
canRestoreUsingCellular = SignalStore.backup.restoreWithCellular,
|
||||
|
||||
+1
-2
@@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.BackupUtil
|
||||
import org.thoughtcrime.securesms.util.ConversationUtil
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
|
||||
class ChatsSettingsViewModel @JvmOverloads constructor(
|
||||
private val repository: ChatsSettingsRepository = ChatsSettingsRepository()
|
||||
@@ -34,7 +33,7 @@ class ChatsSettingsViewModel @JvmOverloads constructor(
|
||||
enterKeySends = SignalStore.settings.isEnterKeySends,
|
||||
localBackupsEnabled = SignalStore.settings.isBackupEnabled && BackupUtil.canUserAccessBackupDirectory(AppDependencies.application),
|
||||
folderCount = 0,
|
||||
userUnregistered = TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application) || !SignalStore.account.isRegistered,
|
||||
userUnregistered = SignalStore.account.isUnauthorizedReceived || !SignalStore.account.isRegistered,
|
||||
clientDeprecated = SignalStore.misc.isClientDeprecated,
|
||||
isPlaintextExportEnabled = RemoteConfig.localPlaintextExport,
|
||||
chatExportState = ChatExportState.None
|
||||
|
||||
+1
-2
@@ -57,7 +57,6 @@ import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import java.io.IOException
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
@@ -74,7 +73,7 @@ class ConversationSettingsRepository(
|
||||
) {
|
||||
|
||||
fun isDeprecatedOrUnregistered(): Boolean {
|
||||
return SignalStore.misc.isClientDeprecated || TextSecurePreferences.isUnauthorizedReceived(context)
|
||||
return SignalStore.misc.isClientDeprecated || SignalStore.account.isUnauthorizedReceived
|
||||
}
|
||||
|
||||
fun isInternalRecipientDetailsEnabled(): Boolean {
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.registration.util.RegistrationUtil
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.util.SignalE164Util
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import java.io.IOException
|
||||
import java.util.Calendar
|
||||
@@ -192,13 +191,13 @@ object ContactDiscovery {
|
||||
)
|
||||
stopwatch.split("contact-sync")
|
||||
|
||||
if (TextSecurePreferences.hasSuccessfullyRetrievedDirectory(context) && notifyOfNewUsers) {
|
||||
if (SignalStore.misc.hasSuccessfullyRetrievedDirectory && notifyOfNewUsers) {
|
||||
val systemContacts: Set<RecipientId> = SignalDatabase.recipients.getSystemContacts().toSet()
|
||||
val newlyRegisteredSystemContacts: Set<RecipientId> = (result.registeredIds - preExistingRegisteredIds).intersect(systemContacts)
|
||||
|
||||
notifyNewUsers(context, newlyRegisteredSystemContacts)
|
||||
} else {
|
||||
TextSecurePreferences.setHasSuccessfullyRetrievedDirectory(context, true)
|
||||
SignalStore.misc.hasSuccessfullyRetrievedDirectory = true
|
||||
}
|
||||
stopwatch.split("notify")
|
||||
} else {
|
||||
|
||||
+1
-2
@@ -8,7 +8,6 @@ import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.search.EmojiSearchRepository
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.AnyMappingModel
|
||||
|
||||
/**
|
||||
@@ -18,7 +17,7 @@ import org.thoughtcrime.securesms.util.adapter.mapping.AnyMappingModel
|
||||
*/
|
||||
class InlineQueryViewModel(
|
||||
private val emojiSearchRepository: EmojiSearchRepository = EmojiSearchRepository(AppDependencies.application),
|
||||
private val recentEmojis: RecentEmojiPageModel = RecentEmojiPageModel(AppDependencies.application, TextSecurePreferences.RECENT_STORAGE_KEY)
|
||||
private val recentEmojis: RecentEmojiPageModel = RecentEmojiPageModel(AppDependencies.application, RecentEmojiPageModel.RECENT_STORAGE_KEY)
|
||||
) : ViewModel() {
|
||||
|
||||
private val querySubject: PublishSubject<InlineQuery> = PublishSubject.create()
|
||||
|
||||
+1
-2
@@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.conversation.v2.ConversationRecipientRepositor
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.search.EmojiSearchRepository
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.AnyMappingModel
|
||||
|
||||
/**
|
||||
@@ -24,7 +23,7 @@ class InlineQueryViewModelV2(
|
||||
private val recipientRepository: ConversationRecipientRepository,
|
||||
private val mentionsPickerRepository: MentionsPickerRepositoryV2 = MentionsPickerRepositoryV2(),
|
||||
private val emojiSearchRepository: EmojiSearchRepository = EmojiSearchRepository(AppDependencies.application),
|
||||
private val recentEmojis: RecentEmojiPageModel = RecentEmojiPageModel(AppDependencies.application, TextSecurePreferences.RECENT_STORAGE_KEY)
|
||||
private val recentEmojis: RecentEmojiPageModel = RecentEmojiPageModel(AppDependencies.application, RecentEmojiPageModel.RECENT_STORAGE_KEY)
|
||||
) : ViewModel() {
|
||||
|
||||
private val querySubject: PublishSubject<InlineQuery> = PublishSubject.create()
|
||||
|
||||
+6
-7
@@ -391,7 +391,6 @@ import org.thoughtcrime.securesms.util.PlayStoreUtil
|
||||
import org.thoughtcrime.securesms.util.Projection
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.SignalLocalMetrics
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.UriUtil
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.atMidnight
|
||||
@@ -583,7 +582,7 @@ class ConversationFragment :
|
||||
private val colorizer = ColorizerV2()
|
||||
private val textDraftSaveDebouncer = Debouncer(500)
|
||||
private val doubleTapToEditDebouncer = DoubleClickDebouncer(200)
|
||||
private val recentEmojis: RecentEmojiPageModel by lazy { RecentEmojiPageModel(AppDependencies.application, TextSecurePreferences.RECENT_STORAGE_KEY) }
|
||||
private val recentEmojis: RecentEmojiPageModel by lazy { RecentEmojiPageModel(AppDependencies.application, RecentEmojiPageModel.RECENT_STORAGE_KEY) }
|
||||
private val nicknameEditActivityLauncher = registerForActivityResult(NicknameActivity.Contract()) {}
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
@@ -1793,7 +1792,7 @@ class ConversationFragment :
|
||||
}
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.getServiceOutage(context)) {
|
||||
if (SignalStore.misc.serviceOutage) {
|
||||
AppDependencies.jobManager.add(ServiceOutageDetectionJob())
|
||||
}
|
||||
|
||||
@@ -2789,7 +2788,7 @@ class ConversationFragment :
|
||||
}
|
||||
|
||||
private fun initializeMediaKeyboard() {
|
||||
val stickerIntro: Boolean = !TextSecurePreferences.hasSeenStickerIntroTooltip(requireContext())
|
||||
val stickerIntro: Boolean = !SignalStore.tooltips.hasSeenStickerIntroTooltip()
|
||||
|
||||
inputPanel.showMediaKeyboardToggle(true)
|
||||
inputPanel.setMediaKeyboardToggleMode(preferredKeyboardPage())
|
||||
@@ -3076,7 +3075,7 @@ class ConversationFragment :
|
||||
}
|
||||
|
||||
private fun maybeShowSwipeToReplyTooltip() {
|
||||
if (!TextSecurePreferences.hasSeenSwipeToReplyTooltip(requireContext())) {
|
||||
if (!SignalStore.tooltips.hasSeenSwipeToReplyTooltip()) {
|
||||
val tooltipText = if (ViewUtil.isLtr(requireContext())) {
|
||||
R.string.ConversationFragment_you_can_swipe_to_the_right_reply
|
||||
} else {
|
||||
@@ -3085,7 +3084,7 @@ class ConversationFragment :
|
||||
|
||||
snackbar(tooltipText)
|
||||
|
||||
TextSecurePreferences.setHasSeenSwipeToReplyTooltip(requireContext(), true)
|
||||
SignalStore.tooltips.markSwipeToReplyTooltipSeen()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5656,7 +5655,7 @@ class ConversationFragment :
|
||||
return
|
||||
}
|
||||
|
||||
if (!TextSecurePreferences.hasSeenStickerIntroTooltip(requireContext())) {
|
||||
if (!SignalStore.tooltips.hasSeenStickerIntroTooltip()) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@ import androidx.lifecycle.ViewModel
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.TooltipPopup
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
|
||||
/**
|
||||
* Any and all tooltips that the conversation can display, and a light amount of related presentation logic.
|
||||
@@ -30,7 +30,7 @@ class ConversationTooltips(fragment: Fragment) {
|
||||
.setTextColor(ContextCompat.getColor(anchor.context, R.color.core_white))
|
||||
.setText(R.string.ConversationActivity_new_say_it_with_stickers)
|
||||
.setOnDismissListener {
|
||||
TextSecurePreferences.setHasSeenStickerIntroTooltip(anchor.context, true)
|
||||
SignalStore.tooltips.markStickerIntroTooltipSeen()
|
||||
onDismiss()
|
||||
}
|
||||
.show(TooltipPopup.POSITION_ABOVE)
|
||||
|
||||
+1
-2
@@ -97,7 +97,6 @@ import org.thoughtcrime.securesms.sms.MessageSender
|
||||
import org.thoughtcrime.securesms.util.BubbleUtil
|
||||
import org.thoughtcrime.securesms.util.ConversationUtil
|
||||
import org.thoughtcrime.securesms.util.NetworkUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.hasGiftBadge
|
||||
import org.thoughtcrime.securesms.util.rx.RxStore
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
|
||||
@@ -320,7 +319,7 @@ class ConversationViewModel(
|
||||
messageRequestState = messageRequestRepository.getMessageRequestState(recipient, threadId),
|
||||
groupRecord = groupRecord.orNull(),
|
||||
isClientExpired = SignalStore.misc.isClientDeprecated,
|
||||
isUnauthorized = TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application),
|
||||
isUnauthorized = SignalStore.account.isUnauthorizedReceived,
|
||||
threadContainsSms = !recipient.isRegistered && !recipient.isPushGroup && !recipient.isSelf && messageRequestRepository.threadContainsSms(threadId)
|
||||
)
|
||||
}.doOnNext {
|
||||
|
||||
+1
-2
@@ -168,7 +168,6 @@ import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
|
||||
import org.thoughtcrime.securesms.util.SignalProxyUtil;
|
||||
import org.thoughtcrime.securesms.util.SnapToTopDataObserver;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.PagingMappingAdapter;
|
||||
import org.thoughtcrime.securesms.verify.SelfVerificationFailureSheet;
|
||||
@@ -453,7 +452,7 @@ public class ConversationListFragment extends MainFragment implements Conversati
|
||||
|
||||
if (SignalStore.account().isRegistered() &&
|
||||
SignalStore.registration().isRegistrationComplete() &&
|
||||
!TextSecurePreferences.isUnauthorizedReceived(requireContext()) &&
|
||||
!SignalStore.account().isUnauthorizedReceived() &&
|
||||
SignalStore.settings().getAutomaticVerificationEnabled() &&
|
||||
SignalStore.misc().getHasKeyTransparencyFailure() &&
|
||||
!SignalStore.misc().getHasSeenKeyTransparencyFailure()) {
|
||||
|
||||
-1
@@ -16,7 +16,6 @@ import org.signal.libsignal.protocol.state.PreKeyRecord;
|
||||
import org.signal.libsignal.protocol.state.SessionRecord;
|
||||
import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountDataStore;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
|
||||
|
||||
@@ -2458,7 +2458,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
)
|
||||
} ?: Recipient.live(recipientId).get()
|
||||
} else {
|
||||
RecipientCreator.forIndividual(context, recipientSettings)
|
||||
RecipientCreator.forIndividual(recipientSettings)
|
||||
}
|
||||
|
||||
val hasReadReceipt = SignalStore.settings.isReadReceiptsEnabled && cursor.requireBoolean(HAS_READ_RECEIPT)
|
||||
|
||||
+3
-4
@@ -120,7 +120,6 @@ import org.thoughtcrime.securesms.util.Environment;
|
||||
import org.thoughtcrime.securesms.util.FrameRateTracker;
|
||||
import org.thoughtcrime.securesms.util.PreKeyBatcher;
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.video.exo.GiphyMp4Cache;
|
||||
import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool;
|
||||
import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat;
|
||||
@@ -247,7 +246,7 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
||||
|
||||
@Override
|
||||
public @NonNull LiveRecipientCache provideRecipientCache() {
|
||||
return new LiveRecipientCache(context);
|
||||
return new LiveRecipientCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -262,7 +261,7 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
||||
.setConstraintFactories(JobManagerFactories.getConstraintFactories(context))
|
||||
.setConstraintObservers(JobManagerFactories.getConstraintObservers(context))
|
||||
.setJobStorage(new FastJobStorage(JobDatabase.getInstance(context)))
|
||||
.setJobMigrator(new JobMigrator(TextSecurePreferences.getJobManagerVersion(context), JobManager.CURRENT_VERSION, JobManagerFactories.getJobMigrations(context)))
|
||||
.setJobMigrator(new JobMigrator(SignalStore.misc().getJobManagerVersion(), JobManager.CURRENT_VERSION, JobManagerFactories.getJobMigrations(context)))
|
||||
.addReservedJobRunner(new FactoryJobPredicate(PushProcessMessageJob.KEY, MarkerJob.KEY))
|
||||
.addReservedJobRunner(new FactoryJobPredicate(AttachmentUploadJob.KEY, AttachmentCompressionJob.KEY))
|
||||
.addReservedJobRunner(new FactoryJobPredicate(
|
||||
@@ -421,7 +420,7 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
||||
};
|
||||
|
||||
SignalWebSocket.AuthenticatedWebSocket webSocket = new SignalWebSocket.AuthenticatedWebSocket(authFactory,
|
||||
() -> !SignalStore.misc().isClientDeprecated() && SignalStore.account().isRegistered() && !TextSecurePreferences.isUnauthorizedReceived(context) && !DeviceTransferBlockingInterceptor.getInstance().isBlockingNetwork() && !Environment.IS_INSTRUMENTATION,
|
||||
() -> !SignalStore.misc().isClientDeprecated() && SignalStore.account().isRegistered() && !SignalStore.account().isUnauthorizedReceived() && !DeviceTransferBlockingInterceptor.getInstance().isBlockingNetwork() && !Environment.IS_INSTRUMENTATION,
|
||||
sleepTimer,
|
||||
TimeUnit.SECONDS.toMillis(30));
|
||||
if (AppForegroundObserver.isForegrounded()) {
|
||||
|
||||
+1
-2
@@ -15,7 +15,6 @@ import org.signal.devicetransfer.NewDeviceRestoreStatus;
|
||||
import org.signal.devicetransfer.ServerTask;
|
||||
import org.thoughtcrime.securesms.AppInitialization;
|
||||
import org.thoughtcrime.securesms.backup.BackupEvent;
|
||||
import org.thoughtcrime.securesms.backup.BackupPassphrase;
|
||||
import org.thoughtcrime.securesms.backup.FullBackupImporter;
|
||||
import org.thoughtcrime.securesms.crypto.AppAttachmentSecretStore;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
@@ -50,7 +49,7 @@ public final class NewDeviceServerTask implements ServerTask {
|
||||
|
||||
String passphrase = SignalStore.account().getAccountEntropyPool().getValue();
|
||||
|
||||
BackupPassphrase.set(context, passphrase);
|
||||
SignalStore.backup().setV1BackupPassphrase(passphrase);
|
||||
FullBackupImporter.importFile(context,
|
||||
AttachmentSecretProvider.getInstance(context, AppAttachmentSecretStore.INSTANCE).getOrCreateAttachmentSecret(),
|
||||
database,
|
||||
|
||||
@@ -16,8 +16,8 @@ import org.thoughtcrime.securesms.jobmanager.impl.DefaultExecutorFactory;
|
||||
import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
|
||||
import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage;
|
||||
import org.thoughtcrime.securesms.jobs.MinimalJobSpec;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.signal.core.util.Debouncer;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.signal.core.util.Util;
|
||||
import org.signal.core.util.concurrent.FilteredExecutor;
|
||||
|
||||
@@ -87,7 +87,7 @@ public class JobManager implements ConstraintObserver.Notifier {
|
||||
jobStorage.init();
|
||||
|
||||
int latestVersion = configuration.getJobMigrator().migrate(jobStorage);
|
||||
TextSecurePreferences.setJobManagerVersion(application, latestVersion);
|
||||
SignalStore.misc().setJobManagerVersion(latestVersion);
|
||||
|
||||
jobController.init();
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.net.SignalNetwork
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
|
||||
/**
|
||||
* Reserves backupIds for both text+media. The intention is that every registered user should be doing this, so it should happen post-registration
|
||||
@@ -49,7 +48,7 @@ class ArchiveBackupIdReservationJob private constructor(parameters: Parameters)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||
if (SignalStore.account.isUnauthorizedReceived) {
|
||||
Log.w(TAG, "Not authorized. Skipping.")
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.messages.AttachmentTransferProgress
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ResumeLocationInvalidException
|
||||
@@ -90,7 +89,7 @@ class BackupMessagesJob private constructor(
|
||||
const val KEY = "BackupMessagesJob"
|
||||
|
||||
private fun isRegistered(): Boolean {
|
||||
return SignalStore.account.isRegistered && !TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application)
|
||||
return SignalStore.account.isRegistered && !SignalStore.account.isUnauthorizedReceived
|
||||
}
|
||||
|
||||
private fun isBackupAllowed(): Boolean {
|
||||
|
||||
@@ -18,7 +18,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.net.SignalNetwork
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess
|
||||
import kotlin.random.Random
|
||||
import kotlin.time.Duration.Companion.days
|
||||
@@ -93,7 +92,7 @@ class CheckKeyTransparencyJob private constructor(
|
||||
} else if (!SignalStore.registration.isRegistrationComplete) {
|
||||
Log.i(TAG, "Registration is not complete. Exiting.")
|
||||
false
|
||||
} else if (TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application)) {
|
||||
} else if (SignalStore.account.isUnauthorizedReceived) {
|
||||
Log.i(TAG, "Account is unauthorized. Exiting.")
|
||||
false
|
||||
} else if (!SignalStore.settings.automaticVerificationEnabled) {
|
||||
@@ -190,7 +189,7 @@ class CheckKeyTransparencyJob private constructor(
|
||||
* For others, it will only show once and only be cleared on the next successful verification.
|
||||
*/
|
||||
private fun markFailure() {
|
||||
if (SignalStore.account.isRegistered && !TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application)) {
|
||||
if (SignalStore.account.isRegistered && !SignalStore.account.isUnauthorizedReceived) {
|
||||
SignalStore.misc.hasKeyTransparencyFailure = true
|
||||
if (RemoteConfig.internalUser) {
|
||||
SignalStore.misc.hasSeenKeyTransparencyFailure = false
|
||||
|
||||
@@ -7,7 +7,6 @@ import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
|
||||
import org.whispersystems.signalservice.internal.util.StaticCredentialsProvider
|
||||
import org.whispersystems.signalservice.internal.websocket.OkHttpWebSocketConnection
|
||||
@@ -35,9 +34,8 @@ class CheckServiceReachabilityJob private constructor(params: Parameters) : Base
|
||||
@JvmStatic
|
||||
fun enqueueIfNecessary() {
|
||||
val isCensored = AppDependencies.signalServiceNetworkAccess.isCensored()
|
||||
val context = AppDependencies.application
|
||||
val timeSinceLastCheck = System.currentTimeMillis() - SignalStore.misc.lastCensorshipServiceReachabilityCheckTime
|
||||
if (SignalStore.account.isRegistered && !TextSecurePreferences.isUnauthorizedReceived(context) && isCensored && timeSinceLastCheck > TimeUnit.DAYS.toMillis(1)) {
|
||||
if (SignalStore.account.isRegistered && !SignalStore.account.isUnauthorizedReceived && isCensored && timeSinceLastCheck > TimeUnit.DAYS.toMillis(1)) {
|
||||
AppDependencies.jobManager.add(CheckServiceReachabilityJob())
|
||||
}
|
||||
}
|
||||
@@ -58,7 +56,7 @@ class CheckServiceReachabilityJob private constructor(params: Parameters) : Base
|
||||
return
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||
if (SignalStore.account.isUnauthorizedReceived) {
|
||||
Log.w(TAG, "Unauthorized received, skipping.")
|
||||
SignalStore.misc.lastCensorshipServiceReachabilityCheckTime = System.currentTimeMillis()
|
||||
return
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.thoughtcrime.securesms.messages.IncomingMessageObserver;
|
||||
import org.thoughtcrime.securesms.net.SignalNetwork;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.signal.core.util.PlayServicesUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.RequestResultUtil;
|
||||
import org.signal.network.exceptions.NonSuccessfulResponseCodeException;
|
||||
|
||||
@@ -73,7 +72,7 @@ public class FcmRefreshJob extends BaseJob {
|
||||
|
||||
@Override
|
||||
public void onRun() throws Exception {
|
||||
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||
if (SignalStore.account().isUnauthorizedReceived()) {
|
||||
Log.i(TAG, "No longer authorized. Ignoring.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.backup.BackupEvent;
|
||||
import org.thoughtcrime.securesms.backup.BackupFileIOError;
|
||||
import org.thoughtcrime.securesms.backup.BackupPassphrase;
|
||||
import org.thoughtcrime.securesms.backup.BackupVerifier;
|
||||
import org.thoughtcrime.securesms.backup.FullBackupExporter;
|
||||
import org.thoughtcrime.securesms.crypto.AppAttachmentSecretStore;
|
||||
@@ -27,6 +26,7 @@ import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.service.GenericForegroundService;
|
||||
import org.thoughtcrime.securesms.service.NotificationController;
|
||||
@@ -124,7 +124,7 @@ public final class LocalBackupJob extends BaseJob {
|
||||
EventBus.getDefault().register(updater);
|
||||
notification.setIndeterminateProgress();
|
||||
|
||||
String backupPassword = BackupPassphrase.get(context);
|
||||
String backupPassword = SignalStore.backup().getV1BackupPassphrase();
|
||||
File backupDirectory = StorageUtil.getOrCreateBackupDirectory();
|
||||
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US).format(new Date());
|
||||
String fileName = String.format("signal-%s.backup", timestamp);
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.backup.BackupEvent;
|
||||
import org.thoughtcrime.securesms.backup.BackupFileIOError;
|
||||
import org.thoughtcrime.securesms.backup.BackupPassphrase;
|
||||
import org.thoughtcrime.securesms.backup.BackupVerifier;
|
||||
import org.thoughtcrime.securesms.backup.FullBackupExporter;
|
||||
import org.thoughtcrime.securesms.crypto.AppAttachmentSecretStore;
|
||||
@@ -102,7 +101,7 @@ public final class LocalBackupJobApi29 extends BaseJob {
|
||||
notification.setIndeterminateProgress();
|
||||
}
|
||||
|
||||
String backupPassword = BackupPassphrase.get(context);
|
||||
String backupPassword = SignalStore.backup().getV1BackupPassphrase();
|
||||
DocumentFile backupDirectory = DocumentFile.fromTreeUri(context, backupDirectoryUri);
|
||||
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US).format(new Date());
|
||||
String fileName = String.format("signal-%s.backup", timestamp);
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.thoughtcrime.securesms.net.NotPushRegisteredException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
@@ -196,18 +195,18 @@ public class MultiDeviceContactUpdateJob extends BaseJob {
|
||||
throws IOException, UntrustedIdentityException, NetworkException, NoSessionException
|
||||
{
|
||||
boolean isAppVisible = AppForegroundObserver.isForegrounded();
|
||||
long timeSinceLastSync = System.currentTimeMillis() - TextSecurePreferences.getLastFullContactSyncTime(context);
|
||||
long timeSinceLastSync = System.currentTimeMillis() - SignalStore.misc().getLastFullContactSyncTime();
|
||||
|
||||
Log.d(TAG, "Requesting a full contact sync. forced = " + forceSync + ", appVisible = " + isAppVisible + ", timeSinceLastSync = " + timeSinceLastSync + " ms");
|
||||
|
||||
if (!forceSync && !isAppVisible && timeSinceLastSync < FULL_SYNC_TIME) {
|
||||
Log.i(TAG, "App is backgrounded and the last contact sync was too soon (" + timeSinceLastSync + " ms ago). Marking that we need a sync. Skipping multi-device contact update...");
|
||||
TextSecurePreferences.setNeedsFullContactSync(context, true);
|
||||
SignalStore.misc().setNeedsFullContactSync(true);
|
||||
return;
|
||||
}
|
||||
|
||||
TextSecurePreferences.setLastFullContactSyncTime(context, System.currentTimeMillis());
|
||||
TextSecurePreferences.setNeedsFullContactSync(context, false);
|
||||
SignalStore.misc().setLastFullContactSyncTime(System.currentTimeMillis());
|
||||
SignalStore.misc().setNeedsFullContactSync(false);
|
||||
|
||||
WriteDetails writeDetails = createTempFile();
|
||||
|
||||
|
||||
-1
@@ -11,7 +11,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.SealedSenderConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.net.NotPushRegisteredException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.signal.network.exceptions.PushNetworkException;
|
||||
|
||||
-1
@@ -11,7 +11,6 @@ import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.SealedSenderConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
|
||||
|
||||
-1
@@ -11,7 +11,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.SealedSenderConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.net.NotPushRegisteredException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.signal.network.exceptions.PushNetworkException;
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.keyvalue.SvrValues;
|
||||
import org.thoughtcrime.securesms.net.SignalNetwork;
|
||||
import org.thoughtcrime.securesms.registration.data.RegistrationRepository;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.NetworkResultUtil;
|
||||
import org.whispersystems.signalservice.api.RequestResultUtil;
|
||||
import org.whispersystems.signalservice.api.account.AccountAttributes;
|
||||
@@ -109,7 +108,7 @@ public class RefreshAttributesJob extends BaseJob {
|
||||
return;
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||
if (SignalStore.account().isUnauthorizedReceived()) {
|
||||
Log.i(TAG, "No longer authorized. Ignoring.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.pin.SvrRepository
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import java.io.IOException
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.days
|
||||
@@ -25,7 +24,7 @@ class RefreshSvrCredentialsJob private constructor(parameters: Parameters) : Bas
|
||||
|
||||
@JvmStatic
|
||||
fun enqueueIfNecessary() {
|
||||
if (SignalStore.svr.hasPin() && SignalStore.account.isRegistered && !TextSecurePreferences.isUnauthorizedReceived(AppDependencies.application)) {
|
||||
if (SignalStore.svr.hasPin() && SignalStore.account.isRegistered && !SignalStore.account.isUnauthorizedReceived) {
|
||||
val lastTimestamp = SignalStore.svr.lastRefreshAuthTimestamp
|
||||
if (lastTimestamp + FREQUENCY.inWholeMilliseconds < System.currentTimeMillis() || lastTimestamp > System.currentTimeMillis()) {
|
||||
AppDependencies.jobManager.add(RefreshSvrCredentialsJob())
|
||||
@@ -56,7 +55,7 @@ class RefreshSvrCredentialsJob private constructor(parameters: Parameters) : Bas
|
||||
return
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||
if (SignalStore.account.isUnauthorizedReceived) {
|
||||
Log.i(TAG, "No longer authorized. Ignoring.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.net.SignalNetwork
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
import kotlin.time.Duration.Companion.days
|
||||
|
||||
@@ -45,7 +44,7 @@ class RemoteConfigRefreshJob private constructor(parameters: Parameters) : Job(p
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||
if (SignalStore.account.isUnauthorizedReceived) {
|
||||
Log.i(TAG, "No longer authorized. Ignoring.")
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ class RetrieveProfileJob private constructor(parameters: Parameters, private val
|
||||
val recipientsToFetch = SignalDatabase
|
||||
.recipients
|
||||
.getRecordsForProfileFetch(recipientIds, debounceThreshold)
|
||||
.map { RecipientCreator.forRecord(context, it) }
|
||||
.map { RecipientCreator.forRecord(it) }
|
||||
|
||||
stopwatch.split("resolve")
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.keyvalue.CertificateType;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.net.SignalNetwork;
|
||||
import org.thoughtcrime.securesms.util.ExceptionHelper;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.NetworkResultUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -60,7 +59,7 @@ public final class RotateCertificateJob extends BaseJob {
|
||||
return;
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||
if (SignalStore.account().isUnauthorizedReceived()) {
|
||||
Log.i(TAG, "No longer authorized. Ignoring.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
@@ -50,7 +50,7 @@ public class ServiceOutageDetectionJob extends BaseJob {
|
||||
public void onRun() throws RetryLaterException {
|
||||
Log.i(TAG, "onRun()");
|
||||
|
||||
long timeSinceLastCheck = System.currentTimeMillis() - TextSecurePreferences.getLastOutageCheckTime(context);
|
||||
long timeSinceLastCheck = System.currentTimeMillis() - SignalStore.misc().getLastOutageCheckTime();
|
||||
if (timeSinceLastCheck < CHECK_TIME) {
|
||||
Log.w(TAG, "Skipping service outage check. Too soon.");
|
||||
return;
|
||||
@@ -62,16 +62,16 @@ public class ServiceOutageDetectionJob extends BaseJob {
|
||||
|
||||
if (IP_SUCCESS.equals(address.getHostAddress())) {
|
||||
Log.i(TAG, "Service is available.");
|
||||
TextSecurePreferences.setServiceOutage(context, false);
|
||||
SignalStore.misc().setServiceOutage(false);
|
||||
} else if (IP_FAILURE.equals(address.getHostAddress())) {
|
||||
Log.w(TAG, "Service is down.");
|
||||
TextSecurePreferences.setServiceOutage(context, true);
|
||||
SignalStore.misc().setServiceOutage(true);
|
||||
} else {
|
||||
Log.w(TAG, "Service status check returned an unrecognized IP address. Could be a weird network state. Prompting retry.");
|
||||
throw new RetryLaterException(new Exception("Unrecognized service outage IP address."));
|
||||
}
|
||||
|
||||
TextSecurePreferences.setLastOutageCheckTime(context, System.currentTimeMillis());
|
||||
SignalStore.misc().setLastOutageCheckTime(System.currentTimeMillis());
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RetryLaterException(e);
|
||||
}
|
||||
@@ -85,8 +85,8 @@ public class ServiceOutageDetectionJob extends BaseJob {
|
||||
@Override
|
||||
public void onFailure() {
|
||||
Log.i(TAG, "Service status check could not complete. Assuming success to avoid false positives due to bad network.");
|
||||
TextSecurePreferences.setServiceOutage(context, false);
|
||||
TextSecurePreferences.setLastOutageCheckTime(context, System.currentTimeMillis());
|
||||
SignalStore.misc().setServiceOutage(false);
|
||||
SignalStore.misc().setLastOutageCheckTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public static final class Factory implements Job.Factory<ServiceOutageDetectionJob> {
|
||||
|
||||
@@ -112,7 +112,7 @@ class StorageAccountRestoreJob private constructor(parameters: Parameters) : Bas
|
||||
Log.i(TAG, "Applying changes locally...")
|
||||
SignalDatabase.writableDatabase.beginTransaction()
|
||||
try {
|
||||
StorageSyncHelper.applyAccountStorageSyncUpdates(context, self().fresh(), accountRecord, false)
|
||||
StorageSyncHelper.applyAccountStorageSyncUpdates(self().fresh(), accountRecord, false)
|
||||
SignalDatabase.writableDatabase.setTransactionSuccessful()
|
||||
} finally {
|
||||
SignalDatabase.writableDatabase.endTransaction()
|
||||
|
||||
@@ -95,7 +95,7 @@ class StorageForcePushJob private constructor(parameters: Parameters) : BaseJob(
|
||||
.map { record -> StorageSyncModels.localToRemoteRecord(record, newContactStorageIds[record.id]!!.raw) }
|
||||
.toMutableList()
|
||||
|
||||
val accountRecord = StorageSyncHelper.buildAccountRecord(context, Recipient.self().fresh())
|
||||
val accountRecord = StorageSyncHelper.buildAccountRecord(Recipient.self().fresh())
|
||||
val allNewStorageIds: MutableList<StorageId> = ArrayList(newContactStorageIds.values)
|
||||
|
||||
inserts.add(accountRecord)
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.thoughtcrime.securesms.storage.StorageSyncValidations
|
||||
import org.thoughtcrime.securesms.storage.StoryDistributionListRecordProcessor
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage
|
||||
@@ -191,7 +190,7 @@ class StorageSyncJob private constructor(parameters: Parameters, private var loc
|
||||
return
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||
if (SignalStore.account.isUnauthorizedReceived) {
|
||||
Log.i(TAG, "No longer authorized. Ignoring.")
|
||||
return
|
||||
}
|
||||
@@ -528,7 +527,7 @@ class StorageSyncJob private constructor(parameters: Parameters, private var loc
|
||||
ContactRecordProcessor(identityConflictsPendingRepair).process(records.contacts, StorageSyncHelper.KEY_GENERATOR)
|
||||
GroupV2RecordProcessor().process(records.gv2, StorageSyncHelper.KEY_GENERATOR)
|
||||
NotificationProfileRecordProcessor().process(records.notificationProfileRecords, StorageSyncHelper.KEY_GENERATOR)
|
||||
AccountRecordProcessor(context, freshSelf()).process(records.account, StorageSyncHelper.KEY_GENERATOR)
|
||||
AccountRecordProcessor(freshSelf()).process(records.account, StorageSyncHelper.KEY_GENERATOR)
|
||||
StoryDistributionListRecordProcessor().process(records.storyDistributionLists, StorageSyncHelper.KEY_GENERATOR)
|
||||
CallLinkRecordProcessor().process(records.callLinkRecords, StorageSyncHelper.KEY_GENERATOR)
|
||||
ChatFolderRecordProcessor().process(records.chatFolderRecords, StorageSyncHelper.KEY_GENERATOR)
|
||||
@@ -575,7 +574,7 @@ class StorageSyncJob private constructor(parameters: Parameters, private var loc
|
||||
if (!self.storageId.contentEquals(id.raw)) {
|
||||
throw AssertionError("Local storage ID doesn't match self!")
|
||||
}
|
||||
records.add(StorageSyncHelper.buildAccountRecord(context, self))
|
||||
records.add(StorageSyncHelper.buildAccountRecord(self))
|
||||
}
|
||||
|
||||
ManifestRecord.Identifier.Type.STORY_DISTRIBUTION_LIST -> {
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.pin.Svr3Migration
|
||||
import org.thoughtcrime.securesms.pin.SvrRepository
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.BackupResponse
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSession
|
||||
import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV2
|
||||
@@ -61,7 +60,7 @@ class Svr2MirrorJob private constructor(parameters: Parameters, private var seri
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.isUnauthorizedReceived(context)) {
|
||||
if (SignalStore.account.isUnauthorizedReceived) {
|
||||
Log.w(TAG, "Not authorized. Skipping.")
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
+1
-2
@@ -5,14 +5,13 @@ import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.signal.emoji.EmojiPageModel
|
||||
import org.signal.emoji.EmojiSource.Companion.latest
|
||||
import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import java.util.function.Consumer
|
||||
|
||||
class EmojiKeyboardPageRepository(private val context: Context) {
|
||||
fun getEmoji(consumer: Consumer<List<EmojiPageModel>>) {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
val list = mutableListOf<EmojiPageModel>()
|
||||
list += RecentEmojiPageModel(context, TextSecurePreferences.RECENT_STORAGE_KEY)
|
||||
list += RecentEmojiPageModel(context, RecentEmojiPageModel.RECENT_STORAGE_KEY)
|
||||
list += latest.displayPages
|
||||
consumer.accept(list)
|
||||
}
|
||||
|
||||
+1
-2
@@ -12,7 +12,6 @@ import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.Emoj
|
||||
import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.util.DefaultValueLiveData
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModelList
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
|
||||
|
||||
@@ -68,7 +67,7 @@ class EmojiKeyboardPageViewModel(private val repository: EmojiKeyboardPageReposi
|
||||
|
||||
companion object {
|
||||
fun getStartingTab(): String {
|
||||
return if (RecentEmojiPageModel.hasRecents(AppDependencies.application, TextSecurePreferences.RECENT_STORAGE_KEY)) {
|
||||
return if (RecentEmojiPageModel.hasRecents(AppDependencies.application, RecentEmojiPageModel.RECENT_STORAGE_KEY)) {
|
||||
RecentEmojiPageModel.KEY
|
||||
} else {
|
||||
EmojiCategory.PEOPLE.key
|
||||
|
||||
+1
-2
@@ -11,7 +11,6 @@ import org.signal.emoji.EmojiSource
|
||||
import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel
|
||||
import org.thoughtcrime.securesms.database.EmojiSearchTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import java.util.function.Consumer
|
||||
|
||||
private const val MINIMUM_QUERY_THRESHOLD = 1
|
||||
@@ -36,7 +35,7 @@ class EmojiSearchRepository(private val context: Context) {
|
||||
|
||||
fun submitQuery(query: String, includeRecents: Boolean, limit: Int = EMOJI_SEARCH_LIMIT, consumer: Consumer<EmojiPageModel>) {
|
||||
if (query.length < MINIMUM_QUERY_THRESHOLD && includeRecents) {
|
||||
consumer.accept(RecentEmojiPageModel(context, TextSecurePreferences.RECENT_STORAGE_KEY))
|
||||
consumer.accept(RecentEmojiPageModel(context, RecentEmojiPageModel.RECENT_STORAGE_KEY))
|
||||
} else {
|
||||
SignalExecutors.SERIAL.execute {
|
||||
val emoji: List<String> = emojiSearchTable.query(query, limit)
|
||||
|
||||
@@ -26,9 +26,9 @@ import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.RegisteredConstraint
|
||||
import org.thoughtcrime.securesms.jobs.PreKeysSyncJob
|
||||
import org.thoughtcrime.securesms.notifications.UnregisteredNotifier
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.push.ServiceIds
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.api.push.UsernameLinkComponents
|
||||
@@ -84,6 +84,7 @@ class AccountValues internal constructor(store: KeyValueStore, context: Context)
|
||||
private const val KEY_ACI = "account.aci"
|
||||
private const val KEY_PNI = "account.pni"
|
||||
private const val KEY_IS_REGISTERED = "account.is_registered"
|
||||
private const val KEY_IS_UNAUTHORIZED_RECEIVED = "account.is_unauthorized_received"
|
||||
private const val KEY_ACCOUNT_REGISTERED_AT = "account.registered_at"
|
||||
|
||||
private const val KEY_HAS_LINKED_DEVICES = "account.has_linked_devices"
|
||||
@@ -113,6 +114,10 @@ class AccountValues internal constructor(store: KeyValueStore, context: Context)
|
||||
migrateFromSharedPrefsV3(context)
|
||||
}
|
||||
|
||||
if (!store.containsKey(KEY_IS_UNAUTHORIZED_RECEIVED)) {
|
||||
migrateFromSharedPrefsV4(context)
|
||||
}
|
||||
|
||||
store.getString(KEY_PNI, null)?.let { pni ->
|
||||
if (!pni.startsWith("PNI:")) {
|
||||
store.beginWrite().putString(KEY_PNI, "PNI:$pni").commit()
|
||||
@@ -516,6 +521,32 @@ class AccountValues internal constructor(store: KeyValueStore, context: Context)
|
||||
RegisteredConstraint.Observer.notifyListeners()
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the service has rejected our credentials on the authenticated websocket, i.e. we've been deregistered or unlinked remotely.
|
||||
*
|
||||
* This is distinct from [isRegistered], which tracks whether *we* believe this install completed registration. This flag is the service's verdict, and
|
||||
* it is cleared automatically the next time we successfully authenticate. Note that setting it rotates the profile key, so it is not a free toggle.
|
||||
*/
|
||||
var isUnauthorizedReceived: Boolean
|
||||
get() = getBoolean(KEY_IS_UNAUTHORIZED_RECEIVED, false)
|
||||
set(value) {
|
||||
val previous = isUnauthorizedReceived
|
||||
|
||||
putBoolean(KEY_IS_UNAUTHORIZED_RECEIVED, value)
|
||||
|
||||
if (previous != value) {
|
||||
Recipient.self().live().refresh()
|
||||
|
||||
if (value) {
|
||||
UnregisteredNotifier.notify(AppDependencies.application)
|
||||
rotateProfileKey()
|
||||
BackupRepository.haltBackupWritesForDeregistration()
|
||||
} else {
|
||||
UnregisteredNotifier.cancel(AppDependencies.application)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Milliseconds since epoch when account was registered or a negative value if not known.
|
||||
*/
|
||||
@@ -604,7 +635,14 @@ class AccountValues internal constructor(store: KeyValueStore, context: Context)
|
||||
|
||||
private fun clearLocalCredentials() {
|
||||
putString(KEY_SERVICE_PASSWORD, Util.getSecret(18))
|
||||
rotateProfileKey()
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that unlike [clearLocalCredentials] this leaves the service password alone, so we can still attempt to authenticate. Important for the
|
||||
* [isUnauthorizedReceived] path, which needs to be able to recover on its own.
|
||||
*/
|
||||
private fun rotateProfileKey() {
|
||||
val newProfileKey = ProfileKeyUtil.createNew()
|
||||
val self = Recipient.self()
|
||||
|
||||
@@ -630,15 +668,15 @@ class AccountValues internal constructor(store: KeyValueStore, context: Context)
|
||||
private fun migrateFromSharedPrefsV1(context: Context) {
|
||||
Log.i(TAG, "[V1] Migrating account values from shared prefs.")
|
||||
|
||||
putString(KEY_ACI, TextSecurePreferences.getStringPreference(context, "pref_local_uuid", null))
|
||||
putString(KEY_E164, TextSecurePreferences.getStringPreference(context, "pref_local_number", null))
|
||||
putString(KEY_SERVICE_PASSWORD, TextSecurePreferences.getStringPreference(context, "pref_gcm_password", null))
|
||||
putBoolean(KEY_IS_REGISTERED, TextSecurePreferences.getBooleanPreference(context, "pref_gcm_registered", false))
|
||||
putInteger(KEY_REGISTRATION_ID, TextSecurePreferences.getIntegerPreference(context, "pref_local_registration_id", 0))
|
||||
putBoolean(KEY_FCM_ENABLED, !TextSecurePreferences.getBooleanPreference(context, "pref_gcm_disabled", false))
|
||||
putString(KEY_FCM_TOKEN, TextSecurePreferences.getStringPreference(context, "pref_gcm_registration_id", null))
|
||||
putInteger(KEY_FCM_TOKEN_VERSION, TextSecurePreferences.getIntegerPreference(context, "pref_gcm_registration_id_version", 0))
|
||||
putLong(KEY_FCM_TOKEN_LAST_SET_TIME, TextSecurePreferences.getLongPreference(context, "pref_gcm_registration_id_last_set_time", 0))
|
||||
putString(KEY_ACI, LegacySharedPrefs.getStringOrNull(context, "pref_local_uuid"))
|
||||
putString(KEY_E164, LegacySharedPrefs.getStringOrNull(context, "pref_local_number"))
|
||||
putString(KEY_SERVICE_PASSWORD, LegacySharedPrefs.getStringOrNull(context, "pref_gcm_password"))
|
||||
putBoolean(KEY_IS_REGISTERED, LegacySharedPrefs.getBoolean(context, "pref_gcm_registered", false))
|
||||
putInteger(KEY_REGISTRATION_ID, LegacySharedPrefs.getInteger(context, "pref_local_registration_id", 0))
|
||||
putBoolean(KEY_FCM_ENABLED, !LegacySharedPrefs.getBoolean(context, "pref_gcm_disabled", false))
|
||||
putString(KEY_FCM_TOKEN, LegacySharedPrefs.getStringOrNull(context, "pref_gcm_registration_id"))
|
||||
putInteger(KEY_FCM_TOKEN_VERSION, LegacySharedPrefs.getInteger(context, "pref_gcm_registration_id_version", 0))
|
||||
putLong(KEY_FCM_TOKEN_LAST_SET_TIME, LegacySharedPrefs.getLong(context, "pref_gcm_registration_id_last_set_time", 0))
|
||||
}
|
||||
|
||||
/** Do not alter. If you need to migrate more stuff, create a new method. */
|
||||
@@ -713,7 +751,14 @@ class AccountValues internal constructor(store: KeyValueStore, context: Context)
|
||||
private fun migrateFromSharedPrefsV3(context: Context) {
|
||||
Log.i(TAG, "[V3] Migrating account values from shared prefs.")
|
||||
|
||||
putBoolean(KEY_HAS_LINKED_DEVICES, TextSecurePreferences.getBooleanPreference(context, "pref_multi_device", false))
|
||||
putBoolean(KEY_HAS_LINKED_DEVICES, LegacySharedPrefs.getBoolean(context, "pref_multi_device", false))
|
||||
}
|
||||
|
||||
/** Do not alter. If you need to migrate more stuff, create a new method. */
|
||||
private fun migrateFromSharedPrefsV4(context: Context) {
|
||||
Log.i(TAG, "[V4] Migrating account values from shared prefs.")
|
||||
|
||||
putBoolean(KEY_IS_UNAUTHORIZED_RECEIVED, LegacySharedPrefs.getBoolean(context, "pref_unauthorized_received", false))
|
||||
}
|
||||
|
||||
private fun SharedPreferences.hasStringData(key: String): Boolean {
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import android.content.Context
|
||||
import org.signal.core.util.logging.Log
|
||||
|
||||
class ApkUpdateValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
class ApkUpdateValues(store: KeyValueStore, context: Context) : SignalStoreValues(store) {
|
||||
companion object {
|
||||
private val TAG = Log.tag(ApkUpdateValues::class.java)
|
||||
|
||||
@@ -17,8 +18,25 @@ class ApkUpdateValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
private const val LAST_SUCCESSFUL_CHECK = "apk_update.last_successful_check"
|
||||
private const val LAST_APK_UPLOAD_TIME = "apk_update.last_apk_upload_time"
|
||||
private const val PENDING_APK_UPLOAD_TIME = "apk_update.pending_apk_upload_time"
|
||||
private const val REFRESH_TIME = "apk_update.refresh_time"
|
||||
}
|
||||
|
||||
init {
|
||||
if (!store.containsKey(REFRESH_TIME)) {
|
||||
migrateFromSharedPrefsV1(context)
|
||||
}
|
||||
}
|
||||
|
||||
/** Do not alter. If you need to migrate more stuff, create a new method. */
|
||||
private fun migrateFromSharedPrefsV1(context: Context) {
|
||||
Log.i(TAG, "[V1] Migrating apk update values from shared prefs.")
|
||||
|
||||
putLong(REFRESH_TIME, LegacySharedPrefs.getLong(context, "pref_update_apk_refresh_time", 0))
|
||||
}
|
||||
|
||||
/** When the next APK update check is scheduled. See [lastSuccessfulCheck] for when one last succeeded. */
|
||||
var refreshTime: Long by longValue(REFRESH_TIME, 0)
|
||||
|
||||
public override fun onFirstEverAppLaunch() = Unit
|
||||
public override fun getKeysToIncludeInBackup(): List<String> = emptyList()
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import android.content.Context
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -7,6 +8,7 @@ import okio.withLock
|
||||
import org.signal.core.models.backup.MediaRootBackupKey
|
||||
import org.signal.core.models.backup.MessageBackupKey
|
||||
import org.signal.core.util.LongSerializer
|
||||
import org.signal.core.util.crypto.KeyStoreHelper
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.network.util.JsonUtil
|
||||
import org.thoughtcrime.securesms.backup.DeletionState
|
||||
@@ -29,7 +31,7 @@ import kotlin.time.Duration.Companion.days
|
||||
import kotlin.time.Duration.Companion.hours
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
class BackupValues(store: KeyValueStore, context: Context) : SignalStoreValues(store) {
|
||||
companion object {
|
||||
val TAG = Log.tag(BackupValues::class.java)
|
||||
private const val KEY_MESSAGE_CREDENTIALS = "backup.messageCredentials"
|
||||
@@ -68,6 +70,8 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
private const val KEY_MESSAGE_BACKUP_INITIALIZED = "backup.messageBackupInitialized"
|
||||
private const val KEY_MEDIA_BACKUP_INITIALIZED = "backup.mediaBackupInitialized"
|
||||
private const val KEY_IMPORTED_EMPTY_ANDROID_SETTINGS = "backup.importedEmptyAndroidSettings"
|
||||
private const val KEY_V1_BACKUP_PASSPHRASE = "backup.v1BackupPassphrase"
|
||||
private const val KEY_V1_BACKUP_PASSPHRASE_MIGRATED = "backup.v1BackupPassphraseMigrated"
|
||||
|
||||
const val KEY_ARCHIVE_UPLOAD_STATE = "backup.archiveUploadState"
|
||||
|
||||
@@ -124,11 +128,56 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
if (!store.containsKey(KEY_MESSAGE_BACKUP_INITIALIZED)) {
|
||||
migrateSplitBackupsInitialized()
|
||||
}
|
||||
|
||||
if (!store.getBoolean(KEY_V1_BACKUP_PASSPHRASE_MIGRATED, false)) {
|
||||
migrateV1BackupPassphrase(context)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onFirstEverAppLaunch() = Unit
|
||||
public override fun getKeysToIncludeInBackup(): List<String> = emptyList()
|
||||
|
||||
/**
|
||||
* The passphrase for legacy (v1) local backups. This store is already encrypted, so unlike the shared-prefs home it used to
|
||||
* have, there's no need to seal it with the keystore by hand.
|
||||
*/
|
||||
var v1BackupPassphrase: String?
|
||||
get() = getString(KEY_V1_BACKUP_PASSPHRASE, null)?.stripSpaces()
|
||||
set(value) {
|
||||
putString(KEY_V1_BACKUP_PASSPHRASE, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulls the v1 backup passphrase out of shared prefs, where it lived as a hand-sealed blob because it predates this store.
|
||||
*
|
||||
* Do not alter. If you need to migrate more stuff, create a new method.
|
||||
*/
|
||||
private fun migrateV1BackupPassphrase(context: Context) {
|
||||
Log.i(TAG, "[V1Passphrase] Migrating the legacy backup passphrase out of shared prefs.")
|
||||
|
||||
val sealed = LegacySharedPrefs.getStringOrNull(context, "pref_encrypted_backup_passphrase")
|
||||
|
||||
val passphrase = if (sealed != null) {
|
||||
try {
|
||||
String(KeyStoreHelper.unseal(KeyStoreHelper.SealedData.fromString(sealed)))
|
||||
} catch (e: Exception) {
|
||||
// Nothing we can do to recover it -- better to lose the passphrase than to fail to construct the store at all.
|
||||
Log.w(TAG, "[V1Passphrase] Failed to unseal the legacy passphrase! The user will have to re-enter it.", e)
|
||||
null
|
||||
}
|
||||
} else {
|
||||
LegacySharedPrefs.getStringOrNull(context, "pref_backup_passphrase")
|
||||
}
|
||||
|
||||
store
|
||||
.beginWrite()
|
||||
.putString(KEY_V1_BACKUP_PASSPHRASE, passphrase?.stripSpaces())
|
||||
.putBoolean(KEY_V1_BACKUP_PASSPHRASE_MIGRATED, true)
|
||||
.commit()
|
||||
}
|
||||
|
||||
private fun String.stripSpaces(): String = this.replace(" ", "")
|
||||
|
||||
var cachedMediaCdnPath: String? by stringValue(KEY_CDN_MEDIA_PATH, null)
|
||||
|
||||
var lastBackupProtoSize: Long by longValue(KEY_BACKUP_LAST_PROTO_SIZE, 0L)
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package org.thoughtcrime.securesms.keyvalue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
|
||||
@@ -81,14 +79,9 @@ public final class CertificateValues extends SignalStoreValues {
|
||||
private void migrateFromSharedPrefsV1(@NonNull Context context) {
|
||||
Log.i(TAG, "[V1] Migrating certificate values from shared prefs.");
|
||||
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
long legacyNextRotationTime = sharedPrefs.getLong("pref_unidentified_access_certificate_rotation_time", 0);
|
||||
long legacyNextRotationTime = LegacySharedPrefs.INSTANCE.getLong(context, "pref_unidentified_access_certificate_rotation_time", 0);
|
||||
|
||||
putLong(LAST_ROTATION_TIME, legacyNextRotationTime > 0 ? legacyNextRotationTime - LEGACY_ROTATION_INTERVAL : NEVER_ROTATED);
|
||||
|
||||
sharedPrefs.edit()
|
||||
.remove("pref_unidentified_access_certificate_rotation_time")
|
||||
.apply();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@ object LegacySharedPrefs {
|
||||
return prefs(context).getString(key, defaultValue) ?: defaultValue
|
||||
}
|
||||
|
||||
fun getStringOrNull(context: Context, key: String): String? {
|
||||
return prefs(context).getString(key, null)
|
||||
}
|
||||
|
||||
/** Some values were stored as strings, but some installs ended up with ints. */
|
||||
fun getIntegerFromString(context: Context, key: String, defaultValue: Int): Int {
|
||||
return try {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import android.content.Context
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.components.settings.app.usernamelinks.UsernameQrCodeColorScheme
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.PendingChangeNumberMetadata
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.ChangeNumberConstraintObserver
|
||||
@@ -7,8 +9,10 @@ import org.thoughtcrime.securesms.jobmanager.impl.SealedSenderConstraint
|
||||
import org.thoughtcrime.securesms.jobs.DeprecatedNotificationJob
|
||||
import org.thoughtcrime.securesms.keyvalue.protos.LeastActiveLinkedDevice
|
||||
|
||||
class MiscellaneousValues internal constructor(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
class MiscellaneousValues internal constructor(store: KeyValueStore, context: Context) : SignalStoreValues(store) {
|
||||
companion object {
|
||||
private val TAG = Log.tag(MiscellaneousValues::class)
|
||||
|
||||
private const val LAST_PREKEY_REFRESH_TIME = "last_prekey_refresh_time"
|
||||
private const val MESSAGE_REQUEST_ENABLE_TIME = "message_request_enable_time"
|
||||
private const val LAST_PROFILE_REFRESH_TIME = "misc.last_profile_refresh_time"
|
||||
@@ -58,8 +62,82 @@ class MiscellaneousValues internal constructor(store: KeyValueStore) : SignalSto
|
||||
private const val LAST_APPLIED_PNI_CHANGE_SERVER_TIMESTAMP = "misc.last_applied_pni_change_server_timestamp"
|
||||
private const val LAST_MISSING_PLAY_SERVICES_FCM_VERIFICATION_TIME = "misc.last_missing_play_services_fcm_verification_time"
|
||||
private const val LAST_PROCESSED_SHARE_DATA_TIMESTAMP = "misc.last_processed_share_data_timestamp"
|
||||
private const val DIRECTORY_REFRESH_TIME = "misc.directory_refresh_time"
|
||||
private const val HAS_SUCCESSFULLY_RETRIEVED_DIRECTORY = "misc.has_successfully_retrieved_directory"
|
||||
private const val LAST_FULL_CONTACT_SYNC_TIME = "misc.last_full_contact_sync_time"
|
||||
private const val NEEDS_FULL_CONTACT_SYNC = "misc.needs_full_contact_sync"
|
||||
private const val SERVICE_OUTAGE = "misc.service_outage"
|
||||
private const val LAST_OUTAGE_CHECK_TIME = "misc.last_outage_check_time"
|
||||
private const val SIGNED_PREKEY_ROTATION_TIME = "misc.signed_prekey_rotation_time"
|
||||
private const val JOB_MANAGER_VERSION = "misc.job_manager_version"
|
||||
private const val FIRST_INSTALL_VERSION = "misc.first_install_version"
|
||||
private const val NOTIFICATION_CHANNEL_VERSION = "misc.notification_channel_version"
|
||||
private const val NOTIFICATION_MESSAGES_CHANNEL_VERSION = "misc.notification_messages_channel_version"
|
||||
private const val RATING_ENABLED = "misc.rating_enabled"
|
||||
private const val RATING_LATER_TIMESTAMP = "misc.rating_later_timestamp"
|
||||
}
|
||||
|
||||
init {
|
||||
if (!store.containsKey(FIRST_INSTALL_VERSION)) {
|
||||
migrateFromSharedPrefsV1(context)
|
||||
}
|
||||
}
|
||||
|
||||
/** Do not alter. If you need to migrate more stuff, create a new method. */
|
||||
private fun migrateFromSharedPrefsV1(context: Context) {
|
||||
Log.i(TAG, "[V1] Migrating misc values from shared prefs.")
|
||||
|
||||
store.beginWrite()
|
||||
.putLong(DIRECTORY_REFRESH_TIME, LegacySharedPrefs.getLong(context, "pref_directory_refresh_time", 0))
|
||||
.putBoolean(HAS_SUCCESSFULLY_RETRIEVED_DIRECTORY, LegacySharedPrefs.getBoolean(context, "pref_successful_directory", false))
|
||||
.putLong(LAST_FULL_CONTACT_SYNC_TIME, LegacySharedPrefs.getLong(context, "pref_last_full_contact_sync_time", 0))
|
||||
.putBoolean(NEEDS_FULL_CONTACT_SYNC, LegacySharedPrefs.getBoolean(context, "pref_needs_full_contact_sync", false))
|
||||
.putBoolean(SERVICE_OUTAGE, LegacySharedPrefs.getBoolean(context, "pref_service_outage", false))
|
||||
.putLong(LAST_OUTAGE_CHECK_TIME, LegacySharedPrefs.getLong(context, "pref_last_outage_check_time", 0))
|
||||
.putLong(SIGNED_PREKEY_ROTATION_TIME, LegacySharedPrefs.getLong(context, "pref_signed_pre_key_rotation_time", 0))
|
||||
.putInteger(JOB_MANAGER_VERSION, LegacySharedPrefs.getInteger(context, "pref_job_manager_version", 1))
|
||||
.putInteger(NOTIFICATION_CHANNEL_VERSION, LegacySharedPrefs.getInteger(context, "pref_notification_channel_version", 1))
|
||||
.putInteger(NOTIFICATION_MESSAGES_CHANNEL_VERSION, LegacySharedPrefs.getInteger(context, "pref_notification_messages_channel_version", 1))
|
||||
.putBoolean(RATING_ENABLED, LegacySharedPrefs.getBoolean(context, "pref_rating_enabled", true))
|
||||
.putLong(RATING_LATER_TIMESTAMP, LegacySharedPrefs.getLong(context, "pref_rating_later", -1))
|
||||
// Written last so that it acts as the marker for this migration having run.
|
||||
.putInteger(FIRST_INSTALL_VERSION, LegacySharedPrefs.getInteger(context, "pref_first_install_version", -1))
|
||||
.commit()
|
||||
}
|
||||
|
||||
/** When the next contact directory refresh is scheduled. */
|
||||
var directoryRefreshTime: Long by longValue(DIRECTORY_REFRESH_TIME, 0)
|
||||
|
||||
/** Whether we've ever managed to pull down the contact directory. */
|
||||
var hasSuccessfullyRetrievedDirectory: Boolean by booleanValue(HAS_SUCCESSFULLY_RETRIEVED_DIRECTORY, false)
|
||||
|
||||
var lastFullContactSyncTime: Long by longValue(LAST_FULL_CONTACT_SYNC_TIME, 0)
|
||||
|
||||
var needsFullContactSync: Boolean by booleanValue(NEEDS_FULL_CONTACT_SYNC, false)
|
||||
|
||||
/** Whether the service is currently reporting an outage. */
|
||||
var serviceOutage: Boolean by booleanValue(SERVICE_OUTAGE, false)
|
||||
|
||||
var lastOutageCheckTime: Long by longValue(LAST_OUTAGE_CHECK_TIME, 0)
|
||||
|
||||
var signedPreKeyRotationTime: Long by longValue(SIGNED_PREKEY_ROTATION_TIME, 0)
|
||||
|
||||
/** The [org.thoughtcrime.securesms.jobmanager.JobManager] version the job database was last migrated to. */
|
||||
var jobManagerVersion: Int by integerValue(JOB_MANAGER_VERSION, 1)
|
||||
|
||||
/** The canonical version code the app was first installed at, or -1 if we don't know. */
|
||||
var firstInstallVersion: Int by integerValue(FIRST_INSTALL_VERSION, -1)
|
||||
|
||||
var notificationChannelVersion: Int by integerValue(NOTIFICATION_CHANNEL_VERSION, 1)
|
||||
|
||||
var notificationMessagesChannelVersion: Int by integerValue(NOTIFICATION_MESSAGES_CHANNEL_VERSION, 1)
|
||||
|
||||
/** Whether we're still allowed to ask the user to rate the app. */
|
||||
var ratingEnabled: Boolean by booleanValue(RATING_ENABLED, true)
|
||||
|
||||
/** The earliest time we're allowed to ask the user to rate the app again. */
|
||||
var ratingLaterTimestamp: Long by longValue(RATING_LATER_TIMESTAMP, -1)
|
||||
|
||||
public override fun onFirstEverAppLaunch() {
|
||||
putLong(MESSAGE_REQUEST_ENABLE_TIME, 0)
|
||||
putBoolean(NEEDS_USERNAME_RESTORE, true)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package org.thoughtcrime.securesms.keyvalue;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||
import org.thoughtcrime.securesms.lock.RegistrationLockReminders;
|
||||
import org.thoughtcrime.securesms.lock.SignalPinReminders;
|
||||
import org.thoughtcrime.securesms.lock.v2.PinKeyboardType;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -22,10 +23,44 @@ public final class PinValues extends SignalStoreValues {
|
||||
private static final String LAST_REMINDER_TIME = "pin.last_reminder_time";
|
||||
private static final String NEXT_INTERVAL = "pin.interval_index";
|
||||
private static final String KEYBOARD_TYPE = "kbs.keyboard_type";
|
||||
private static final String MIGRATION_VERSION = "pin.migration_version";
|
||||
public static final String PIN_REMINDERS_ENABLED = "pin.pin_reminders_enabled";
|
||||
|
||||
PinValues(KeyValueStore store) {
|
||||
private static final int CURRENT_MIGRATION_VERSION = 1;
|
||||
|
||||
PinValues(KeyValueStore store, @NonNull Context context) {
|
||||
super(store);
|
||||
|
||||
if (getLong(MIGRATION_VERSION, 0) < CURRENT_MIGRATION_VERSION) {
|
||||
migrateFromSharedPrefsV1(context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlike the other stores, we can't use one of the migrated keys as the "has this run?" marker: both {@link #NEXT_INTERVAL} and
|
||||
* {@link #LAST_SUCCESSFUL_ENTRY} are keys released versions already write, so their presence says nothing about whether this
|
||||
* migration ran. Hence the explicit {@link #MIGRATION_VERSION}.
|
||||
*
|
||||
* These values used to be read straight out of shared prefs as the *default* for the keys above, so only migrate the ones this
|
||||
* store doesn't already have a value for.
|
||||
*
|
||||
* Do not alter. If you need to migrate more stuff, bump {@link #CURRENT_MIGRATION_VERSION} and add a new method.
|
||||
*/
|
||||
private void migrateFromSharedPrefsV1(@NonNull Context context) {
|
||||
Log.i(TAG, "[V1] Migrating pin values from shared prefs.");
|
||||
|
||||
KeyValueStore.Writer writer = getStore().beginWrite();
|
||||
|
||||
if (!getStore().containsKey(LAST_SUCCESSFUL_ENTRY)) {
|
||||
writer.putLong(LAST_SUCCESSFUL_ENTRY, LegacySharedPrefs.INSTANCE.getLong(context, "pref_registration_lock_last_reminder_time_post_kbs", 0));
|
||||
}
|
||||
|
||||
if (!getStore().containsKey(NEXT_INTERVAL)) {
|
||||
writer.putLong(NEXT_INTERVAL, LegacySharedPrefs.INSTANCE.getLong(context, "pref_registration_lock_next_reminder_interval", RegistrationLockReminders.INITIAL_INTERVAL));
|
||||
}
|
||||
|
||||
writer.putLong(MIGRATION_VERSION, CURRENT_MIGRATION_VERSION)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -38,7 +73,7 @@ public final class PinValues extends SignalStoreValues {
|
||||
}
|
||||
|
||||
public void onEntrySuccess(@NonNull String pin) {
|
||||
long nextInterval = SignalPinReminders.getNextInterval(getCurrentInterval());
|
||||
long nextInterval = SignalPinReminders.getNextInterval(getNextReminderInterval());
|
||||
Log.i(TAG, "onEntrySuccess() nextInterval: " + nextInterval);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
@@ -53,7 +88,7 @@ public final class PinValues extends SignalStoreValues {
|
||||
}
|
||||
|
||||
public void onEntrySuccessWithWrongGuess(@NonNull String pin) {
|
||||
long nextInterval = SignalPinReminders.getPreviousInterval(getCurrentInterval());
|
||||
long nextInterval = SignalPinReminders.getPreviousInterval(getNextReminderInterval());
|
||||
Log.i(TAG, "onEntrySuccessWithWrongGuess() nextInterval: " + nextInterval);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
@@ -75,9 +110,9 @@ public final class PinValues extends SignalStoreValues {
|
||||
long nextInterval;
|
||||
|
||||
if (includedFailure) {
|
||||
nextInterval = SignalPinReminders.getPreviousInterval(getCurrentInterval());
|
||||
nextInterval = SignalPinReminders.getPreviousInterval(getNextReminderInterval());
|
||||
} else {
|
||||
nextInterval = getCurrentInterval();
|
||||
nextInterval = getNextReminderInterval();
|
||||
}
|
||||
|
||||
Log.i(TAG, "onEntrySkip(includedFailure: " + includedFailure +") nextInterval: " + nextInterval);
|
||||
@@ -101,12 +136,20 @@ public final class PinValues extends SignalStoreValues {
|
||||
.apply();
|
||||
}
|
||||
|
||||
public long getCurrentInterval() {
|
||||
return getLong(NEXT_INTERVAL, TextSecurePreferences.getRegistrationLockNextReminderInterval(AppDependencies.getApplication()));
|
||||
public long getNextReminderInterval() {
|
||||
return getLong(NEXT_INTERVAL, RegistrationLockReminders.INITIAL_INTERVAL);
|
||||
}
|
||||
|
||||
public void setNextReminderInterval(long interval) {
|
||||
putLong(NEXT_INTERVAL, interval);
|
||||
}
|
||||
|
||||
public long getLastSuccessfulEntryTime() {
|
||||
return getLong(LAST_SUCCESSFUL_ENTRY, TextSecurePreferences.getRegistrationLockLastReminderTime(AppDependencies.getApplication()));
|
||||
return getLong(LAST_SUCCESSFUL_ENTRY, 0);
|
||||
}
|
||||
|
||||
public void setLastSuccessfulEntryTime(long time) {
|
||||
putLong(LAST_SUCCESSFUL_ENTRY, time);
|
||||
}
|
||||
|
||||
public long getLastReminderTime() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.thoughtcrime.securesms.keyvalue
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.CheckResult
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import org.signal.core.util.logging.Log
|
||||
@@ -7,7 +8,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.LocalRegistratio
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.RestoreDecisionState
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
|
||||
class RegistrationValues internal constructor(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
class RegistrationValues internal constructor(store: KeyValueStore, context: Context) : SignalStoreValues(store) {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(RegistrationValues::class)
|
||||
@@ -25,10 +26,28 @@ class RegistrationValues internal constructor(store: KeyValueStore) : SignalStor
|
||||
private const val RESTORING_ON_NEW_DEVICE = "registration.restoring_on_new_device"
|
||||
private const val IN_PROGRESS_DATA_BLOB_URI = "registration.in_progress_data_blob_uri"
|
||||
|
||||
private const val HAS_PROMPTED_PUSH_REGISTRATION = "registration.has_prompted_push_registration"
|
||||
|
||||
@VisibleForTesting
|
||||
const val RESTORE_DECISION_STATE = "registration.restore_decision_state.2"
|
||||
}
|
||||
|
||||
init {
|
||||
if (!store.containsKey(HAS_PROMPTED_PUSH_REGISTRATION)) {
|
||||
migrateFromSharedPrefsV1(context)
|
||||
}
|
||||
}
|
||||
|
||||
/** Do not alter. If you need to migrate more stuff, create a new method. */
|
||||
private fun migrateFromSharedPrefsV1(context: Context) {
|
||||
Log.i(TAG, "[V1] Migrating registration values from shared prefs.")
|
||||
|
||||
putBoolean(HAS_PROMPTED_PUSH_REGISTRATION, LegacySharedPrefs.getBoolean(context, "pref_prompted_push_registration", false))
|
||||
}
|
||||
|
||||
/** Whether we've already walked the user through push registration. */
|
||||
var hasPromptedPushRegistration: Boolean by booleanValue(HAS_PROMPTED_PUSH_REGISTRATION, false)
|
||||
|
||||
@Synchronized
|
||||
public override fun onFirstEverAppLaunch() {
|
||||
store
|
||||
|
||||
@@ -499,6 +499,39 @@ class SettingsValues internal constructor(store: KeyValueStore, private val cont
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* V1 backups made before these settings moved into this store carry them as shared prefs rather than key-values. The shared-prefs
|
||||
* migration has already run by the time a restore happens, so the restored prefs need to be re-read afterwards or the user silently
|
||||
* loses their privacy and security choices.
|
||||
*/
|
||||
fun restoreLegacySharedPrefsAfterBackupRestore() {
|
||||
Log.i(TAG, "Restoring legacy privacy settings from shared prefs.")
|
||||
|
||||
val writer = store.beginWrite()
|
||||
|
||||
val booleanKeys = mapOf(
|
||||
"pref_screen_security" to SCREEN_SECURITY_ENABLED,
|
||||
"pref_incognito_keyboard" to INCOGNITO_KEYBOARD_ENABLED,
|
||||
"pref_read_receipts" to READ_RECEIPTS_ENABLED,
|
||||
"pref_typing_indicators" to TYPING_INDICATORS_ENABLED,
|
||||
"pref_show_unidentifed_delivery_indicators" to SHOW_UNIDENTIFIED_DELIVERY_INDICATORS,
|
||||
"pref_universal_unidentified_access" to UNIVERSAL_UNIDENTIFIED_ACCESS,
|
||||
"pref_turn_only" to ALWAYS_RELAY_CALLS
|
||||
)
|
||||
|
||||
for ((legacyKey, key) in booleanKeys) {
|
||||
if (LegacySharedPrefs.contains(context, legacyKey)) {
|
||||
writer.putBoolean(key, LegacySharedPrefs.getBoolean(context, legacyKey, false))
|
||||
}
|
||||
}
|
||||
|
||||
if (LegacySharedPrefs.contains(context, "pref_notification_privacy")) {
|
||||
writer.putString(MESSAGE_NOTIFICATION_PRIVACY, LegacySharedPrefs.getString(context, "pref_notification_privacy", "all"))
|
||||
}
|
||||
|
||||
writer.commit()
|
||||
}
|
||||
|
||||
private fun migrateFromSharedPrefsV1(context: Context) {
|
||||
Log.i(TAG, "[V1] Migrating screen lock values from shared prefs.")
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@ class SignalStore(context: Application, private val store: KeyValueStore) {
|
||||
|
||||
val accountValues = AccountValues(store, context)
|
||||
val svrValues = SvrValues(store)
|
||||
val registrationValues = RegistrationValues(store)
|
||||
val pinValues = PinValues(store)
|
||||
val registrationValues = RegistrationValues(store, context)
|
||||
val pinValues = PinValues(store, context)
|
||||
val remoteConfigValues = RemoteConfigValues(store)
|
||||
val storageServiceValues = StorageServiceValues(store)
|
||||
val uiHintValues = UiHintValues(store)
|
||||
val tooltipValues = TooltipValues(store)
|
||||
val miscValues = MiscellaneousValues(store)
|
||||
val uiHintValues = UiHintValues(store, context)
|
||||
val tooltipValues = TooltipValues(store, context)
|
||||
val miscValues = MiscellaneousValues(store, context)
|
||||
val internalValues = InternalValues(store)
|
||||
val emojiValues = EmojiValues(store)
|
||||
val settingsValues = SettingsValues(store, context)
|
||||
@@ -35,8 +35,8 @@ class SignalStore(context: Application, private val store: KeyValueStore) {
|
||||
val notificationProfileValues = NotificationProfileValues(store)
|
||||
val releaseChannelValues = ReleaseChannelValues(store)
|
||||
val storyValues = StoryValues(store)
|
||||
val apkUpdateValues = ApkUpdateValues(store)
|
||||
val backupValues = BackupValues(store)
|
||||
val apkUpdateValues = ApkUpdateValues(store, context)
|
||||
val backupValues = BackupValues(store, context)
|
||||
val callQualityValues = CallQualityValues(store)
|
||||
val labsValues = LabsValues(store)
|
||||
|
||||
@@ -145,6 +145,7 @@ class SignalStore(context: Application, private val store: KeyValueStore) {
|
||||
@JvmStatic
|
||||
fun onPostBackupRestore() {
|
||||
instance!!.store.resetCache()
|
||||
instance!!.settingsValues.restoreLegacySharedPrefsAfterBackupRestore()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@@ -270,6 +271,8 @@ class SignalStore(context: Application, private val store: KeyValueStore) {
|
||||
val story: StoryValues
|
||||
get() = instance!!.storyValues
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("apkUpdate")
|
||||
val apkUpdate: ApkUpdateValues
|
||||
get() = instance!!.apkUpdateValues
|
||||
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package org.thoughtcrime.securesms.keyvalue;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TooltipValues extends SignalStoreValues {
|
||||
|
||||
private static final String TAG = Log.tag(TooltipValues.class);
|
||||
|
||||
private static final int GROUP_CALLING_MAX_TOOLTIP_DISPLAY_COUNT = 3;
|
||||
|
||||
private static final String BLUR_HUD_ICON = "tooltip.blur_hud_icon";
|
||||
@@ -16,9 +22,41 @@ public class TooltipValues extends SignalStoreValues {
|
||||
private static final String BUBBLE_OPT_OUT = "tooltip.bubble.opt.out";
|
||||
private static final String PROFILE_SETTINGS_QR_CODE = "tooltip.profile_settings_qr_code";
|
||||
private static final String CALLING_SWITCH_CAMERA = "tooltip.calling.switch_camera";
|
||||
private static final String STICKER_INTRO = "tooltip.sticker_intro";
|
||||
private static final String SWIPE_TO_REPLY = "tooltip.swipe_to_reply";
|
||||
|
||||
TooltipValues(@NonNull KeyValueStore store) {
|
||||
TooltipValues(@NonNull KeyValueStore store, @NonNull Context context) {
|
||||
super(store);
|
||||
|
||||
if (!store.containsKey(STICKER_INTRO)) {
|
||||
migrateFromSharedPrefsV1(context);
|
||||
}
|
||||
}
|
||||
|
||||
/** Do not alter. If you need to migrate more stuff, create a new method. */
|
||||
private void migrateFromSharedPrefsV1(@NonNull Context context) {
|
||||
Log.i(TAG, "[V1] Migrating tooltip values from shared prefs.");
|
||||
|
||||
getStore().beginWrite()
|
||||
.putBoolean(SWIPE_TO_REPLY, LegacySharedPrefs.INSTANCE.getBoolean(context, "pref_has_seen_swipe_to_reply", false))
|
||||
.putBoolean(STICKER_INTRO, LegacySharedPrefs.INSTANCE.getBoolean(context, "pref_seen_sticker_intro_tooltip", false))
|
||||
.commit();
|
||||
}
|
||||
|
||||
public boolean hasSeenStickerIntroTooltip() {
|
||||
return getBoolean(STICKER_INTRO, false);
|
||||
}
|
||||
|
||||
public void markStickerIntroTooltipSeen() {
|
||||
putBoolean(STICKER_INTRO, true);
|
||||
}
|
||||
|
||||
public boolean hasSeenSwipeToReplyTooltip() {
|
||||
return getBoolean(SWIPE_TO_REPLY, false);
|
||||
}
|
||||
|
||||
public void markSwipeToReplyTooltipSeen() {
|
||||
putBoolean(SWIPE_TO_REPLY, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package org.thoughtcrime.securesms.keyvalue;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class UiHintValues extends SignalStoreValues {
|
||||
|
||||
private static final String TAG = Log.tag(UiHintValues.class);
|
||||
|
||||
private static final int NEVER_DISPLAY_PULL_TO_FILTER_TIP_THRESHOLD = 3;
|
||||
private static final int HAS_SEEN_PINNED_MESSAGE_SHEET_THRESHOLD = 3;
|
||||
|
||||
@@ -34,9 +40,29 @@ public class UiHintValues extends SignalStoreValues {
|
||||
private static final String HAS_DISMISSED_MEMBER_LABEL_ABOUT_OVERRIDE_WARNING = "uihints.has_dismissed_member_label_about_override_warning";
|
||||
private static final String HAS_SEEN_ADMIN_DELETE_EDUCATION_DIALOG = "uihints.has_seen_admin_delete_education_dialog";
|
||||
private static final String DISMISSED_SET_UP_USERNAME_BANNER = "uihints.dismissed_set_up_username_banner";
|
||||
private static final String HAS_PROMPTED_OPTIMIZE_DOZE = "uihints.has_prompted_optimize_doze";
|
||||
|
||||
UiHintValues(@NonNull KeyValueStore store) {
|
||||
UiHintValues(@NonNull KeyValueStore store, @NonNull Context context) {
|
||||
super(store);
|
||||
|
||||
if (!store.containsKey(HAS_PROMPTED_OPTIMIZE_DOZE)) {
|
||||
migrateFromSharedPrefsV1(context);
|
||||
}
|
||||
}
|
||||
|
||||
/** Do not alter. If you need to migrate more stuff, create a new method. */
|
||||
private void migrateFromSharedPrefsV1(@NonNull Context context) {
|
||||
Log.i(TAG, "[V1] Migrating ui hint values from shared prefs.");
|
||||
|
||||
putBoolean(HAS_PROMPTED_OPTIMIZE_DOZE, LegacySharedPrefs.INSTANCE.getBoolean(context, "pref_prompted_optimize_doze", false));
|
||||
}
|
||||
|
||||
public boolean hasPromptedOptimizeDoze() {
|
||||
return getBoolean(HAS_PROMPTED_OPTIMIZE_DOZE, false);
|
||||
}
|
||||
|
||||
public void setHasPromptedOptimizeDoze(boolean value) {
|
||||
putBoolean(HAS_PROMPTED_OPTIMIZE_DOZE, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
|
||||
import java.util.NavigableSet;
|
||||
import java.util.TreeSet;
|
||||
@@ -24,26 +24,26 @@ public class RegistrationLockReminders {
|
||||
public static final long INITIAL_INTERVAL = INTERVALS.first();
|
||||
|
||||
public static boolean needsReminder(@NonNull Context context) {
|
||||
long lastReminderTime = TextSecurePreferences.getRegistrationLockLastReminderTime(context);
|
||||
long nextIntervalTime = TextSecurePreferences.getRegistrationLockNextReminderInterval(context);
|
||||
long lastReminderTime = SignalStore.pin().getLastSuccessfulEntryTime();
|
||||
long nextIntervalTime = SignalStore.pin().getNextReminderInterval();
|
||||
|
||||
return System.currentTimeMillis() > lastReminderTime + nextIntervalTime;
|
||||
}
|
||||
|
||||
public static void scheduleReminder(@NonNull Context context, boolean success) {
|
||||
if (success) {
|
||||
long timeSinceLastReminder = System.currentTimeMillis() - TextSecurePreferences.getRegistrationLockLastReminderTime(context);
|
||||
long timeSinceLastReminder = System.currentTimeMillis() - SignalStore.pin().getLastSuccessfulEntryTime();
|
||||
Long nextReminderInterval = INTERVALS.higher(timeSinceLastReminder);
|
||||
|
||||
if (nextReminderInterval == null) {
|
||||
nextReminderInterval = INTERVALS.last();
|
||||
}
|
||||
|
||||
TextSecurePreferences.setRegistrationLockLastReminderTime(context, System.currentTimeMillis());
|
||||
TextSecurePreferences.setRegistrationLockNextReminderInterval(context, nextReminderInterval);
|
||||
SignalStore.pin().setLastSuccessfulEntryTime(System.currentTimeMillis());
|
||||
SignalStore.pin().setNextReminderInterval(nextReminderInterval);
|
||||
} else {
|
||||
long timeSinceLastReminder = TextSecurePreferences.getRegistrationLockLastReminderTime(context) + TimeUnit.MINUTES.toMillis(5);
|
||||
TextSecurePreferences.setRegistrationLockLastReminderTime(context, timeSinceLastReminder);
|
||||
long timeSinceLastReminder = SignalStore.pin().getLastSuccessfulEntryTime() + TimeUnit.MINUTES.toMillis(5);
|
||||
SignalStore.pin().setLastSuccessfulEntryTime(timeSinceLastReminder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -7,7 +7,6 @@ import androidx.annotation.NonNull;
|
||||
import org.thoughtcrime.securesms.keyvalue.KeepMessagesDuration;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.signal.core.util.Util;
|
||||
|
||||
final class LogSectionKeyPreferences implements LogSection {
|
||||
@@ -27,7 +26,7 @@ final class LogSectionKeyPreferences implements LogSection {
|
||||
.append("Media Quality : ").append(SignalStore.settings().getSentMediaQuality()).append("\n")
|
||||
.append("Client Deprecated : ").append(SignalStore.misc().isClientDeprecated()).append("\n")
|
||||
.append("Push Registered : ").append(SignalStore.account().isRegistered()).append("\n")
|
||||
.append("Unauthorized Received : ").append(TextSecurePreferences.isUnauthorizedReceived(context)).append("\n")
|
||||
.append("Unauthorized Received : ").append(SignalStore.account().isUnauthorizedReceived()).append("\n")
|
||||
.append("self.isRegistered() : ").append(SignalStore.account().getAci() == null ? "false" : Recipient.self().isRegistered()).append("\n")
|
||||
.append("Thread Trimming : ").append(getThreadTrimmingString()).append("\n")
|
||||
.append("Censorship Setting : ").append(SignalStore.settings().getCensorshipCircumventionEnabled()).append("\n")
|
||||
|
||||
@@ -17,7 +17,7 @@ public class LogSectionPin implements LogSection {
|
||||
public @NonNull CharSequence getContent(@NonNull Context context) {
|
||||
return new StringBuilder().append("Last Successful Reminder Entry: ").append(SignalStore.pin().getLastSuccessfulEntryTime()).append("\n")
|
||||
.append("Last Reminder Time: ").append(SignalStore.pin().getLastReminderTime()).append("\n")
|
||||
.append("Next Reminder Interval: ").append(SignalStore.pin().getCurrentInterval()).append("\n")
|
||||
.append("Next Reminder Interval: ").append(SignalStore.pin().getNextReminderInterval()).append("\n")
|
||||
.append("Reglock: ").append(SignalStore.svr().isRegistrationLockEnabled()).append("\n")
|
||||
.append("Signal PIN: ").append(SignalStore.svr().hasPin()).append("\n")
|
||||
.append("Restored via AEP: ").append(SignalStore.account().restoredAccountEntropyPool()).append("\n")
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.thoughtcrime.securesms.service.webrtc.AndroidTelecomUtil.telecomSuppo
|
||||
import org.thoughtcrime.securesms.util.AppSignatureUtil
|
||||
import org.thoughtcrime.securesms.util.NetworkUtil
|
||||
import org.thoughtcrime.securesms.util.PowerManagerCompat
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.VersionTracker.getDaysSinceFirstInstalled
|
||||
import java.util.Locale
|
||||
import kotlin.math.roundToLong
|
||||
@@ -71,7 +70,7 @@ class LogSectionSystemInfo : LogSection {
|
||||
FCM : ${SignalStore.account.fcmEnabled}
|
||||
Locale : ${Locale.getDefault()}
|
||||
Linked Devices : ${SignalStore.account.isMultiDevice}
|
||||
First Version : ${TextSecurePreferences.getFirstInstallVersion(context)}
|
||||
First Version : ${SignalStore.misc.firstInstallVersion}
|
||||
Days Installed : ${getDaysSinceFirstInstalled(context)}
|
||||
Last Registration : ${getTimeRegistered()}
|
||||
Build Variant : ${BuildConfig.BUILD_DISTRIBUTION_TYPE}${BuildConfig.BUILD_ENVIRONMENT_TYPE}${BuildConfig.BUILD_VARIANT_TYPE}
|
||||
|
||||
@@ -48,7 +48,6 @@ import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.Environment;
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.signal.core.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.VersionTracker;
|
||||
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
|
||||
|
||||
@@ -131,7 +130,7 @@ public final class Megaphones {
|
||||
// Specifically putting backup reminders here, above PIN reminders
|
||||
put(Event.BACKUP_LOW_STORAGE_UPSELL, shouldShowBackupLowStorageUpsell(context) ? new BackupUpsellSchedule(records, TimeUnit.DAYS.toMillis(60), TimeUnit.DAYS.toMillis(120)) : NEVER);
|
||||
put(Event.BACKUP_MEDIA_SIZE_UPSELL, shouldShowBackupMediaSizeUpsell() ? new BackupUpsellSchedule(records, TimeUnit.DAYS.toMillis(60), TimeUnit.DAYS.toMillis(120)) : NEVER);
|
||||
put(Event.BACKUP_MESSAGE_COUNT_UPSELL, shouldShowBackupMessageCountUpsell(context) ? new BackupUpsellSchedule(records, TimeUnit.DAYS.toMillis(60)) : NEVER);
|
||||
put(Event.BACKUP_MESSAGE_COUNT_UPSELL, shouldShowBackupMessageCountUpsell() ? new BackupUpsellSchedule(records, TimeUnit.DAYS.toMillis(60)) : NEVER);
|
||||
put(Event.BACKUPS_GENERIC_UPSELL, shouldShowGenericBackupsMegaphone(context) ? new BackupUpsellSchedule(records, TimeUnit.DAYS.toMillis(60)) : NEVER);
|
||||
put(Event.VERIFY_BACKUP_KEY, new VerifyBackupKeyReminderSchedule());
|
||||
put(Event.USE_NEW_ON_DEVICE_BACKUPS, shouldShowUseNewOnDeviceBackupsMegaphone() ? RecurringSchedule.every(TimeUnit.DAYS.toMillis(7)) : NEVER);
|
||||
@@ -273,7 +272,7 @@ public final class Megaphones {
|
||||
|
||||
SignalStore.pin().onEntrySkip(includedFailure);
|
||||
controller.onMegaphoneSnooze(Event.PIN_REMINDER);
|
||||
controller.onMegaphoneToastRequested(controller.getMegaphoneActivity().getString(SignalPinReminders.getSkipReminderString(SignalStore.pin().getCurrentInterval())));
|
||||
controller.onMegaphoneToastRequested(controller.getMegaphoneActivity().getString(SignalPinReminders.getSkipReminderString(SignalStore.pin().getNextReminderInterval())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -286,7 +285,7 @@ public final class Megaphones {
|
||||
}
|
||||
|
||||
controller.onMegaphoneSnooze(Event.PIN_REMINDER);
|
||||
controller.onMegaphoneToastRequested(controller.getMegaphoneActivity().getString(SignalPinReminders.getReminderString(SignalStore.pin().getCurrentInterval())));
|
||||
controller.onMegaphoneToastRequested(controller.getMegaphoneActivity().getString(SignalPinReminders.getReminderString(SignalStore.pin().getNextReminderInterval())));
|
||||
}
|
||||
});
|
||||
})
|
||||
@@ -624,7 +623,7 @@ public final class Megaphones {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SignalStore.account().isRegistered() || TextSecurePreferences.isUnauthorizedReceived(context) || SignalStore.account().isLinkedDevice()) {
|
||||
if (!SignalStore.account().isRegistered() || SignalStore.account().isUnauthorizedReceived() || SignalStore.account().isLinkedDevice()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -667,8 +666,8 @@ public final class Megaphones {
|
||||
return System.currentTimeMillis() - lastSeenDonatePrompt;
|
||||
}
|
||||
|
||||
private static boolean shouldShowBackupMessageCountUpsell(@NonNull Context context) {
|
||||
if (!SignalStore.account().isRegistered() || TextSecurePreferences.isUnauthorizedReceived(context) || SignalStore.account().isLinkedDevice()) {
|
||||
private static boolean shouldShowBackupMessageCountUpsell() {
|
||||
if (!SignalStore.account().isRegistered() || SignalStore.account().isUnauthorizedReceived() || SignalStore.account().isLinkedDevice()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -692,7 +691,7 @@ public final class Megaphones {
|
||||
}
|
||||
|
||||
private static boolean shouldShowBackupLowStorageUpsell(@NonNull Context context) {
|
||||
if (!SignalStore.account().isRegistered() || TextSecurePreferences.isUnauthorizedReceived(context) || SignalStore.account().isLinkedDevice() || !Environment.Backups.supportsGooglePlayBilling()) {
|
||||
if (!SignalStore.account().isRegistered() || SignalStore.account().isUnauthorizedReceived() || SignalStore.account().isLinkedDevice() || !Environment.Backups.supportsGooglePlayBilling()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ final class SignalPinReminderSchedule implements MegaphoneSchedule {
|
||||
}
|
||||
|
||||
long lastReminderTime = SignalStore.pin().getLastReminderTime();
|
||||
long interval = SignalStore.pin().getCurrentInterval();
|
||||
long interval = SignalStore.pin().getNextReminderInterval();
|
||||
|
||||
return currentTime - lastReminderTime >= interval;
|
||||
}
|
||||
|
||||
@@ -860,7 +860,7 @@ object DataMessageProcessor {
|
||||
val giftBadge: DataMessage.GiftBadge = message.giftBadge!!
|
||||
check(giftBadge.receiptCredentialPresentation != null)
|
||||
|
||||
notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipientId, metadata.sourceDeviceId)
|
||||
notifyTypingStoppedFromIncomingMessage(senderRecipient, threadRecipientId, metadata.sourceDeviceId)
|
||||
|
||||
val token = ReceiptCredentialPresentation(giftBadge.receiptCredentialPresentation!!.toByteArray()).serialize()
|
||||
val dbGiftBadge = GiftBadge.Builder()
|
||||
@@ -911,7 +911,7 @@ object DataMessageProcessor {
|
||||
): InsertResult? {
|
||||
log(envelope.clientTimestamp!!, "Media message.")
|
||||
|
||||
notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
||||
notifyTypingStoppedFromIncomingMessage(senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
||||
|
||||
val insertResult: InsertResult?
|
||||
|
||||
@@ -1018,7 +1018,7 @@ object DataMessageProcessor {
|
||||
|
||||
handlePossibleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient, groupId, message.expireTimerDuration, message.expireTimerVersion, receivedTime)
|
||||
|
||||
notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
||||
notifyTypingStoppedFromIncomingMessage(senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
||||
|
||||
val textMessage = IncomingMessage(
|
||||
type = MessageType.NORMAL,
|
||||
@@ -1479,7 +1479,7 @@ object DataMessageProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyTypingStoppedFromIncomingMessage(context: Context, senderRecipient: Recipient, threadRecipientId: RecipientId, device: Int) {
|
||||
fun notifyTypingStoppedFromIncomingMessage(senderRecipient: Recipient, threadRecipientId: RecipientId, device: Int) {
|
||||
val threadId = SignalDatabase.threads.getThreadIdIfExistsFor(threadRecipientId)
|
||||
|
||||
if (threadId > 0 && SignalStore.settings.isTypingIndicatorsEnabled) {
|
||||
|
||||
@@ -85,7 +85,7 @@ object EditMessageProcessor {
|
||||
return
|
||||
}
|
||||
|
||||
DataMessageProcessor.notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
||||
DataMessageProcessor.notifyTypingStoppedFromIncomingMessage(senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
||||
|
||||
targetMessage = targetMessage.withAttachments(SignalDatabase.attachments.getAttachmentsForMessage(targetMessage.id))
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ import org.thoughtcrime.securesms.util.AlarmSleepTimer
|
||||
import org.thoughtcrime.securesms.util.Environment
|
||||
import org.thoughtcrime.securesms.util.SignalLocalMetrics
|
||||
import org.thoughtcrime.securesms.util.SignalTrace
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.asChain
|
||||
import org.whispersystems.signalservice.api.messages.EnvelopeResponse
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
@@ -176,7 +175,7 @@ class IncomingMessageObserver(
|
||||
|
||||
MessageRetrievalThread().start()
|
||||
|
||||
val registered = SignalStore.account.isRegistered && !TextSecurePreferences.isUnauthorizedReceived(context)
|
||||
val registered = SignalStore.account.isRegistered && !SignalStore.account.isUnauthorizedReceived
|
||||
if (registered && (!SignalStore.account.fcmEnabled || SignalStore.settings.forceWebsocketMode.isEnabled)) {
|
||||
SignalExecutors.UNBOUNDED.execute {
|
||||
if (!SafeForegroundService.start(context, ForegroundService::class.java)) {
|
||||
@@ -251,7 +250,7 @@ class IncomingMessageObserver(
|
||||
val timeIdle = if (isForeground) 0 else System.currentTimeMillis() - lastInteractionTime
|
||||
|
||||
val registered = SignalStore.account.isRegistered
|
||||
val unauthorizedReceived = TextSecurePreferences.isUnauthorizedReceived(context)
|
||||
val unauthorizedReceived = SignalStore.account.isUnauthorizedReceived
|
||||
val fcmEnabled = SignalStore.account.fcmEnabled
|
||||
val hasNetwork = NetworkConstraint.isMet(context)
|
||||
val hasProxy = SignalStore.proxy.isProxyEnabled
|
||||
@@ -278,7 +277,7 @@ class IncomingMessageObserver(
|
||||
}
|
||||
|
||||
private fun isConnectionAvailable(): Boolean {
|
||||
return !TextSecurePreferences.isUnauthorizedReceived(context) && SignalStore.account.isRegistered && (authWebSocket.stateSnapshot == WebSocketConnectionState.CONNECTED || (authWebSocket.shouldSendKeepAlives() && NetworkConstraint.isMet(context)))
|
||||
return !SignalStore.account.isUnauthorizedReceived && SignalStore.account.isRegistered && (authWebSocket.stateSnapshot == WebSocketConnectionState.CONNECTED || (authWebSocket.shouldSendKeepAlives() && NetworkConstraint.isMet(context)))
|
||||
}
|
||||
|
||||
/** Conditions are evaluated outside of [connectionLock] so notifiers never block on them. We only park if nothing signaled since the version we evaluated against. */
|
||||
|
||||
@@ -518,7 +518,6 @@ open class MessageContentProcessor(private val context: Context) {
|
||||
|
||||
content.receiptMessage != null -> {
|
||||
ReceiptMessageProcessor.process(
|
||||
context,
|
||||
senderRecipient,
|
||||
envelope,
|
||||
content,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.thoughtcrime.securesms.messages
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import org.signal.core.util.Stopwatch
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
@@ -22,13 +21,13 @@ object ReceiptMessageProcessor {
|
||||
|
||||
private const val VERBOSE = false
|
||||
|
||||
fun process(context: Context, senderRecipient: Recipient, envelope: Envelope, content: Content, metadata: EnvelopeMetadata, earlyMessageCacheEntry: EarlyMessageCacheEntry?, batchCache: BatchCache) {
|
||||
fun process(senderRecipient: Recipient, envelope: Envelope, content: Content, metadata: EnvelopeMetadata, earlyMessageCacheEntry: EarlyMessageCacheEntry?, batchCache: BatchCache) {
|
||||
val receiptMessage = content.receiptMessage!!
|
||||
|
||||
when (receiptMessage.type) {
|
||||
ReceiptMessage.Type.DELIVERY -> handleDeliveryReceipt(envelope, metadata, receiptMessage, senderRecipient.id, batchCache)
|
||||
ReceiptMessage.Type.READ -> handleReadReceipt(context, senderRecipient.id, envelope, metadata, receiptMessage, earlyMessageCacheEntry, batchCache)
|
||||
ReceiptMessage.Type.VIEWED -> handleViewedReceipt(context, envelope, metadata, receiptMessage, senderRecipient.id, earlyMessageCacheEntry, batchCache)
|
||||
ReceiptMessage.Type.READ -> handleReadReceipt(senderRecipient.id, envelope, metadata, receiptMessage, earlyMessageCacheEntry, batchCache)
|
||||
ReceiptMessage.Type.VIEWED -> handleViewedReceipt(envelope, metadata, receiptMessage, senderRecipient.id, earlyMessageCacheEntry, batchCache)
|
||||
else -> warn(envelope.clientTimestamp!!, "Unknown recipient message type ${receiptMessage.type}")
|
||||
}
|
||||
}
|
||||
@@ -68,7 +67,6 @@ object ReceiptMessageProcessor {
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
private fun handleReadReceipt(
|
||||
context: Context,
|
||||
senderRecipientId: RecipientId,
|
||||
envelope: Envelope,
|
||||
metadata: EnvelopeMetadata,
|
||||
@@ -104,7 +102,6 @@ object ReceiptMessageProcessor {
|
||||
}
|
||||
|
||||
private fun handleViewedReceipt(
|
||||
context: Context,
|
||||
envelope: Envelope,
|
||||
metadata: EnvelopeMetadata,
|
||||
viewedReceipt: ReceiptMessage,
|
||||
|
||||
@@ -174,13 +174,13 @@ object SyncMessageProcessor {
|
||||
|
||||
when {
|
||||
syncMessage.sent != null -> handleSynchronizeSentMessage(context, envelope, content, metadata, syncMessage.sent!!, senderRecipient, threadRecipient, earlyMessageCacheEntry, batchCache)
|
||||
syncMessage.request != null -> handleSynchronizeRequestMessage(context, syncMessage.request!!, envelope.clientTimestamp!!)
|
||||
syncMessage.request != null -> handleSynchronizeRequestMessage(syncMessage.request!!, envelope.clientTimestamp!!)
|
||||
syncMessage.read.isNotEmpty() -> handleSynchronizeReadMessage(context, syncMessage.read, envelope.clientTimestamp!!, earlyMessageCacheEntry, batchCache)
|
||||
syncMessage.viewed.isNotEmpty() -> handleSynchronizeViewedMessage(context, syncMessage.viewed, envelope.clientTimestamp!!)
|
||||
syncMessage.viewOnceOpen != null -> handleSynchronizeViewOnceOpenMessage(context, syncMessage.viewOnceOpen!!, envelope.clientTimestamp!!, earlyMessageCacheEntry, batchCache)
|
||||
syncMessage.verified != null -> handleSynchronizeVerifiedMessage(context, syncMessage.verified!!)
|
||||
syncMessage.stickerPackOperation.isNotEmpty() -> handleSynchronizeStickerPackOperation(syncMessage.stickerPackOperation, envelope.clientTimestamp!!)
|
||||
syncMessage.configuration != null -> handleSynchronizeConfigurationMessage(context, syncMessage.configuration!!, envelope.clientTimestamp!!)
|
||||
syncMessage.configuration != null -> handleSynchronizeConfigurationMessage(syncMessage.configuration!!, envelope.clientTimestamp!!)
|
||||
syncMessage.blocked != null -> handleSynchronizeBlockedListMessage(syncMessage.blocked!!, envelope.clientTimestamp!!)
|
||||
syncMessage.fetchLatest?.type != null -> handleSynchronizeFetchMessage(syncMessage.fetchLatest!!.type!!, envelope.clientTimestamp!!)
|
||||
syncMessage.messageRequestResponse != null -> handleSynchronizeMessageRequestResponse(syncMessage.messageRequestResponse!!, envelope.clientTimestamp!!)
|
||||
@@ -978,7 +978,7 @@ object SyncMessageProcessor {
|
||||
return threadId
|
||||
}
|
||||
|
||||
private fun handleSynchronizeRequestMessage(context: Context, message: Request, envelopeTimestamp: Long) {
|
||||
private fun handleSynchronizeRequestMessage(message: Request, envelopeTimestamp: Long) {
|
||||
if (SignalStore.account.isPrimaryDevice) {
|
||||
log(envelopeTimestamp, "Synchronize request message.")
|
||||
} else {
|
||||
@@ -1135,7 +1135,7 @@ object SyncMessageProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSynchronizeConfigurationMessage(context: Context, configurationMessage: Configuration, envelopeTimestamp: Long) {
|
||||
private fun handleSynchronizeConfigurationMessage(configurationMessage: Configuration, envelopeTimestamp: Long) {
|
||||
log(envelopeTimestamp, "Synchronize configuration message.")
|
||||
|
||||
if (configurationMessage.readReceipts != null) {
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ public class ApplyUnknownFieldsToSelfMigrationJob extends MigrationJob {
|
||||
SignalAccountRecord signalAccountRecord = new SignalAccountRecord(storageId, accountRecord);
|
||||
|
||||
Log.d(TAG, "Applying potentially now known unknowns");
|
||||
StorageSyncHelper.applyAccountStorageSyncUpdates(context, self, signalAccountRecord, false);
|
||||
StorageSyncHelper.applyAccountStorageSyncUpdates(self, signalAccountRecord, false);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.util.FileUtils;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.VersionTracker;
|
||||
|
||||
import java.io.File;
|
||||
@@ -166,7 +165,7 @@ public class LegacyMigrationJob extends MigrationJob {
|
||||
|
||||
if (lastSeenVersion < INTERNALIZE_CONTACTS) {
|
||||
if (SignalStore.account().isRegistered()) {
|
||||
TextSecurePreferences.setHasSuccessfullyRetrievedDirectory(context, true);
|
||||
SignalStore.misc().setHasSuccessfullyRetrievedDirectory(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
||||
import org.thoughtcrime.securesms.jobs.RefreshOwnProfileJob;
|
||||
import org.thoughtcrime.securesms.jobs.StorageForcePushJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
/**
|
||||
* This does a couple things:
|
||||
|
||||
-1
@@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceStorageSyncRequestJob;
|
||||
import org.thoughtcrime.securesms.jobs.StorageSyncJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
/**
|
||||
* Just runs a storage sync. Useful if you've started syncing a new field to storage service.
|
||||
|
||||
+1
-2
@@ -26,7 +26,6 @@ import org.thoughtcrime.securesms.MainActivity;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationIds;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -73,7 +72,7 @@ public class UserNotificationMigrationJob extends MigrationJob {
|
||||
return;
|
||||
}
|
||||
|
||||
if (TextSecurePreferences.getFirstInstallVersion(context) < 759) {
|
||||
if (SignalStore.misc().getFirstInstallVersion() < 759) {
|
||||
Log.w(TAG, "Install is older than v5.0.8. Skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ import org.signal.core.util.AppForegroundObserver
|
||||
import org.signal.core.util.SleepTimer
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.clockskew.ClockSkewDetector
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.websocket.HealthMonitor
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
|
||||
@@ -91,13 +89,13 @@ class SignalWebSocketHealthMonitor(
|
||||
}
|
||||
WebSocketConnectionState.CONNECTED -> {
|
||||
if (webSocket is SignalWebSocket.AuthenticatedWebSocket) {
|
||||
TextSecurePreferences.setUnauthorizedReceived(AppDependencies.application, false)
|
||||
SignalStore.account.isUnauthorizedReceived = false
|
||||
}
|
||||
failedInConnecting = false
|
||||
}
|
||||
WebSocketConnectionState.AUTHENTICATION_FAILED -> {
|
||||
if (webSocket is SignalWebSocket.AuthenticatedWebSocket) {
|
||||
TextSecurePreferences.setUnauthorizedReceived(AppDependencies.application, true)
|
||||
SignalStore.account.isUnauthorizedReceived = true
|
||||
}
|
||||
}
|
||||
WebSocketConnectionState.REMOTE_DEPRECATED -> {
|
||||
|
||||
+7
-8
@@ -37,7 +37,6 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.ConversationUtil;
|
||||
import org.signal.core.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -113,10 +112,10 @@ public class NotificationChannels {
|
||||
|
||||
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
|
||||
|
||||
int oldVersion = TextSecurePreferences.getNotificationChannelVersion(context);
|
||||
int oldVersion = SignalStore.misc().getNotificationChannelVersion();
|
||||
if (oldVersion != VERSION) {
|
||||
onUpgrade(notificationManager, oldVersion, VERSION);
|
||||
TextSecurePreferences.setNotificationChannelVersion(context, VERSION);
|
||||
SignalStore.misc().setNotificationChannelVersion(VERSION);
|
||||
}
|
||||
|
||||
onCreate(notificationManager);
|
||||
@@ -214,7 +213,7 @@ public class NotificationChannels {
|
||||
* @return The channel ID for the default messages channel.
|
||||
*/
|
||||
public synchronized @NonNull String getMessagesChannel() {
|
||||
return getMessagesChannelId(TextSecurePreferences.getNotificationMessagesChannelVersion(context));
|
||||
return getMessagesChannelId(SignalStore.misc().getNotificationMessagesChannelVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -709,7 +708,7 @@ public class NotificationChannels {
|
||||
|
||||
if (oldVersion < Version.AUDIO_ATTRIBUTE_CHANGE) {
|
||||
Context context = AppDependencies.getApplication();
|
||||
int existingMessageChannelVersion = TextSecurePreferences.getNotificationMessagesChannelVersion(context);
|
||||
int existingMessageChannelVersion = SignalStore.misc().getNotificationMessagesChannelVersion();
|
||||
int newMessageChannelVersion = existingMessageChannelVersion + 1;
|
||||
String existingChannelId = "messages_" + existingMessageChannelVersion;
|
||||
String newChannelId = "messages_" + newMessageChannelVersion;
|
||||
@@ -734,7 +733,7 @@ public class NotificationChannels {
|
||||
|
||||
notificationManager.createNotificationChannel(newChannel);
|
||||
|
||||
TextSecurePreferences.setNotificationMessagesChannelVersion(context, newMessageChannelVersion);
|
||||
SignalStore.misc().setNotificationMessagesChannelVersion(newMessageChannelVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -803,12 +802,12 @@ public class NotificationChannels {
|
||||
@TargetApi(26)
|
||||
private void updateMessageChannel(@NonNull ChannelUpdater updater) {
|
||||
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
|
||||
int existingVersion = TextSecurePreferences.getNotificationMessagesChannelVersion(context);
|
||||
int existingVersion = SignalStore.misc().getNotificationMessagesChannelVersion();
|
||||
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);
|
||||
SignalStore.misc().setNotificationMessagesChannelVersion(newVersion);
|
||||
} else {
|
||||
onCreate(notificationManager);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.notifications
|
||||
|
||||
import android.Manifest
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import org.signal.core.util.PendingIntentFlags
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.registration.ui.RegistrationActivity
|
||||
|
||||
/**
|
||||
* Notification shown when the service tells us our credentials are no longer valid, prompting the user to re-register or re-link.
|
||||
*/
|
||||
object UnregisteredNotifier {
|
||||
|
||||
private val TAG = Log.tag(UnregisteredNotifier::class)
|
||||
|
||||
fun notify(context: Context) {
|
||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
|
||||
Log.w(TAG, "Notification permission is not granted.")
|
||||
return
|
||||
}
|
||||
|
||||
val registrationIntent = if (SignalStore.account.isLinkedDevice) {
|
||||
RegistrationActivity.newIntentForReLinkDevice(context)
|
||||
} else {
|
||||
RegistrationActivity.newIntentForReRegistration(context)
|
||||
}
|
||||
|
||||
val reRegistrationIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
registrationIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentFlags.immutable()
|
||||
)
|
||||
|
||||
val notification = NotificationCompat.Builder(context, NotificationChannels.getInstance().FAILURES)
|
||||
.setSmallIcon(R.drawable.ic_signal_logo_large)
|
||||
.setContentText(context.getString(R.string.LoggedOutNotification_you_have_been_logged_out))
|
||||
.setContentIntent(reRegistrationIntent)
|
||||
.setOnlyAlertOnce(true)
|
||||
.setAutoCancel(true)
|
||||
.build()
|
||||
|
||||
NotificationManagerCompat.from(context).notify(NotificationIds.UNREGISTERED_NOTIFICATION_ID, notification)
|
||||
}
|
||||
|
||||
fun cancel(context: Context) {
|
||||
NotificationManagerCompat.from(context).cancel(NotificationIds.UNREGISTERED_NOTIFICATION_ID)
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.notifications.DeviceSpecificNotificationConfig.ShowCondition
|
||||
import org.thoughtcrime.securesms.util.ConnectivityWarning
|
||||
import org.thoughtcrime.securesms.util.NetworkUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.time.Duration.Companion.days
|
||||
@@ -79,7 +78,7 @@ class VitalsViewModel(private val context: Application) : AndroidViewModel(conte
|
||||
val timeSinceLastConnection = System.currentTimeMillis() - SignalStore.misc.lastWebSocketConnectTime
|
||||
val timeSinceLastConnectionWarning = System.currentTimeMillis() - SignalStore.misc.lastConnectivityWarningTime
|
||||
val connectedToWebSocket = AppDependencies.webSocketObserver.value == WebSocketConnectionState.CONNECTED
|
||||
val isRegistered = SignalStore.account.isRegistered && !TextSecurePreferences.isUnauthorizedReceived(context)
|
||||
val isRegistered = SignalStore.account.isRegistered && !SignalStore.account.isUnauthorizedReceived
|
||||
|
||||
if (ConnectivityWarning.isEnabled && timeSinceLastConnection > ConnectivityWarning.threshold && timeSinceLastConnectionWarning > 14.days.inWholeMilliseconds && NetworkUtil.isConnected(context) && isRegistered && !connectedToWebSocket) {
|
||||
return@fromCallable if (ConnectivityWarning.isDebugPromptEnabled) {
|
||||
|
||||
+1
-2
@@ -46,7 +46,6 @@ import org.thoughtcrime.securesms.service.LocalBackupListener;
|
||||
import org.thoughtcrime.securesms.util.BackupUtil;
|
||||
import org.thoughtcrime.securesms.util.Environment;
|
||||
import org.thoughtcrime.securesms.util.JavaTimeExtensionsKt;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.time.LocalTime;
|
||||
@@ -330,7 +329,7 @@ public class BackupsPreferenceFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void updateToggle() {
|
||||
boolean userUnregistered = TextSecurePreferences.isUnauthorizedReceived(AppDependencies.getApplication()) || !SignalStore.account().isRegistered();
|
||||
boolean userUnregistered = SignalStore.account().isUnauthorizedReceived() || !SignalStore.account().isRegistered();
|
||||
boolean clientDeprecated = SignalStore.misc().isClientDeprecated();
|
||||
boolean legacyLocalBackupsEnabled = SignalStore.settings().isBackupEnabled() && BackupUtil.canUserAccessBackupDirectory(AppDependencies.getApplication());
|
||||
|
||||
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
package org.thoughtcrime.securesms.preferences;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceGroupAdapter;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.CustomDefaultPreference;
|
||||
|
||||
public abstract class CorrectedPreferenceFragment extends PreferenceFragmentCompat {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
View lv = getView().findViewById(android.R.id.list);
|
||||
if (lv != null) lv.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@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) {
|
||||
return new PreferenceGroupAdapter(preferenceScreen) {
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder, int position) {
|
||||
super.onBindViewHolder(holder, position);
|
||||
Preference preference = getItem(position);
|
||||
if (preference instanceof PreferenceCategory) {
|
||||
setZeroPaddingToLayoutChildren(holder.itemView);
|
||||
} else {
|
||||
View iconFrame = holder.itemView.findViewById(androidx.preference.R.id.icon_frame);
|
||||
if (iconFrame != null) {
|
||||
iconFrame.setVisibility(preference.getIcon() == null ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setZeroPaddingToLayoutChildren(View view) {
|
||||
if (!(view instanceof ViewGroup)) return;
|
||||
|
||||
ViewGroup viewGroup = (ViewGroup) view;
|
||||
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
||||
setZeroPaddingToLayoutChildren(viewGroup.getChildAt(i));
|
||||
ViewCompat.setPaddingRelative(viewGroup, 0, viewGroup.getPaddingTop(), ViewCompat.getPaddingEnd(viewGroup), viewGroup.getPaddingBottom());
|
||||
}
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
package org.thoughtcrime.securesms.preferences;
|
||||
|
||||
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public abstract class ListSummaryPreferenceFragment extends CorrectedPreferenceFragment {
|
||||
|
||||
protected class ListSummaryListener implements Preference.OnPreferenceChangeListener {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object value) {
|
||||
ListPreference listPref = (ListPreference) preference;
|
||||
int entryIndex = Arrays.asList(listPref.getEntryValues()).indexOf(value);
|
||||
|
||||
listPref.setSummary(entryIndex >= 0 && entryIndex < listPref.getEntries().length
|
||||
? listPref.getEntries()[entryIndex]
|
||||
: getString(R.string.preferences__led_color_unknown));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void initializeListSummary(ListPreference pref) {
|
||||
pref.setSummary(pref.getEntry());
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -24,7 +24,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
|
||||
import org.thoughtcrime.securesms.util.DefaultValueLiveData;
|
||||
import org.thoughtcrime.securesms.util.SingleLiveEvent;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||
|
||||
@@ -107,7 +106,7 @@ class EditProfileViewModel extends ViewModel {
|
||||
}
|
||||
|
||||
public boolean isRegisteredAndUpToDate() {
|
||||
return !TextSecurePreferences.isUnauthorizedReceived(AppDependencies.getApplication()) && SignalStore.account().isRegistered() && !SignalStore.misc().isClientDeprecated();
|
||||
return !SignalStore.account().isUnauthorizedReceived() && SignalStore.account().isRegistered() && !SignalStore.misc().isClientDeprecated();
|
||||
}
|
||||
|
||||
public boolean isDeprecated() {
|
||||
|
||||
@@ -117,7 +117,7 @@ class AvatarProvider : BaseContentProvider() {
|
||||
if (uriMatcher.match(uri) == AVATAR) {
|
||||
if (VERBOSE) Log.i(TAG, "Loading avatar.")
|
||||
try {
|
||||
val recipient = getRecipientId(uri)?.let { RecipientCreator.forRecord(application, SignalDatabase.recipients.getRecord(it)) } ?: return null
|
||||
val recipient = getRecipientId(uri)?.let { RecipientCreator.forRecord(SignalDatabase.recipients.getRecord(it)) } ?: return null
|
||||
return getParcelFileDescriptorForAvatar(recipient)
|
||||
} catch (ioe: IOException) {
|
||||
Log.w(TAG, ioe)
|
||||
|
||||
+2
-2
@@ -39,7 +39,7 @@ import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView;
|
||||
import org.thoughtcrime.securesms.reactions.ReactionsRepository;
|
||||
import org.thoughtcrime.securesms.reactions.edit.EditReactionsActivity;
|
||||
import org.thoughtcrime.securesms.util.SystemWindowInsetsSetter;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel;
|
||||
|
||||
@@ -52,7 +52,7 @@ public final class ReactWithAnyEmojiBottomSheetDialogFragment extends FixedRound
|
||||
{
|
||||
|
||||
public static final String REACTION_STORAGE_KEY = "reactions_recent_emoji";
|
||||
private static final String ABOUT_STORAGE_KEY = TextSecurePreferences.RECENT_STORAGE_KEY;
|
||||
private static final String ABOUT_STORAGE_KEY = RecentEmojiPageModel.RECENT_STORAGE_KEY;
|
||||
|
||||
private static final String ARG_MESSAGE_ID = "arg_message_id";
|
||||
private static final String ARG_IS_MMS = "arg_is_mms";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user