Convert MiscellaneousValues to kotlin.

This commit is contained in:
Greyson Parrelli
2024-03-18 11:18:22 -04:00
committed by Cody Henthorne
parent e6a11c1ccf
commit e24c951d83
18 changed files with 264 additions and 397 deletions

View File

@@ -273,7 +273,7 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr
public void checkBuildExpiration() { public void checkBuildExpiration() {
if (Util.getTimeUntilBuildExpiry() <= 0 && !SignalStore.misc().isClientDeprecated()) { if (Util.getTimeUntilBuildExpiry() <= 0 && !SignalStore.misc().isClientDeprecated()) {
Log.w(TAG, "Build expired!"); Log.w(TAG, "Build expired!");
SignalStore.misc().markClientDeprecated(); SignalStore.misc().setClientDeprecated(true);
} }
} }

View File

@@ -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) .setMessage(R.string.OldDeviceTransferLockedDialog__your_signal_account_has_been_transferred_to_your_new_device)
.setPositiveButton(R.string.OldDeviceTransferLockedDialog__done, (d, w) -> OldDeviceExitActivity.exit(this)) .setPositiveButton(R.string.OldDeviceTransferLockedDialog__done, (d, w) -> OldDeviceExitActivity.exit(this))
.setNegativeButton(R.string.OldDeviceTransferLockedDialog__cancel_and_activate_this_device, (d, w) -> { .setNegativeButton(R.string.OldDeviceTransferLockedDialog__cancel_and_activate_this_device, (d, w) -> {
SignalStore.misc().clearOldDeviceTransferLocked(); SignalStore.misc().setOldDeviceTransferLocked(false);
DeviceTransferBlockingInterceptor.getInstance().unblockNetwork(); DeviceTransferBlockingInterceptor.getInstance().unblockNetwork();
}) })
.setCancelable(false) .setCancelable(false)

View File

@@ -291,7 +291,7 @@ class ChangeNumberRepository(
true true
) )
SignalStore.misc().setPniInitializedDevices(true) SignalStore.misc().hasPniInitializedDevices = true
ApplicationDependencies.getGroupsV2Authorization().clear() ApplicationDependencies.getGroupsV2Authorization().clear()
} }

View File

@@ -75,7 +75,7 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
} }
fun resetPnpInitializedState() { fun resetPnpInitializedState() {
SignalStore.misc().setPniInitializedDevices(false) SignalStore.misc().hasPniInitializedDevices = false
refresh() refresh()
} }
@@ -159,7 +159,7 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
delayResends = SignalStore.internalValues().delayResends(), delayResends = SignalStore.internalValues().delayResends(),
disableStorageService = SignalStore.internalValues().storageServiceDisabled(), disableStorageService = SignalStore.internalValues().storageServiceDisabled(),
canClearOnboardingState = SignalStore.storyValues().hasDownloadedOnboardingStory && Stories.isFeatureEnabled(), canClearOnboardingState = SignalStore.storyValues().hasDownloadedOnboardingStory && Stories.isFeatureEnabled(),
pnpInitialized = SignalStore.misc().hasPniInitializedDevices(), pnpInitialized = SignalStore.misc().hasPniInitializedDevices,
useConversationItemV2ForMedia = SignalStore.internalValues().useConversationItemV2Media(), useConversationItemV2ForMedia = SignalStore.internalValues().useConversationItemV2Media(),
hasPendingOneTimeDonation = SignalStore.donationsValues().getPendingOneTimeDonation() != null hasPendingOneTimeDonation = SignalStore.donationsValues().getPendingOneTimeDonation() != null
) )

View File

@@ -67,7 +67,7 @@ final class OldDeviceClientTask implements ClientTask {
@Override @Override
public void success() { public void success() {
SignalStore.misc().markOldDeviceTransferLocked(); SignalStore.misc().setOldDeviceTransferLocked(true);
EventBus.getDefault().post(new Status(0, 0, 0,true)); EventBus.getDefault().post(new Status(0, 0, 0,true));
} }

View File

@@ -48,7 +48,7 @@ class PnpInitializeDevicesJob private constructor(parameters: Parameters) : Base
@JvmStatic @JvmStatic
fun enqueueIfNecessary() { 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 return
} }
@@ -77,19 +77,19 @@ class PnpInitializeDevicesJob private constructor(parameters: Parameters) : Base
if (!TextSecurePreferences.isMultiDevice(context)) { if (!TextSecurePreferences.isMultiDevice(context)) {
Log.i(TAG, "Not multi device, aborting...") Log.i(TAG, "Not multi device, aborting...")
SignalStore.misc().setPniInitializedDevices(true) SignalStore.misc().hasPniInitializedDevices = true
return return
} }
if (SignalStore.account().isLinkedDevice) { if (SignalStore.account().isLinkedDevice) {
Log.i(TAG, "Not primary device, aborting...") Log.i(TAG, "Not primary device, aborting...")
SignalStore.misc().setPniInitializedDevices(true) SignalStore.misc().hasPniInitializedDevices = true
return return
} }
ChangeNumberRepository.CHANGE_NUMBER_LOCK.lock() ChangeNumberRepository.CHANGE_NUMBER_LOCK.lock()
try { 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.") Log.w(TAG, "We found out that things have been initialized after we got the lock! No need to do anything else.")
return return
} }
@@ -110,7 +110,7 @@ class PnpInitializeDevicesJob private constructor(parameters: Parameters) : Base
throw t throw t
} }
SignalStore.misc().setPniInitializedDevices(true) SignalStore.misc().hasPniInitializedDevices = true
} finally { } finally {
ChangeNumberRepository.CHANGE_NUMBER_LOCK.unlock() ChangeNumberRepository.CHANGE_NUMBER_LOCK.unlock()
} }

