kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add storage sync support for linked devices.
rodzic
4f03c98f60
commit
22c396067d
|
@ -103,13 +103,13 @@ class ExpireTimerSettingsFragment : DSLSettingsFragment(
|
|||
val values: Array<Int> = resources.getIntArray(R.array.ExpireTimerSettingsFragment__values).toTypedArray()
|
||||
|
||||
var hasCustomValue = true
|
||||
labels.zip(values).forEach { (label, value) ->
|
||||
labels.zip(values).forEach { (label, seconds) ->
|
||||
radioPref(
|
||||
title = DSLSettingsText.from(label),
|
||||
isChecked = state.currentTimer == value,
|
||||
onClick = { viewModel.select(value) }
|
||||
isChecked = state.currentTimer == seconds,
|
||||
onClick = { viewModel.select(seconds) }
|
||||
)
|
||||
hasCustomValue = hasCustomValue && state.currentTimer != value
|
||||
hasCustomValue = hasCustomValue && state.currentTimer != seconds
|
||||
}
|
||||
|
||||
radioPref(
|
||||
|
|
|
@ -8,10 +8,12 @@ import org.thoughtcrime.securesms.database.SignalDatabase
|
|||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import java.io.IOException
|
||||
|
||||
private val TAG: String = Log.tag(ExpireTimerSettingsRepository::class.java)
|
||||
|
@ -44,6 +46,15 @@ class ExpireTimerSettingsRepository(val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun setUniversalExpireTimerSeconds(newExpirationTime: Int, onDone: () -> Unit) {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
SignalStore.settings().universalExpireTimer = newExpirationTime
|
||||
SignalDatabase.recipients.markNeedsSync(Recipient.self().id)
|
||||
StorageSyncHelper.scheduleSyncForDataChange()
|
||||
onDone.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getThreadId(recipientId: RecipientId): Long {
|
||||
val threadDatabase: ThreadDatabase = SignalDatabase.threads
|
||||
|
|
|
@ -45,8 +45,9 @@ class ExpireTimerSettingsViewModel(val config: Config, private val repository: E
|
|||
} else if (config.forResultMode) {
|
||||
store.update { it.copy(saveState = ProcessState.Success(userSetTimer)) }
|
||||
} else {
|
||||
SignalStore.settings().universalExpireTimer = userSetTimer
|
||||
store.update { it.copy(saveState = ProcessState.Success(userSetTimer)) }
|
||||
repository.setUniversalExpireTimerSeconds(userSetTimer) {
|
||||
store.update { it.copy(saveState = ProcessState.Success(userSetTimer)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
|||
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
|||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.net.NotPushRegisteredException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
@ -94,6 +95,11 @@ public class MultiDeviceConfigurationUpdateJob extends BaseJob {
|
|||
return;
|
||||
}
|
||||
|
||||
if (SignalStore.account().isLinkedDevice()) {
|
||||
Log.i(TAG, "Not primary device, aborting...");
|
||||
return;
|
||||
}
|
||||
|
||||
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
|
||||
messageSender.sendSyncMessage(SignalServiceSyncMessage.forConfiguration(new ConfigurationMessage(Optional.of(readReceiptsEnabled),
|
||||
Optional.of(unidentifiedDeliveryIndicatorsEnabled),
|
||||
|
|
|
@ -50,7 +50,7 @@ class MultiDeviceContactSyncJob(parameters: Parameters, private val attachmentPo
|
|||
}
|
||||
|
||||
if (SignalStore.account().isPrimaryDevice) {
|
||||
Log.i(TAG, "Sync jobs are for linked devices only")
|
||||
Log.i(TAG, "Not linked device, aborting...")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -126,6 +126,11 @@ public class MultiDeviceContactUpdateJob extends BaseJob {
|
|||
return;
|
||||
}
|
||||
|
||||
if (SignalStore.account().isLinkedDevice()) {
|
||||
Log.i(TAG, "Not primary device, aborting...");
|
||||
return;
|
||||
}
|
||||
|
||||
if (recipientId == null) generateFullContactUpdate();
|
||||
else generateSingleContactUpdate(recipientId);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
|||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.net.NotPushRegisteredException;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
|
@ -82,6 +83,11 @@ public class MultiDeviceGroupUpdateJob extends BaseJob {
|
|||
return;
|
||||
}
|
||||
|
||||
if (SignalStore.account().isLinkedDevice()) {
|
||||
Log.i(TAG, "Not primary device, aborting...");
|
||||
return;
|
||||
}
|
||||
|
||||
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
|
||||
InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pipe[0]);
|
||||
Uri uri = BlobProvider.getInstance()
|
||||
|
|
|
@ -65,6 +65,11 @@ public class MultiDeviceKeysUpdateJob extends BaseJob {
|
|||
return;
|
||||
}
|
||||
|
||||
if (SignalStore.account().isLinkedDevice()) {
|
||||
Log.i(TAG, "Not primary device, aborting...");
|
||||
return;
|
||||
}
|
||||
|
||||
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
|
||||
StorageKey storageServiceKey = SignalStore.storageService().getOrCreateStorageKey();
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ public class RefreshOwnProfileJob extends BaseJob {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!SignalStore.registrationValues().hasUploadedProfile()) {
|
||||
if (!SignalStore.registrationValues().hasUploadedProfile() && SignalStore.account().isPrimaryDevice()) {
|
||||
Log.i(TAG, "Registered but haven't uploaded profile yet.");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,11 @@ public class StorageForcePushJob extends BaseJob {
|
|||
|
||||
@Override
|
||||
protected void onRun() throws IOException, RetryLaterException {
|
||||
if (SignalStore.account().isLinkedDevice()) {
|
||||
Log.i(TAG, "Only the primary device can force push");
|
||||
return;
|
||||
}
|
||||
|
||||
StorageKey storageServiceKey = SignalStore.storageService().getOrCreateStorageKey();
|
||||
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
||||
RecipientDatabase recipientDatabase = SignalDatabase.recipients();
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.annimon.stream.Stream;
|
|||
import net.zetetic.database.sqlcipher.SQLiteDatabase;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.RecipientRecord;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
|
@ -37,6 +38,9 @@ import org.thoughtcrime.securesms.util.Util;
|
|||
import org.whispersystems.libsignal.InvalidKeyException;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||
|
@ -47,6 +51,7 @@ import org.whispersystems.signalservice.api.storage.SignalStorageManifest;
|
|||
import org.whispersystems.signalservice.api.storage.SignalStorageRecord;
|
||||
import org.whispersystems.signalservice.api.storage.StorageId;
|
||||
import org.whispersystems.signalservice.api.storage.StorageKey;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
||||
import org.whispersystems.signalservice.internal.storage.protos.ManifestRecord;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -160,7 +165,7 @@ public class StorageSyncJob extends BaseJob {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onRun() throws IOException, RetryLaterException {
|
||||
protected void onRun() throws IOException, RetryLaterException, UntrustedIdentityException {
|
||||
if (!SignalStore.kbsValues().hasPin() && !SignalStore.kbsValues().hasOptedOut()) {
|
||||
Log.i(TAG, "Doesn't have a PIN. Skipping.");
|
||||
return;
|
||||
|
@ -185,12 +190,18 @@ public class StorageSyncJob extends BaseJob {
|
|||
|
||||
SignalStore.storageService().onSyncCompleted();
|
||||
} catch (InvalidKeyException e) {
|
||||
Log.w(TAG, "Failed to decrypt remote storage! Force-pushing and syncing the storage key to linked devices.", e);
|
||||
if (SignalStore.account().isPrimaryDevice()) {
|
||||
Log.w(TAG, "Failed to decrypt remote storage! Force-pushing and syncing the storage key to linked devices.", e);
|
||||
|
||||
ApplicationDependencies.getJobManager().startChain(new MultiDeviceKeysUpdateJob())
|
||||
.then(new StorageForcePushJob())
|
||||
.then(new MultiDeviceStorageSyncRequestJob())
|
||||
.enqueue();
|
||||
ApplicationDependencies.getJobManager().startChain(new MultiDeviceKeysUpdateJob())
|
||||
.then(new StorageForcePushJob())
|
||||
.then(new MultiDeviceStorageSyncRequestJob())
|
||||
.enqueue();
|
||||
} else {
|
||||
Log.w(TAG, "Failed to decrypt remote storage! Requesting new keys from primary.", e);
|
||||
SignalStore.storageService().clearStorageKeyFromPrimary();
|
||||
ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(SignalServiceSyncMessage.forRequest(RequestMessage.forType(SignalServiceProtos.SyncMessage.Request.Type.KEYS)), UnidentifiedAccessUtil.getAccessForSync(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,7 +244,7 @@ public class StorageSyncJob extends BaseJob {
|
|||
List<StorageId> localStorageIdsBeforeMerge = getAllLocalStorageIds(context, self);
|
||||
IdDifferenceResult idDifference = StorageSyncHelper.findIdDifference(remoteManifest.getStorageIds(), localStorageIdsBeforeMerge);
|
||||
|
||||
if (idDifference.hasTypeMismatches()) {
|
||||
if (idDifference.hasTypeMismatches() && SignalStore.account().isPrimaryDevice()) {
|
||||
Log.w(TAG, "[Remote Sync] Found type mismatches in the ID sets! Scheduling a force push after this sync completes.");
|
||||
needsForcePush = true;
|
||||
}
|
||||
|
@ -361,7 +372,7 @@ public class StorageSyncJob extends BaseJob {
|
|||
Log.i(TAG, "No remote writes needed. Still at version: " + remoteManifest.getVersion());
|
||||
}
|
||||
|
||||
if (needsForcePush) {
|
||||
if (needsForcePush && SignalStore.account().isPrimaryDevice()) {
|
||||
Log.w(TAG, "Scheduling a force push.");
|
||||
ApplicationDependencies.getJobManager().add(new StorageForcePushJob());
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
|
|||
import androidx.lifecycle.LiveData;
|
||||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.mms.SentMediaQuality;
|
||||
|
@ -18,7 +19,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
|||
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
|
||||
import org.thoughtcrime.securesms.util.SingleLiveEvent;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.webrtc.CallBandwidthMode;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -377,10 +377,6 @@ public final class SettingsValues extends SignalStoreValues {
|
|||
|
||||
public void setUniversalExpireTimer(int seconds) {
|
||||
putInteger(UNIVERSAL_EXPIRE_TIMER, seconds);
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
SignalDatabase.recipients().markNeedsSync(Recipient.self().getId());
|
||||
StorageSyncHelper.scheduleSyncForDataChange();
|
||||
});
|
||||
}
|
||||
|
||||
public int getUniversalExpireTimer() {
|
||||
|
|
|
@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.subscription.Subscriber;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
@ -105,8 +106,8 @@ public class AccountRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
|||
AccountRecord.PhoneNumberSharingMode phoneNumberSharingMode = remote.getPhoneNumberSharingMode();
|
||||
boolean preferContactAvatars = remote.isPreferContactAvatars();
|
||||
int universalExpireTimer = remote.getUniversalExpireTimer();
|
||||
boolean primarySendsSms = local.isPrimarySendsSms();
|
||||
String e164 = local.getE164();
|
||||
boolean primarySendsSms = SignalStore.account().isPrimaryDevice() ? local.isPrimarySendsSms() : remote.isPrimarySendsSms();
|
||||
String e164 = SignalStore.account().isPrimaryDevice() ? local.getE164() : remote.getE164();
|
||||
List<String> defaultReactions = remote.getDefaultReactions().size() > 0 ? remote.getDefaultReactions() : local.getDefaultReactions();
|
||||
boolean displayBadgesOnProfile = remote.isDisplayBadgesOnProfile();
|
||||
boolean subscriptionManuallyCancelled = remote.isSubscriptionManuallyCancelled();
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.io.Closeable;
|
|||
*/
|
||||
public interface SignalServiceDataStore extends SignalProtocolStore, SignalServiceSessionStore, SignalServiceSenderKeyStore {
|
||||
/**
|
||||
* @return True if the active account has linked devices, otherwise false.
|
||||
* @return True if the active account has or is a linked device, otherwise false.
|
||||
*/
|
||||
boolean isMultiDevice();
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue