diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 5087902012..7f03743aa8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -273,7 +273,7 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr public void checkBuildExpiration() { if (Util.getTimeUntilBuildExpiry() <= 0 && !SignalStore.misc().isClientDeprecated()) { Log.w(TAG, "Build expired!"); - SignalStore.misc().markClientDeprecated(); + SignalStore.misc().setClientDeprecated(true); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/MainActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MainActivity.java index 89a5b1d337..98671047d5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MainActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MainActivity.java @@ -152,7 +152,7 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot .setMessage(R.string.OldDeviceTransferLockedDialog__your_signal_account_has_been_transferred_to_your_new_device) .setPositiveButton(R.string.OldDeviceTransferLockedDialog__done, (d, w) -> OldDeviceExitActivity.exit(this)) .setNegativeButton(R.string.OldDeviceTransferLockedDialog__cancel_and_activate_this_device, (d, w) -> { - SignalStore.misc().clearOldDeviceTransferLocked(); + SignalStore.misc().setOldDeviceTransferLocked(false); DeviceTransferBlockingInterceptor.getInstance().unblockNetwork(); }) .setCancelable(false) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberRepository.kt index 8ee18e1265..96a8098266 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberRepository.kt @@ -291,7 +291,7 @@ class ChangeNumberRepository( true ) - SignalStore.misc().setPniInitializedDevices(true) + SignalStore.misc().hasPniInitializedDevices = true ApplicationDependencies.getGroupsV2Authorization().clear() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/InternalSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/InternalSettingsViewModel.kt index 494edd977f..bfff5057eb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/InternalSettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/InternalSettingsViewModel.kt @@ -75,7 +75,7 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito } fun resetPnpInitializedState() { - SignalStore.misc().setPniInitializedDevices(false) + SignalStore.misc().hasPniInitializedDevices = false refresh() } @@ -159,7 +159,7 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito delayResends = SignalStore.internalValues().delayResends(), disableStorageService = SignalStore.internalValues().storageServiceDisabled(), canClearOnboardingState = SignalStore.storyValues().hasDownloadedOnboardingStory && Stories.isFeatureEnabled(), - pnpInitialized = SignalStore.misc().hasPniInitializedDevices(), + pnpInitialized = SignalStore.misc().hasPniInitializedDevices, useConversationItemV2ForMedia = SignalStore.internalValues().useConversationItemV2Media(), hasPendingOneTimeDonation = SignalStore.donationsValues().getPendingOneTimeDonation() != null ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/devicetransfer/olddevice/OldDeviceClientTask.java b/app/src/main/java/org/thoughtcrime/securesms/devicetransfer/olddevice/OldDeviceClientTask.java index 948dddf52d..49ca457e38 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/devicetransfer/olddevice/OldDeviceClientTask.java +++ b/app/src/main/java/org/thoughtcrime/securesms/devicetransfer/olddevice/OldDeviceClientTask.java @@ -67,7 +67,7 @@ final class OldDeviceClientTask implements ClientTask { @Override public void success() { - SignalStore.misc().markOldDeviceTransferLocked(); + SignalStore.misc().setOldDeviceTransferLocked(true); EventBus.getDefault().post(new Status(0, 0, 0,true)); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PnpInitializeDevicesJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/PnpInitializeDevicesJob.kt index 27c52d36bc..2c9f6b3d78 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PnpInitializeDevicesJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PnpInitializeDevicesJob.kt @@ -48,7 +48,7 @@ class PnpInitializeDevicesJob private constructor(parameters: Parameters) : Base @JvmStatic fun enqueueIfNecessary() { - if (SignalStore.misc().hasPniInitializedDevices() || !SignalStore.account().isRegistered || SignalStore.account().aci == null) { + if (SignalStore.misc().hasPniInitializedDevices || !SignalStore.account().isRegistered || SignalStore.account().aci == null) { return } @@ -77,19 +77,19 @@ class PnpInitializeDevicesJob private constructor(parameters: Parameters) : Base if (!TextSecurePreferences.isMultiDevice(context)) { Log.i(TAG, "Not multi device, aborting...") - SignalStore.misc().setPniInitializedDevices(true) + SignalStore.misc().hasPniInitializedDevices = true return } if (SignalStore.account().isLinkedDevice) { Log.i(TAG, "Not primary device, aborting...") - SignalStore.misc().setPniInitializedDevices(true) + SignalStore.misc().hasPniInitializedDevices = true return } ChangeNumberRepository.CHANGE_NUMBER_LOCK.lock() try { - if (SignalStore.misc().hasPniInitializedDevices()) { + if (SignalStore.misc().hasPniInitializedDevices) { Log.w(TAG, "We found out that things have been initialized after we got the lock! No need to do anything else.") return } @@ -110,7 +110,7 @@ class PnpInitializeDevicesJob private constructor(parameters: Parameters) : Base throw t } - SignalStore.misc().setPniInitializedDevices(true) + SignalStore.misc().hasPniInitializedDevices = true } finally { ChangeNumberRepository.CHANGE_NUMBER_LOCK.unlock() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java index 39addaa8c4..85c220b0c9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java @@ -127,7 +127,7 @@ public class RetrieveProfileAvatarJob extends BaseJob { AvatarHelper.setAvatar(context, recipient.getId(), avatarStream); if (recipient.isSelf()) { - SignalStore.misc().markHasEverHadAnAvatar(); + SignalStore.misc().setHasEverHadAnAvatar(true); } } catch (AssertionError e) { throw new IOException("Failed to copy stream. Likely a Conscrypt issue.", e); diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.java b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.java deleted file mode 100644 index 6bb6f5364f..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.java +++ /dev/null @@ -1,373 +0,0 @@ -package org.thoughtcrime.securesms.keyvalue; - -import android.preference.PreferenceManager; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.thoughtcrime.securesms.components.settings.app.usernamelinks.UsernameQrCodeColorScheme; -import org.thoughtcrime.securesms.database.model.databaseprotos.PendingChangeNumberMetadata; -import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; -import org.thoughtcrime.securesms.jobmanager.impl.ChangeNumberConstraintObserver; - -import java.util.Collections; -import java.util.List; - -public final class MiscellaneousValues extends SignalStoreValues { - - private static final String LAST_PREKEY_REFRESH_TIME = "last_prekey_refresh_time"; - private static final String MESSAGE_REQUEST_ENABLE_TIME = "message_request_enable_time"; - private static final String LAST_PROFILE_REFRESH_TIME = "misc.last_profile_refresh_time"; - private static final String USERNAME_SHOW_REMINDER = "username.show.reminder"; - private static final String CLIENT_DEPRECATED = "misc.client_deprecated"; - private static final String OLD_DEVICE_TRANSFER_LOCKED = "misc.old_device.transfer.locked"; - private static final String HAS_EVER_HAD_AN_AVATAR = "misc.has.ever.had.an.avatar"; - private static final String CHANGE_NUMBER_LOCK = "misc.change_number.lock"; - private static final String PENDING_CHANGE_NUMBER_METADATA = "misc.pending_change_number.metadata"; - private static final String CENSORSHIP_LAST_CHECK_TIME = "misc.censorship.last_check_time"; - private static final String CENSORSHIP_SERVICE_REACHABLE = "misc.censorship.service_reachable"; - private static final String LAST_GV2_PROFILE_CHECK_TIME = "misc.last_gv2_profile_check_time"; - private static final String CDS_TOKEN = "misc.cds_token"; - private static final String CDS_BLOCKED_UNTIL = "misc.cds_blocked_until"; - private static final String LAST_FOREGROUND_TIME = "misc.last_foreground_time"; - private static final String PNI_INITIALIZED_DEVICES = "misc.pni_initialized_devices"; - private static final String LINKED_DEVICES_REMINDER = "misc.linked_devices_reminder"; - private static final String HAS_LINKED_DEVICES = "misc.linked_devices_present"; - private static final String USERNAME_QR_CODE_COLOR = "mis.username_qr_color_scheme"; - private static final String KEYBOARD_LANDSCAPE_HEIGHT = "misc.keyboard.landscape_height"; - private static final String KEYBOARD_PORTRAIT_HEIGHT = "misc.keyboard.protrait_height"; - private static final String LAST_CONSISTENCY_CHECK_TIME = "misc.last_consistency_check_time"; - private static final String SERVER_TIME_OFFSET = "misc.server_time_offset"; - private static final String LAST_SERVER_TIME_OFFSET_UPDATE = "misc.last_server_time_offset_update"; - private static final String NEEDS_USERNAME_RESTORE = "misc.needs_username_restore"; - private static final String LAST_FORCED_PREKEY_REFRESH = "misc.last_forced_prekey_refresh"; - private static final String LAST_CDS_FOREGROUND_SYNC = "misc.last_cds_foreground_sync"; - - MiscellaneousValues(@NonNull KeyValueStore store) { - super(store); - } - - @Override - void onFirstEverAppLaunch() { - putLong(MESSAGE_REQUEST_ENABLE_TIME, 0); - putBoolean(NEEDS_USERNAME_RESTORE, true); - } - - @Override - @NonNull List getKeysToIncludeInBackup() { - return Collections.emptyList(); - } - - /** - * Represents the last time a _full_ prekey refreshed finished. That means signed+one-time prekeys for both ACI and PNI. - */ - public long getLastFullPrekeyRefreshTime() { - return getLong(LAST_PREKEY_REFRESH_TIME, 0); - } - - public void setLastFullPrekeyRefreshTime(long time) { - putLong(LAST_PREKEY_REFRESH_TIME, time); - } - - public long getMessageRequestEnableTime() { - return getLong(MESSAGE_REQUEST_ENABLE_TIME, 0); - } - - public long getLastProfileRefreshTime() { - return getLong(LAST_PROFILE_REFRESH_TIME, 0); - } - - public void setLastProfileRefreshTime(long time) { - putLong(LAST_PROFILE_REFRESH_TIME, time); - } - - public void hideUsernameReminder() { - putBoolean(USERNAME_SHOW_REMINDER, false); - } - - public boolean shouldShowUsernameReminder() { - return getBoolean(USERNAME_SHOW_REMINDER, true); - } - - public boolean isClientDeprecated() { - return getBoolean(CLIENT_DEPRECATED, false); - } - - public void markClientDeprecated() { - putBoolean(CLIENT_DEPRECATED, true); - } - - public void clearClientDeprecated() { - putBoolean(CLIENT_DEPRECATED, false); - } - - public boolean isOldDeviceTransferLocked() { - return getBoolean(OLD_DEVICE_TRANSFER_LOCKED, false); - } - - public void markOldDeviceTransferLocked() { - putBoolean(OLD_DEVICE_TRANSFER_LOCKED, true); - } - - public void clearOldDeviceTransferLocked() { - putBoolean(OLD_DEVICE_TRANSFER_LOCKED, false); - } - - public boolean hasEverHadAnAvatar() { - return getBoolean(HAS_EVER_HAD_AN_AVATAR, false); - } - - public void markHasEverHadAnAvatar() { - putBoolean(HAS_EVER_HAD_AN_AVATAR, true); - } - - public boolean isChangeNumberLocked() { - return getBoolean(CHANGE_NUMBER_LOCK, false); - } - - public void lockChangeNumber() { - putBoolean(CHANGE_NUMBER_LOCK, true); - ChangeNumberConstraintObserver.INSTANCE.onChange(); - } - - public void unlockChangeNumber() { - putBoolean(CHANGE_NUMBER_LOCK, false); - ChangeNumberConstraintObserver.INSTANCE.onChange(); - } - - public @Nullable PendingChangeNumberMetadata getPendingChangeNumberMetadata() { - return getObject(PENDING_CHANGE_NUMBER_METADATA, null, PendingChangeNumberMetadataSerializer.INSTANCE); - } - - /** Store pending new PNI data to be applied after successful change number */ - public void setPendingChangeNumberMetadata(@NonNull PendingChangeNumberMetadata metadata) { - putObject(PENDING_CHANGE_NUMBER_METADATA, metadata, PendingChangeNumberMetadataSerializer.INSTANCE); - } - - /** Clear pending new PNI data after confirmed successful or failed change number */ - public void clearPendingChangeNumberMetadata() { - remove(PENDING_CHANGE_NUMBER_METADATA); - } - - public long getLastCensorshipServiceReachabilityCheckTime() { - return getLong(CENSORSHIP_LAST_CHECK_TIME, 0); - } - - public void setLastCensorshipServiceReachabilityCheckTime(long value) { - putLong(CENSORSHIP_LAST_CHECK_TIME, value); - } - - public boolean isServiceReachableWithoutCircumvention() { - return getBoolean(CENSORSHIP_SERVICE_REACHABLE, false); - } - - public void setServiceReachableWithoutCircumvention(boolean value) { - putBoolean(CENSORSHIP_SERVICE_REACHABLE, value); - } - - public long getLastGv2ProfileCheckTime() { - return getLong(LAST_GV2_PROFILE_CHECK_TIME, 0); - } - - public void setLastGv2ProfileCheckTime(long value) { - putLong(LAST_GV2_PROFILE_CHECK_TIME, value); - } - - public @Nullable byte[] getCdsToken() { - return getBlob(CDS_TOKEN, null); - } - - public void setCdsToken(@Nullable byte[] token) { - getStore().beginWrite() - .putBlob(CDS_TOKEN, token) - .commit(); - } - - /** - * Marks the time at which we think the next CDS request will succeed. This should be taken from the service response. - */ - public void setCdsBlockedUtil(long time) { - putLong(CDS_BLOCKED_UNTIL, time); - } - - /** - * Indicates that a CDS request will never succeed at the current contact count. - */ - public void markCdsPermanentlyBlocked() { - putLong(CDS_BLOCKED_UNTIL, Long.MAX_VALUE); - } - - /** - * Clears any rate limiting state related to CDS. - */ - public void clearCdsBlocked() { - setCdsBlockedUtil(0); - } - - /** - * Whether or not we expect the next CDS request to succeed. - */ - public boolean isCdsBlocked() { - return getCdsBlockedUtil() > 0; - } - - /** - * This represents the next time we think we'll be able to make a successful CDS request. If it is before this time, we expect the request will fail - * (assuming the user still has the same number of new E164s). - */ - public long getCdsBlockedUtil() { - return getLong(CDS_BLOCKED_UNTIL, 0); - } - - public long getLastForegroundTime() { - return getLong(LAST_FOREGROUND_TIME, 0); - } - - public void setLastForegroundTime(long time) { - putLong(LAST_FOREGROUND_TIME, time); - } - - public boolean hasPniInitializedDevices() { - return getBoolean(PNI_INITIALIZED_DEVICES, false); - } - - public void setPniInitializedDevices(boolean value) { - putBoolean(PNI_INITIALIZED_DEVICES, value); - } - - public void setHasLinkedDevices(boolean value) { - putBoolean(HAS_LINKED_DEVICES, value); - } - - public boolean getHasLinkedDevices() { - return getBoolean(HAS_LINKED_DEVICES, false); - } - - public void setShouldShowLinkedDevicesReminder(boolean value) { - putBoolean(LINKED_DEVICES_REMINDER, value); - } - - public boolean getShouldShowLinkedDevicesReminder() { - return getBoolean(LINKED_DEVICES_REMINDER, false); - } - - /** The color the user saved for rendering their shareable username QR code. */ - public @NonNull UsernameQrCodeColorScheme getUsernameQrCodeColorScheme() { - String serialized = getString(USERNAME_QR_CODE_COLOR, null); - return UsernameQrCodeColorScheme.deserialize(serialized); - } - - public void setUsernameQrCodeColorScheme(@NonNull UsernameQrCodeColorScheme color) { - putString(USERNAME_QR_CODE_COLOR, color.serialize()); - } - - public int getKeyboardLandscapeHeight() { - int height = (int) getLong(KEYBOARD_LANDSCAPE_HEIGHT, 0); - if (height == 0) { - //noinspection deprecation - height = PreferenceManager.getDefaultSharedPreferences(ApplicationDependencies.getApplication()) - .getInt("keyboard_height_landscape", 0); - - if (height > 0) { - setKeyboardLandscapeHeight(height); - } - } - return height; - } - - public void setKeyboardLandscapeHeight(int height) { - putLong(KEYBOARD_LANDSCAPE_HEIGHT, height); - } - - public int getKeyboardPortraitHeight() { - int height = (int) getInteger(KEYBOARD_PORTRAIT_HEIGHT, 0); - if (height == 0) { - //noinspection deprecation - height = PreferenceManager.getDefaultSharedPreferences(ApplicationDependencies.getApplication()) - .getInt("keyboard_height_portrait", 0); - - if (height > 0) { - setKeyboardPortraitHeight(height); - } - } - return height; - } - - public void setKeyboardPortraitHeight(int height) { - putInteger(KEYBOARD_PORTRAIT_HEIGHT, height); - } - - public long getLastConsistencyCheckTime() { - return getLong(LAST_CONSISTENCY_CHECK_TIME, 0); - } - - public void setLastConsistencyCheckTime(long time) { - putLong(LAST_CONSISTENCY_CHECK_TIME, time); - } - - /** - * Sets the last-known server time. - */ - public void setLastKnownServerTime(long serverTime, long currentTime) { - getStore() - .beginWrite() - .putLong(SERVER_TIME_OFFSET, currentTime - serverTime) - .putLong(LAST_SERVER_TIME_OFFSET_UPDATE, System.currentTimeMillis()) - .apply(); - } - - /** - * The last-known offset between our local clock and the server. To get an estimate of the server time, take your current time and subtract this offset. e.g. - * - * estimatedServerTime = System.currentTimeMillis() - SignalStore.misc().getLastKnownServerTimeOffset() - */ - public long getLastKnownServerTimeOffset() { - return getLong(SERVER_TIME_OFFSET, 0); - } - - /** - * The last time (using our local clock) we updated the server time offset returned by {@link #getLastKnownServerTimeOffset()}}. - */ - public long getLastKnownServerTimeOffsetUpdateTime() { - return getLong(LAST_SERVER_TIME_OFFSET_UPDATE, 0); - } - - /** - * Whether or not we should attempt to restore the user's username and link. - */ - public boolean needsUsernameRestore() { - return getBoolean(NEEDS_USERNAME_RESTORE, false); - } - - public void setNeedsUsernameRestore(boolean value) { - putBoolean(NEEDS_USERNAME_RESTORE, value); - } - - /** - * Set the last time we successfully completed a forced prekey refresh. - */ - public void setLastForcedPreKeyRefresh(long time) { - putLong(LAST_FORCED_PREKEY_REFRESH, time); - } - - /** - * Get the last time we successfully completed a forced prekey refresh. - */ - public long getLastForcedPreKeyRefresh() { - return getLong(LAST_FORCED_PREKEY_REFRESH, 0); - } - - /** - * How long it's been since the last foreground CDS sync, which we do in response to new threads being created. - */ - public long getLastCdsForegroundSyncTime() { - return getLong(LAST_CDS_FOREGROUND_SYNC, 0); - } - - /** - * Set the last time we did a foreground CDS sync. - */ - public void setLastCdsForegroundSyncTime(long time) { - putLong(LAST_CDS_FOREGROUND_SYNC, time); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.kt new file mode 100644 index 0000000000..e283326202 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/MiscellaneousValues.kt @@ -0,0 +1,226 @@ +package org.thoughtcrime.securesms.keyvalue + +import org.thoughtcrime.securesms.components.settings.app.usernamelinks.UsernameQrCodeColorScheme +import org.thoughtcrime.securesms.database.model.databaseprotos.PendingChangeNumberMetadata +import org.thoughtcrime.securesms.jobmanager.impl.ChangeNumberConstraintObserver + +internal class MiscellaneousValues internal constructor(store: KeyValueStore) : SignalStoreValues(store) { + companion object { + 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" + private const val CLIENT_DEPRECATED = "misc.client_deprecated" + private const val OLD_DEVICE_TRANSFER_LOCKED = "misc.old_device.transfer.locked" + private const val HAS_EVER_HAD_AN_AVATAR = "misc.has.ever.had.an.avatar" + private const val CHANGE_NUMBER_LOCK = "misc.change_number.lock" + private const val PENDING_CHANGE_NUMBER_METADATA = "misc.pending_change_number.metadata" + private const val CENSORSHIP_LAST_CHECK_TIME = "misc.censorship.last_check_time" + private const val CENSORSHIP_SERVICE_REACHABLE = "misc.censorship.service_reachable" + private const val LAST_GV2_PROFILE_CHECK_TIME = "misc.last_gv2_profile_check_time" + private const val CDS_TOKEN = "misc.cds_token" + private const val CDS_BLOCKED_UNTIL = "misc.cds_blocked_until" + private const val LAST_FOREGROUND_TIME = "misc.last_foreground_time" + private const val PNI_INITIALIZED_DEVICES = "misc.pni_initialized_devices" + private const val LINKED_DEVICES_REMINDER = "misc.linked_devices_reminder" + private const val HAS_LINKED_DEVICES = "misc.linked_devices_present" + private const val USERNAME_QR_CODE_COLOR = "mis.username_qr_color_scheme" + private const val KEYBOARD_LANDSCAPE_HEIGHT = "misc.keyboard.landscape_height" + private const val KEYBOARD_PORTRAIT_HEIGHT = "misc.keyboard.protrait_height" + private const val LAST_CONSISTENCY_CHECK_TIME = "misc.last_consistency_check_time" + private const val SERVER_TIME_OFFSET = "misc.server_time_offset" + private const val LAST_SERVER_TIME_OFFSET_UPDATE = "misc.last_server_time_offset_update" + private const val NEEDS_USERNAME_RESTORE = "misc.needs_username_restore" + private const val LAST_FORCED_PREKEY_REFRESH = "misc.last_forced_prekey_refresh" + private const val LAST_CDS_FOREGROUND_SYNC = "misc.last_cds_foreground_sync" + } + + public override fun onFirstEverAppLaunch() { + putLong(MESSAGE_REQUEST_ENABLE_TIME, 0) + putBoolean(NEEDS_USERNAME_RESTORE, true) + } + + public override fun getKeysToIncludeInBackup(): List { + return emptyList() + } + + /** + * Represents the last time a _full_ prekey refreshed finished. That means signed+one-time prekeys for both ACI and PNI. + */ + var lastFullPrekeyRefreshTime by longValue(LAST_PREKEY_REFRESH_TIME, 0) + + val messageRequestEnableTime by longValue(MESSAGE_REQUEST_ENABLE_TIME, 0) + + /** + * Get the last time we successfully completed a forced prekey refresh. + */ + var lastForcedPreKeyRefresh by longValue(LAST_FORCED_PREKEY_REFRESH, 0) + + /** + * The last time we completed a routine profile refresh. + */ + var lastProfileRefreshTime by longValue(LAST_PROFILE_REFRESH_TIME, 0) + + /** + * Whether or not the client is currently in a 'deprecated' state, disallowing network access. + */ + var isClientDeprecated: Boolean by booleanValue(CLIENT_DEPRECATED, false) + + /** + * Whether or not we've locked the device after they've transferred to a new one. + */ + var isOldDeviceTransferLocked by booleanValue(OLD_DEVICE_TRANSFER_LOCKED, false) + + /** + * Whether or not the user has ever had an avatar. + */ + var hasEverHadAnAvatar by booleanValue(HAS_EVER_HAD_AN_AVATAR, false) + + val isChangeNumberLocked: Boolean by booleanValue(CHANGE_NUMBER_LOCK, false) + + fun lockChangeNumber() { + putBoolean(CHANGE_NUMBER_LOCK, true) + ChangeNumberConstraintObserver.onChange() + } + + fun unlockChangeNumber() { + putBoolean(CHANGE_NUMBER_LOCK, false) + ChangeNumberConstraintObserver.onChange() + } + + val pendingChangeNumberMetadata: PendingChangeNumberMetadata? + get() = getObject(PENDING_CHANGE_NUMBER_METADATA, null, PendingChangeNumberMetadataSerializer) + + /** Store pending new PNI data to be applied after successful change number */ + fun setPendingChangeNumberMetadata(metadata: PendingChangeNumberMetadata) { + putObject(PENDING_CHANGE_NUMBER_METADATA, metadata, PendingChangeNumberMetadataSerializer) + } + + /** Clear pending new PNI data after confirmed successful or failed change number */ + fun clearPendingChangeNumberMetadata() { + remove(PENDING_CHANGE_NUMBER_METADATA) + } + + /** + * The last time we checked if the service was reachable without censorship circumvention. + */ + var lastCensorshipServiceReachabilityCheckTime by longValue(CENSORSHIP_LAST_CHECK_TIME, 0) + + /** + * Whether or not the service is reachable without censorship circumvention. + */ + var isServiceReachableWithoutCircumvention by booleanValue(CENSORSHIP_SERVICE_REACHABLE, false) + + /** + * The last time we did a routing check to see if our GV2 groups have the latest version of our profile key. + */ + var lastGv2ProfileCheckTime by longValue(LAST_GV2_PROFILE_CHECK_TIME, 0) + + /** + * The CDS token that is used for rate-limiting. + */ + var cdsToken by nullableBlobValue(CDS_TOKEN, null) + + /** + * Indicates that a CDS request will never succeed at the current contact count. + */ + fun markCdsPermanentlyBlocked() { + putLong(CDS_BLOCKED_UNTIL, Long.MAX_VALUE) + } + + /** + * Clears any rate limiting state related to CDS. + */ + fun clearCdsBlocked() { + cdsBlockedUtil = 0 + } + + /** Whether or not we expect the next CDS request to succeed.*/ + val isCdsBlocked: Boolean + get() = cdsBlockedUtil > 0 + + /** + * This represents the next time we think we'll be able to make a successful CDS request. If it is before this time, we expect the request will fail + * (assuming the user still has the same number of new E164s). + */ + var cdsBlockedUtil by longValue(CDS_BLOCKED_UNTIL, 0) + + /** + * The last time the user foregrounded the app. + */ + var lastForegroundTime by longValue(LAST_FOREGROUND_TIME, 0) + + /** + * Whether or not we've done the initial "PNP Hello World" dance. + */ + var hasPniInitializedDevices by booleanValue(PNI_INITIALIZED_DEVICES, false) + + /** + * Whether or not the user has linked devices. + */ + var hasLinkedDevices by booleanValue(HAS_LINKED_DEVICES, false) + + /** + * Whether or not we should show a reminder for the user to relink their devices after re-registering. + */ + var shouldShowLinkedDevicesReminder by booleanValue(LINKED_DEVICES_REMINDER, false) + + /** + * The color the user saved for rendering their shareable username QR code. + */ + var usernameQrCodeColorScheme: UsernameQrCodeColorScheme + get() { + val serialized = getString(USERNAME_QR_CODE_COLOR, null) + return UsernameQrCodeColorScheme.deserialize(serialized) + } + set(color) { + putString(USERNAME_QR_CODE_COLOR, color.serialize()) + } + + /** + * Cached landscape keyboard height. + */ + var keyboardLandscapeHeight by integerValue(KEYBOARD_LANDSCAPE_HEIGHT, 0) + + /** + * Cached portrait keyboard height. + */ + var keyboardPortraitHeight by integerValue(KEYBOARD_PORTRAIT_HEIGHT, 0) + + /** + * The last time we ran an account consistency check via [org.thoughtcrime.securesms.jobs.AccountConsistencyWorkerJob] + */ + var lastConsistencyCheckTime by longValue(LAST_CONSISTENCY_CHECK_TIME, 0) + + /** + * The last-known offset between our local clock and the server. To get an estimate of the server time, take your current time and subtract this offset. e.g. + * + * estimatedServerTime = System.currentTimeMillis() - SignalStore.misc().getLastKnownServerTimeOffset() + */ + val lastKnownServerTimeOffset by longValue(SERVER_TIME_OFFSET, 0) + + /** + * The last time (using our local clock) we updated the server time offset returned by [.getLastKnownServerTimeOffset]}. + */ + val lastKnownServerTimeOffsetUpdateTime by longValue(LAST_SERVER_TIME_OFFSET_UPDATE, 0) + + /** + * Sets the last-known server time. + */ + fun setLastKnownServerTime(serverTime: Long, currentTime: Long) { + store + .beginWrite() + .putLong(SERVER_TIME_OFFSET, currentTime - serverTime) + .putLong(LAST_SERVER_TIME_OFFSET_UPDATE, System.currentTimeMillis()) + .apply() + } + + /** + * Whether or not we should attempt to restore the user's username and link. + */ + var needsUsernameRestore by booleanValue(NEEDS_USERNAME_RESTORE, false) + + /** + * How long it's been since the last foreground CDS sync, which we do in response to new threads being created. + */ + var lastCdsForegroundSyncTime by longValue(LAST_CDS_FOREGROUND_SYNC, 0) +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/SignalStoreValueDelegates.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/SignalStoreValueDelegates.kt index 99d586a802..cf4c68af57 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/SignalStoreValueDelegates.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/SignalStoreValueDelegates.kt @@ -28,6 +28,10 @@ internal fun SignalStoreValues.blobValue(key: String, default: ByteArray): Signa return BlobValue(key, default, this.store) } +internal fun SignalStoreValues.nullableBlobValue(key: String, default: ByteArray?): SignalStoreValueDelegate { + return NullableBlobValue(key, default, this.store) +} + internal fun SignalStoreValues.enumValue(key: String, default: T, serializer: LongSerializer): SignalStoreValueDelegate { return KeyValueEnumValue(key, default, serializer, this.store) } @@ -114,6 +118,16 @@ private class BlobValue(private val key: String, private val default: ByteArray, } } +private class NullableBlobValue(private val key: String, private val default: ByteArray?, store: KeyValueStore) : SignalStoreValueDelegate(store) { + override fun getValue(values: KeyValueStore): ByteArray? { + return values.getBlob(key, default) + } + + override fun setValue(values: KeyValueStore, value: ByteArray?) { + values.beginWrite().putBlob(key, value).apply() + } +} + private class KeyValueProtoValue( private val key: String, private val adapter: ProtoAdapter, diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java index 85fe1c19fe..e96574bf98 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java @@ -405,13 +405,13 @@ public final class Megaphones { } private static boolean shouldShowAddAProfilePhotoMegaphone(@NonNull Context context) { - if (SignalStore.misc().hasEverHadAnAvatar()) { + if (SignalStore.misc().getHasEverHadAnAvatar()) { return false; } boolean hasAnAvatar = AvatarHelper.hasAvatar(context, Recipient.self().getId()); if (hasAnAvatar) { - SignalStore.misc().markHasEverHadAnAvatar(); + SignalStore.misc().setHasEverHadAnAvatar(true); return false; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/OnboardingMegaphoneView.java b/app/src/main/java/org/thoughtcrime/securesms/megaphone/OnboardingMegaphoneView.java index 511b5a1756..1621f79432 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/OnboardingMegaphoneView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/OnboardingMegaphoneView.java @@ -135,7 +135,7 @@ public class OnboardingMegaphoneView extends FrameLayout { data.add(TYPE_INVITE); } - if (SignalStore.onboarding().shouldShowAddPhoto() && !SignalStore.misc().hasEverHadAnAvatar()) { + if (SignalStore.onboarding().shouldShowAddPhoto() && !SignalStore.misc().getHasEverHadAnAvatar()) { data.add(TYPE_ADD_PHOTO); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java index 3b2c0d3200..8271eff2ec 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java @@ -167,7 +167,7 @@ public class ApplicationMigrations { return; } else { Log.d(TAG, "About to update. Clearing deprecation flag."); - SignalStore.misc().clearClientDeprecated(); + SignalStore.misc().setClientDeprecated(false); } final int lastSeenVersion = TextSecurePreferences.getAppMigrationVersion(context); diff --git a/app/src/main/java/org/thoughtcrime/securesms/net/RemoteDeprecationDetectorInterceptor.java b/app/src/main/java/org/thoughtcrime/securesms/net/RemoteDeprecationDetectorInterceptor.java index e88570fef9..cc4b006efe 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/net/RemoteDeprecationDetectorInterceptor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/net/RemoteDeprecationDetectorInterceptor.java @@ -23,7 +23,7 @@ public final class RemoteDeprecationDetectorInterceptor implements Interceptor { if (response.code() == 499 && !SignalStore.misc().isClientDeprecated()) { Log.w(TAG, "Received 499. Client version is deprecated."); - SignalStore.misc().markClientDeprecated(); + SignalStore.misc().setClientDeprecated(true); } return response; diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/edit/EditSelfProfileRepository.java b/app/src/main/java/org/thoughtcrime/securesms/profiles/edit/EditSelfProfileRepository.java index 6a135fa45b..5716ab7c4a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/edit/EditSelfProfileRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/edit/EditSelfProfileRepository.java @@ -148,7 +148,7 @@ public class EditSelfProfileRepository implements EditProfileRepository { RegistrationUtil.maybeMarkRegistrationComplete(); if (avatar != null) { - SignalStore.misc().markHasEverHadAnAvatar(); + SignalStore.misc().setHasEverHadAnAvatar(true); } return UploadResult.SUCCESS; diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/EditProfileRepository.java b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/EditProfileRepository.java index e004166b35..da0a95a6de 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/EditProfileRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/EditProfileRepository.java @@ -59,7 +59,7 @@ final class EditProfileRepository { try { ProfileUtil.uploadProfileWithAvatar(new StreamDetails(new ByteArrayInputStream(data), contentType, data.length)); AvatarHelper.setAvatar(context, Recipient.self().getId(), new ByteArrayInputStream(data)); - SignalStore.misc().markHasEverHadAnAvatar(); + SignalStore.misc().setHasEverHadAnAvatar(true); ApplicationDependencies.getJobManager().add(new MultiDeviceProfileContentUpdateJob()); callback.accept(Result.SUCCESS); diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt index 660e2221b4..b12d7fc22d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt @@ -130,7 +130,7 @@ object UsernameRepository { @WorkerThread @JvmStatic fun reclaimUsernameIfNecessary(): UsernameReclaimResult { - if (!SignalStore.misc().needsUsernameRestore()) { + if (!SignalStore.misc().needsUsernameRestore) { Log.d(TAG, "[reclaimUsernameIfNecessary] No need to restore username. Skipping.") return UsernameReclaimResult.SUCCESS } @@ -140,7 +140,7 @@ object UsernameRepository { if (username == null || link == null) { Log.d(TAG, "[reclaimUsernameIfNecessary] No username or link to restore. Skipping.") - SignalStore.misc().setNeedsUsernameRestore(false) + SignalStore.misc().needsUsernameRestore = false return UsernameReclaimResult.SUCCESS } @@ -149,13 +149,13 @@ object UsernameRepository { when (result) { UsernameReclaimResult.SUCCESS -> { Log.i(TAG, "[reclaimUsernameIfNecessary] Successfully reclaimed username and link.") - SignalStore.misc().setNeedsUsernameRestore(false) + SignalStore.misc().needsUsernameRestore = false } UsernameReclaimResult.PERMANENT_ERROR -> { Log.w(TAG, "[reclaimUsernameIfNecessary] Permanently failed to reclaim username and link. User will see an error.") SignalStore.account().usernameSyncState = AccountValues.UsernameSyncState.USERNAME_AND_LINK_CORRUPTED - SignalStore.misc().setNeedsUsernameRestore(false) + SignalStore.misc().needsUsernameRestore = false } UsernameReclaimResult.NETWORK_ERROR -> { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionTracker.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionTracker.kt index 68c76f8112..c44fde5a4f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionTracker.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionTracker.kt @@ -25,7 +25,7 @@ object VersionTracker { if (currentVersionCode != lastVersionCode) { Log.i(TAG, "Upgraded from $lastVersionCode to $currentVersionCode") - SignalStore.misc().clearClientDeprecated() + SignalStore.misc().isClientDeprecated = false val jobChain = listOf(RemoteConfigRefreshJob(), RefreshAttributesJob()) ApplicationDependencies.getJobManager().startChain(jobChain).enqueue() RetrieveRemoteAnnouncementsJob.enqueue(true)