View File

@@ -127,7 +127,7 @@ public class RetrieveProfileAvatarJob extends BaseJob {
AvatarHelper.setAvatar(context, recipient.getId(), avatarStream); AvatarHelper.setAvatar(context, recipient.getId(), avatarStream);
if (recipient.isSelf()) { if (recipient.isSelf()) {
SignalStore.misc().markHasEverHadAnAvatar(); SignalStore.misc().setHasEverHadAnAvatar(true);
} }
} catch (AssertionError e) { } catch (AssertionError e) {
throw new IOException("Failed to copy stream. Likely a Conscrypt issue.", e); throw new IOException("Failed to copy stream. Likely a Conscrypt issue.", e);

View File

@@ -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<String> 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);
}
}

View File

@@ -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<String> {
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)
}

View File

@@ -28,6 +28,10 @@ internal fun SignalStoreValues.blobValue(key: String, default: ByteArray): Signa
return BlobValue(key, default, this.store) return BlobValue(key, default, this.store)
} }
internal fun SignalStoreValues.nullableBlobValue(key: String, default: ByteArray?): SignalStoreValueDelegate<ByteArray?> {
return NullableBlobValue(key, default, this.store)
}
internal fun <T : Any?> SignalStoreValues.enumValue(key: String, default: T, serializer: LongSerializer<T>): SignalStoreValueDelegate<T> { internal fun <T : Any?> SignalStoreValues.enumValue(key: String, default: T, serializer: LongSerializer<T>): SignalStoreValueDelegate<T> {
return KeyValueEnumValue(key, default, serializer, this.store) 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<ByteArray?>(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<M>( private class KeyValueProtoValue<M>(
private val key: String, private val key: String,
private val adapter: ProtoAdapter<M>, private val adapter: ProtoAdapter<M>,

View File

@@ -405,13 +405,13 @@ public final class Megaphones {
} }
private static boolean shouldShowAddAProfilePhotoMegaphone(@NonNull Context context) { private static boolean shouldShowAddAProfilePhotoMegaphone(@NonNull Context context) {
if (SignalStore.misc().hasEverHadAnAvatar()) { if (SignalStore.misc().getHasEverHadAnAvatar()) {
return false; return false;
} }
boolean hasAnAvatar = AvatarHelper.hasAvatar(context, Recipient.self().getId()); boolean hasAnAvatar = AvatarHelper.hasAvatar(context, Recipient.self().getId());
if (hasAnAvatar) { if (hasAnAvatar) {
SignalStore.misc().markHasEverHadAnAvatar(); SignalStore.misc().setHasEverHadAnAvatar(true);
return false; return false;
} }

View File

@@ -135,7 +135,7 @@ public class OnboardingMegaphoneView extends FrameLayout {
data.add(TYPE_INVITE); data.add(TYPE_INVITE);
} }
if (SignalStore.onboarding().shouldShowAddPhoto() && !SignalStore.misc().hasEverHadAnAvatar()) { if (SignalStore.onboarding().shouldShowAddPhoto() && !SignalStore.misc().getHasEverHadAnAvatar()) {
data.add(TYPE_ADD_PHOTO); data.add(TYPE_ADD_PHOTO);
} }

View File

@@ -167,7 +167,7 @@ public class ApplicationMigrations {
return; return;
} else { } else {
Log.d(TAG, "About to update. Clearing deprecation flag."); Log.d(TAG, "About to update. Clearing deprecation flag.");
SignalStore.misc().clearClientDeprecated(); SignalStore.misc().setClientDeprecated(false);
} }
final int lastSeenVersion = TextSecurePreferences.getAppMigrationVersion(context); final int lastSeenVersion = TextSecurePreferences.getAppMigrationVersion(context);

View File

@@ -23,7 +23,7 @@ public final class RemoteDeprecationDetectorInterceptor implements Interceptor {
if (response.code() == 499 && !SignalStore.misc().isClientDeprecated()) { if (response.code() == 499 && !SignalStore.misc().isClientDeprecated()) {
Log.w(TAG, "Received 499. Client version is deprecated."); Log.w(TAG, "Received 499. Client version is deprecated.");
SignalStore.misc().markClientDeprecated(); SignalStore.misc().setClientDeprecated(true);
} }
return response; return response;

View File

@@ -148,7 +148,7 @@ public class EditSelfProfileRepository implements EditProfileRepository {
RegistrationUtil.maybeMarkRegistrationComplete(); RegistrationUtil.maybeMarkRegistrationComplete();
if (avatar != null) { if (avatar != null) {
SignalStore.misc().markHasEverHadAnAvatar(); SignalStore.misc().setHasEverHadAnAvatar(true);
} }
return UploadResult.SUCCESS; return UploadResult.SUCCESS;

View File

@@ -59,7 +59,7 @@ final class EditProfileRepository {
try { try {
ProfileUtil.uploadProfileWithAvatar(new StreamDetails(new ByteArrayInputStream(data), contentType, data.length)); ProfileUtil.uploadProfileWithAvatar(new StreamDetails(new ByteArrayInputStream(data), contentType, data.length));
AvatarHelper.setAvatar(context, Recipient.self().getId(), new ByteArrayInputStream(data)); AvatarHelper.setAvatar(context, Recipient.self().getId(), new ByteArrayInputStream(data));
SignalStore.misc().markHasEverHadAnAvatar(); SignalStore.misc().setHasEverHadAnAvatar(true);
ApplicationDependencies.getJobManager().add(new MultiDeviceProfileContentUpdateJob()); ApplicationDependencies.getJobManager().add(new MultiDeviceProfileContentUpdateJob());
callback.accept(Result.SUCCESS); callback.accept(Result.SUCCESS);

View File

@@ -130,7 +130,7 @@ object UsernameRepository {
@WorkerThread @WorkerThread
@JvmStatic @JvmStatic
fun reclaimUsernameIfNecessary(): UsernameReclaimResult { fun reclaimUsernameIfNecessary(): UsernameReclaimResult {
if (!SignalStore.misc().needsUsernameRestore()) { if (!SignalStore.misc().needsUsernameRestore) {
Log.d(TAG, "[reclaimUsernameIfNecessary] No need to restore username. Skipping.") Log.d(TAG, "[reclaimUsernameIfNecessary] No need to restore username. Skipping.")
return UsernameReclaimResult.SUCCESS return UsernameReclaimResult.SUCCESS
} }
@@ -140,7 +140,7 @@ object UsernameRepository {
if (username == null || link == null) { if (username == null || link == null) {
Log.d(TAG, "[reclaimUsernameIfNecessary] No username or link to restore. Skipping.") Log.d(TAG, "[reclaimUsernameIfNecessary] No username or link to restore. Skipping.")
SignalStore.misc().setNeedsUsernameRestore(false) SignalStore.misc().needsUsernameRestore = false
return UsernameReclaimResult.SUCCESS return UsernameReclaimResult.SUCCESS
} }
@@ -149,13 +149,13 @@ object UsernameRepository {
when (result) { when (result) {
UsernameReclaimResult.SUCCESS -> { UsernameReclaimResult.SUCCESS -> {
Log.i(TAG, "[reclaimUsernameIfNecessary] Successfully reclaimed username and link.") Log.i(TAG, "[reclaimUsernameIfNecessary] Successfully reclaimed username and link.")
SignalStore.misc().setNeedsUsernameRestore(false) SignalStore.misc().needsUsernameRestore = false
} }
UsernameReclaimResult.PERMANENT_ERROR -> { UsernameReclaimResult.PERMANENT_ERROR -> {
Log.w(TAG, "[reclaimUsernameIfNecessary] Permanently failed to reclaim username and link. User will see an 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.account().usernameSyncState = AccountValues.UsernameSyncState.USERNAME_AND_LINK_CORRUPTED
SignalStore.misc().setNeedsUsernameRestore(false) SignalStore.misc().needsUsernameRestore = false
} }
UsernameReclaimResult.NETWORK_ERROR -> { UsernameReclaimResult.NETWORK_ERROR -> {

View File

@@ -25,7 +25,7 @@ object VersionTracker {
if (currentVersionCode != lastVersionCode) { if (currentVersionCode != lastVersionCode) {
Log.i(TAG, "Upgraded from $lastVersionCode to $currentVersionCode") Log.i(TAG, "Upgraded from $lastVersionCode to $currentVersionCode")
SignalStore.misc().clearClientDeprecated() SignalStore.misc().isClientDeprecated = false
val jobChain = listOf(RemoteConfigRefreshJob(), RefreshAttributesJob()) val jobChain = listOf(RemoteConfigRefreshJob(), RefreshAttributesJob())
ApplicationDependencies.getJobManager().startChain(jobChain).enqueue() ApplicationDependencies.getJobManager().startChain(jobChain).enqueue()
RetrieveRemoteAnnouncementsJob.enqueue(true) RetrieveRemoteAnnouncementsJob.enqueue(true)