kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add Change Number capability and Conversation Update item.
rodzic
bb446ac1d5
commit
77ff25ec49
|
@ -8,6 +8,38 @@
|
||||||
<option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" />
|
<option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" />
|
||||||
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
|
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
|
||||||
<option name="ALIGN_MULTILINE_TEXT_BLOCKS" value="true" />
|
<option name="ALIGN_MULTILINE_TEXT_BLOCKS" value="true" />
|
||||||
|
<option name="IMPORT_LAYOUT_TABLE">
|
||||||
|
<value>
|
||||||
|
<package name="android" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="androidx" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="com" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="junit" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="net" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="org" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="java" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="javax" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="android" withSubpackages="true" static="true" />
|
||||||
|
<package name="androidx" withSubpackages="true" static="true" />
|
||||||
|
<package name="com" withSubpackages="true" static="true" />
|
||||||
|
<package name="junit" withSubpackages="true" static="true" />
|
||||||
|
<package name="net" withSubpackages="true" static="true" />
|
||||||
|
<package name="org" withSubpackages="true" static="true" />
|
||||||
|
<package name="java" withSubpackages="true" static="true" />
|
||||||
|
<package name="javax" withSubpackages="true" static="true" />
|
||||||
|
<package name="" withSubpackages="true" static="true" />
|
||||||
|
<emptyLine />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
</JavaCodeStyleSettings>
|
</JavaCodeStyleSettings>
|
||||||
<JetCodeStyleSettings>
|
<JetCodeStyleSettings>
|
||||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||||
|
|
|
@ -12,12 +12,13 @@ public final class AppCapabilities {
|
||||||
private static final boolean GV1_MIGRATION = true;
|
private static final boolean GV1_MIGRATION = true;
|
||||||
private static final boolean ANNOUNCEMENT_GROUPS = true;
|
private static final boolean ANNOUNCEMENT_GROUPS = true;
|
||||||
private static final boolean SENDER_KEY = true;
|
private static final boolean SENDER_KEY = true;
|
||||||
|
private static final boolean CHANGE_NUMBER = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param storageCapable Whether or not the user can use storage service. This is another way of
|
* @param storageCapable Whether or not the user can use storage service. This is another way of
|
||||||
* asking if the user has set a Signal PIN or not.
|
* asking if the user has set a Signal PIN or not.
|
||||||
*/
|
*/
|
||||||
public static AccountAttributes.Capabilities getCapabilities(boolean storageCapable) {
|
public static AccountAttributes.Capabilities getCapabilities(boolean storageCapable) {
|
||||||
return new AccountAttributes.Capabilities(UUID_CAPABLE, GV2_CAPABLE, storageCapable, GV1_MIGRATION, SENDER_KEY, ANNOUNCEMENT_GROUPS);
|
return new AccountAttributes.Capabilities(UUID_CAPABLE, GV2_CAPABLE, storageCapable, GV1_MIGRATION, SENDER_KEY, ANNOUNCEMENT_GROUPS, CHANGE_NUMBER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ public interface BindableConversationItem extends Unbindable, GiphyMp4Playable,
|
||||||
void onPlayInlineContent(ConversationMessage conversationMessage);
|
void onPlayInlineContent(ConversationMessage conversationMessage);
|
||||||
void onInMemoryMessageClicked(@NonNull InMemoryMessageRecord messageRecord);
|
void onInMemoryMessageClicked(@NonNull InMemoryMessageRecord messageRecord);
|
||||||
void onViewGroupDescriptionChange(@Nullable GroupId groupId, @NonNull String description, boolean isMessageRequestAccepted);
|
void onViewGroupDescriptionChange(@Nullable GroupId groupId, @NonNull String description, boolean isMessageRequestAccepted);
|
||||||
|
void onChangeNumberUpdateContact(@NonNull Recipient recipient);
|
||||||
|
|
||||||
/** @return true if handled, false if you want to let the normal url handling continue */
|
/** @return true if handled, false if you want to let the normal url handling continue */
|
||||||
boolean onUrlClicked(@NonNull String url);
|
boolean onUrlClicked(@NonNull String url);
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.lock.v2.CreateKbsPinActivity
|
||||||
import org.thoughtcrime.securesms.lock.v2.KbsConstants
|
import org.thoughtcrime.securesms.lock.v2.KbsConstants
|
||||||
import org.thoughtcrime.securesms.lock.v2.PinKeyboardType
|
import org.thoughtcrime.securesms.lock.v2.PinKeyboardType
|
||||||
import org.thoughtcrime.securesms.pin.RegistrationLockV2Dialog
|
import org.thoughtcrime.securesms.pin.RegistrationLockV2Dialog
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
import org.thoughtcrime.securesms.util.ServiceUtil
|
||||||
import org.thoughtcrime.securesms.util.ThemeUtil
|
import org.thoughtcrime.securesms.util.ThemeUtil
|
||||||
|
@ -104,7 +105,7 @@ class AccountSettingsFragment : DSLSettingsFragment(R.string.AccountSettingsFrag
|
||||||
|
|
||||||
sectionHeaderPref(R.string.AccountSettingsFragment__account)
|
sectionHeaderPref(R.string.AccountSettingsFragment__account)
|
||||||
|
|
||||||
if (FeatureFlags.changeNumber()) {
|
if (FeatureFlags.changeNumber() && Recipient.self().changeNumberCapability == Recipient.Capability.SUPPORTED) {
|
||||||
clickPref(
|
clickPref(
|
||||||
title = DSLSettingsText.from(R.string.AccountSettingsFragment__change_phone_number),
|
title = DSLSettingsText.from(R.string.AccountSettingsFragment__change_phone_number),
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|
|
@ -86,7 +86,6 @@ import org.thoughtcrime.securesms.contactshare.ContactUtil;
|
||||||
import org.thoughtcrime.securesms.contactshare.SharedContactDetailsActivity;
|
import org.thoughtcrime.securesms.contactshare.SharedContactDetailsActivity;
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationAdapter.ItemClickListener;
|
import org.thoughtcrime.securesms.conversation.ConversationAdapter.ItemClickListener;
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationAdapter.StickyHeaderViewHolder;
|
import org.thoughtcrime.securesms.conversation.ConversationAdapter.StickyHeaderViewHolder;
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationMessage.ConversationMessageFactory;
|
|
||||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
||||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerView;
|
import org.thoughtcrime.securesms.conversation.colors.ColorizerView;
|
||||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectItemAnimator;
|
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectItemAnimator;
|
||||||
|
@ -136,6 +135,7 @@ import org.thoughtcrime.securesms.ratelimit.RecaptchaProofBottomSheetFragment;
|
||||||
import org.thoughtcrime.securesms.reactions.ReactionsBottomSheetDialogFragment;
|
import org.thoughtcrime.securesms.reactions.ReactionsBottomSheetDialogFragment;
|
||||||
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
import org.thoughtcrime.securesms.recipients.RecipientExporter;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment;
|
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment;
|
||||||
import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity;
|
import org.thoughtcrime.securesms.revealable.ViewOnceMessageActivity;
|
||||||
|
@ -1718,6 +1718,11 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
||||||
GroupDescriptionDialog.show(getChildFragmentManager(), groupId, description, isMessageRequestAccepted);
|
GroupDescriptionDialog.show(getChildFragmentManager(), groupId, description, isMessageRequestAccepted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChangeNumberUpdateContact(@NonNull Recipient recipient) {
|
||||||
|
startActivity(RecipientExporter.export(recipient).asAddContactIntent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshList() {
|
public void refreshList() {
|
||||||
|
|
|
@ -408,6 +408,14 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||||
eventListener.onBadDecryptLearnMoreClicked(conversationMessage.getMessageRecord().getRecipient().getId());
|
eventListener.onBadDecryptLearnMoreClicked(conversationMessage.getMessageRecord().getRecipient().getId());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else if (conversationMessage.getMessageRecord().isChangeNumber() && conversationMessage.getMessageRecord().getIndividualRecipient().isSystemContact()) {
|
||||||
|
actionButton.setText(R.string.ConversationUpdateItem_update_contact);
|
||||||
|
actionButton.setVisibility(VISIBLE);
|
||||||
|
actionButton.setOnClickListener(v -> {
|
||||||
|
if (batchSelected.isEmpty() && eventListener != null) {
|
||||||
|
eventListener.onChangeNumberUpdateContact(conversationMessage.getMessageRecord().getIndividualRecipient());
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
actionButton.setVisibility(GONE);
|
actionButton.setVisibility(GONE);
|
||||||
actionButton.setOnClickListener(null);
|
actionButton.setOnClickListener(null);
|
||||||
|
@ -480,10 +488,11 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isSameType(@NonNull MessageRecord current, @NonNull MessageRecord candidate) {
|
private static boolean isSameType(@NonNull MessageRecord current, @NonNull MessageRecord candidate) {
|
||||||
return (current.isGroupUpdate() && candidate.isGroupUpdate()) ||
|
return (current.isGroupUpdate() && candidate.isGroupUpdate()) ||
|
||||||
(current.isProfileChange() && candidate.isProfileChange()) ||
|
(current.isProfileChange() && candidate.isProfileChange()) ||
|
||||||
(current.isGroupCall() && candidate.isGroupCall()) ||
|
(current.isGroupCall() && candidate.isGroupCall()) ||
|
||||||
(current.isExpirationTimerUpdate() && candidate.isExpirationTimerUpdate());
|
(current.isExpirationTimerUpdate() && candidate.isExpirationTimerUpdate()) ||
|
||||||
|
(current.isChangeNumber() && candidate.isChangeNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,7 +7,6 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -188,7 +187,8 @@ final class MenuState {
|
||||||
messageRecord.isProfileChange() ||
|
messageRecord.isProfileChange() ||
|
||||||
messageRecord.isGroupV1MigrationEvent() ||
|
messageRecord.isGroupV1MigrationEvent() ||
|
||||||
messageRecord.isChatSessionRefresh() ||
|
messageRecord.isChatSessionRefresh() ||
|
||||||
messageRecord.isInMemoryMessageRecord();
|
messageRecord.isInMemoryMessageRecord() ||
|
||||||
|
messageRecord.isChangeNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static class Builder {
|
private final static class Builder {
|
||||||
|
|
|
@ -491,6 +491,8 @@ public final class ConversationListItem extends ConstraintLayout
|
||||||
return emphasisAdded(context, context.getString(R.string.ThreadRecord_message_could_not_be_processed), defaultTint);
|
return emphasisAdded(context, context.getString(R.string.ThreadRecord_message_could_not_be_processed), defaultTint);
|
||||||
} else if (SmsDatabase.Types.isProfileChange(thread.getType())) {
|
} else if (SmsDatabase.Types.isProfileChange(thread.getType())) {
|
||||||
return emphasisAdded(context, "", defaultTint);
|
return emphasisAdded(context, "", defaultTint);
|
||||||
|
} else if (SmsDatabase.Types.isChangeNumber(thread.getType())) {
|
||||||
|
return emphasisAdded(context, "", defaultTint);
|
||||||
} else if (MmsSmsColumns.Types.isBadDecryptType(thread.getType())) {
|
} else if (MmsSmsColumns.Types.isBadDecryptType(thread.getType())) {
|
||||||
return emphasisAdded(context, context.getString(R.string.ThreadRecord_delivery_issue), defaultTint);
|
return emphasisAdded(context, context.getString(R.string.ThreadRecord_delivery_issue), defaultTint);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -167,6 +167,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
|
||||||
public abstract long insertMessageOutbox(@NonNull OutgoingMediaMessage message, long threadId, boolean forceSms, int defaultReceiptStatus, @Nullable SmsDatabase.InsertListener insertListener) throws MmsException;
|
public abstract long insertMessageOutbox(@NonNull OutgoingMediaMessage message, long threadId, boolean forceSms, int defaultReceiptStatus, @Nullable SmsDatabase.InsertListener insertListener) throws MmsException;
|
||||||
public abstract void insertProfileNameChangeMessages(@NonNull Recipient recipient, @NonNull String newProfileName, @NonNull String previousProfileName);
|
public abstract void insertProfileNameChangeMessages(@NonNull Recipient recipient, @NonNull String newProfileName, @NonNull String previousProfileName);
|
||||||
public abstract void insertGroupV1MigrationEvents(@NonNull RecipientId recipientId, long threadId, @NonNull GroupMigrationMembershipChange membershipChange);
|
public abstract void insertGroupV1MigrationEvents(@NonNull RecipientId recipientId, long threadId, @NonNull GroupMigrationMembershipChange membershipChange);
|
||||||
|
public abstract void insertNumberChangeMessages(@NonNull Recipient recipient);
|
||||||
|
|
||||||
public abstract boolean deleteMessage(long messageId);
|
public abstract boolean deleteMessage(long messageId);
|
||||||
abstract void deleteThread(long threadId);
|
abstract void deleteThread(long threadId);
|
||||||
|
|
|
@ -503,6 +503,11 @@ public class MmsDatabase extends MessageDatabase {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertNumberChangeMessages(@NonNull Recipient recipient) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endTransaction(SQLiteDatabase database) {
|
public void endTransaction(SQLiteDatabase database) {
|
||||||
database.endTransaction();
|
database.endTransaction();
|
||||||
|
|
|
@ -77,6 +77,7 @@ public interface MmsSmsColumns {
|
||||||
protected static final long OUTGOING_VIDEO_CALL_TYPE = 11;
|
protected static final long OUTGOING_VIDEO_CALL_TYPE = 11;
|
||||||
protected static final long GROUP_CALL_TYPE = 12;
|
protected static final long GROUP_CALL_TYPE = 12;
|
||||||
protected static final long BAD_DECRYPT_TYPE = 13;
|
protected static final long BAD_DECRYPT_TYPE = 13;
|
||||||
|
protected static final long CHANGE_NUMBER_TYPE = 14;
|
||||||
|
|
||||||
protected static final long BASE_INBOX_TYPE = 20;
|
protected static final long BASE_INBOX_TYPE = 20;
|
||||||
protected static final long BASE_OUTBOX_TYPE = 21;
|
protected static final long BASE_OUTBOX_TYPE = 21;
|
||||||
|
@ -334,6 +335,10 @@ public interface MmsSmsColumns {
|
||||||
return type == GV1_MIGRATION_TYPE;
|
return type == GV1_MIGRATION_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isChangeNumber(long type) {
|
||||||
|
return type == CHANGE_NUMBER_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
public static long translateFromSystemBaseType(long theirType) {
|
public static long translateFromSystemBaseType(long theirType) {
|
||||||
// public static final int NONE_TYPE = 0;
|
// public static final int NONE_TYPE = 0;
|
||||||
// public static final int INBOX_TYPE = 1;
|
// public static final int INBOX_TYPE = 1;
|
||||||
|
|
|
@ -108,7 +108,7 @@ public class MmsSmsDatabase extends Database {
|
||||||
MmsSmsColumns.RECEIPT_TIMESTAMP};
|
MmsSmsColumns.RECEIPT_TIMESTAMP};
|
||||||
|
|
||||||
private static final String SNIPPET_QUERY = "SELECT " + MmsSmsColumns.ID + ", 0 AS " + TRANSPORT + ", " + SmsDatabase.TYPE + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + SmsDatabase.TABLE_NAME + " " +
|
private static final String SNIPPET_QUERY = "SELECT " + MmsSmsColumns.ID + ", 0 AS " + TRANSPORT + ", " + SmsDatabase.TYPE + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + SmsDatabase.TABLE_NAME + " " +
|
||||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ") " +
|
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ", " + SmsDatabase.Types.CHANGE_NUMBER_TYPE + ") " +
|
||||||
"UNION ALL " +
|
"UNION ALL " +
|
||||||
"SELECT " + MmsSmsColumns.ID + ", 1 AS " + TRANSPORT + ", " + MmsDatabase.MESSAGE_BOX + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + MmsDatabase.TABLE_NAME + " " +
|
"SELECT " + MmsSmsColumns.ID + ", 1 AS " + TRANSPORT + ", " + MmsDatabase.MESSAGE_BOX + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + MmsDatabase.TABLE_NAME + " " +
|
||||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? " +
|
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? " +
|
||||||
|
|
|
@ -29,9 +29,9 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||||
import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper;
|
import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper;
|
||||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
||||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
|
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
|
||||||
import org.thoughtcrime.securesms.database.model.IdentityRecord;
|
|
||||||
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||||
|
import org.thoughtcrime.securesms.database.model.IdentityRecord;
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||||
import org.thoughtcrime.securesms.database.model.databaseprotos.ChatColor;
|
import org.thoughtcrime.securesms.database.model.databaseprotos.ChatColor;
|
||||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DeviceLastResetTime;
|
import org.thoughtcrime.securesms.database.model.databaseprotos.DeviceLastResetTime;
|
||||||
|
@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.groups.GroupId;
|
import org.thoughtcrime.securesms.groups.GroupId;
|
||||||
import org.thoughtcrime.securesms.groups.v2.ProfileKeySet;
|
import org.thoughtcrime.securesms.groups.v2.ProfileKeySet;
|
||||||
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
|
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
|
||||||
|
import org.thoughtcrime.securesms.jobs.RecipientChangedNumberJob;
|
||||||
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
||||||
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
|
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
|
||||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
|
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
|
||||||
|
@ -59,6 +60,7 @@ import org.thoughtcrime.securesms.util.GroupUtil;
|
||||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||||
import org.thoughtcrime.securesms.util.SqlUtil;
|
import org.thoughtcrime.securesms.util.SqlUtil;
|
||||||
import org.thoughtcrime.securesms.util.StringUtil;
|
import org.thoughtcrime.securesms.util.StringUtil;
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaperFactory;
|
import org.thoughtcrime.securesms.wallpaper.ChatWallpaperFactory;
|
||||||
|
@ -167,6 +169,7 @@ public class RecipientDatabase extends Database {
|
||||||
static final int GROUPS_V1_MIGRATION = 1;
|
static final int GROUPS_V1_MIGRATION = 1;
|
||||||
static final int SENDER_KEY = 2;
|
static final int SENDER_KEY = 2;
|
||||||
static final int ANNOUNCEMENT_GROUPS = 3;
|
static final int ANNOUNCEMENT_GROUPS = 3;
|
||||||
|
static final int CHANGE_NUMBER = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String[] RECIPIENT_PROJECTION = new String[] {
|
private static final String[] RECIPIENT_PROJECTION = new String[] {
|
||||||
|
@ -421,12 +424,17 @@ public class RecipientDatabase extends Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull RecipientId getAndPossiblyMerge(@Nullable UUID uuid, @Nullable String e164, boolean highTrust) {
|
public @NonNull RecipientId getAndPossiblyMerge(@Nullable UUID uuid, @Nullable String e164, boolean highTrust) {
|
||||||
|
return getAndPossiblyMerge(uuid, e164, highTrust, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NonNull RecipientId getAndPossiblyMerge(@Nullable UUID uuid, @Nullable String e164, boolean highTrust, boolean changeSelf) {
|
||||||
if (uuid == null && e164 == null) {
|
if (uuid == null && e164 == null) {
|
||||||
throw new IllegalArgumentException("Must provide a UUID or E164!");
|
throw new IllegalArgumentException("Must provide a UUID or E164!");
|
||||||
}
|
}
|
||||||
|
|
||||||
RecipientId recipientNeedingRefresh = null;
|
RecipientId recipientNeedingRefresh = null;
|
||||||
Pair<RecipientId, RecipientId> remapped = null;
|
Pair<RecipientId, RecipientId> remapped = null;
|
||||||
|
RecipientId recipientChangedNumber = null;
|
||||||
boolean transactionSuccessful = false;
|
boolean transactionSuccessful = false;
|
||||||
|
|
||||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||||
|
@ -485,9 +493,15 @@ public class RecipientDatabase extends Database {
|
||||||
} else if (!byE164.isPresent() && byUuid.isPresent()) {
|
} else if (!byE164.isPresent() && byUuid.isPresent()) {
|
||||||
if (e164 != null) {
|
if (e164 != null) {
|
||||||
if (highTrust) {
|
if (highTrust) {
|
||||||
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). High-trust, so updating.", e164, byUuid.get()), true);
|
if (Objects.equals(uuid, TextSecurePreferences.getLocalUuid(context)) && !changeSelf) {
|
||||||
setPhoneNumberOrThrow(byUuid.get(), e164);
|
Log.w(TAG, String.format(Locale.US, "Found out about an E164 (%s) for our own UUID user (%s). High-trust but not change self, doing nothing.", e164, byUuid.get()), true);
|
||||||
finalId = byUuid.get();
|
finalId = byUuid.get();
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). High-trust, so updating.", e164, byUuid.get()), true);
|
||||||
|
setPhoneNumberOrThrow(byUuid.get(), e164);
|
||||||
|
finalId = byUuid.get();
|
||||||
|
recipientChangedNumber = finalId;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). Low-trust, so doing nothing.", e164, byUuid.get()), true);
|
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). Low-trust, so doing nothing.", e164, byUuid.get()), true);
|
||||||
finalId = byUuid.get();
|
finalId = byUuid.get();
|
||||||
|
@ -552,6 +566,10 @@ public class RecipientDatabase extends Database {
|
||||||
StorageSyncHelper.scheduleSyncForDataChange();
|
StorageSyncHelper.scheduleSyncForDataChange();
|
||||||
RecipientId.clearCache();
|
RecipientId.clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (recipientChangedNumber != null) {
|
||||||
|
ApplicationDependencies.getJobManager().add(new RecipientChangedNumberJob(recipientChangedNumber));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1616,6 +1634,7 @@ public class RecipientDatabase extends Database {
|
||||||
value = Bitmask.update(value, Capabilities.GROUPS_V1_MIGRATION, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isGv1Migration()).serialize());
|
value = Bitmask.update(value, Capabilities.GROUPS_V1_MIGRATION, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isGv1Migration()).serialize());
|
||||||
value = Bitmask.update(value, Capabilities.SENDER_KEY, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isSenderKey()).serialize());
|
value = Bitmask.update(value, Capabilities.SENDER_KEY, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isSenderKey()).serialize());
|
||||||
value = Bitmask.update(value, Capabilities.ANNOUNCEMENT_GROUPS, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isAnnouncementGroup()).serialize());
|
value = Bitmask.update(value, Capabilities.ANNOUNCEMENT_GROUPS, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isAnnouncementGroup()).serialize());
|
||||||
|
value = Bitmask.update(value, Capabilities.CHANGE_NUMBER, Capabilities.BIT_LENGTH, Recipient.Capability.fromBoolean(capabilities.isChangeNumber()).serialize());
|
||||||
|
|
||||||
ContentValues values = new ContentValues(1);
|
ContentValues values = new ContentValues(1);
|
||||||
values.put(CAPABILITIES, value);
|
values.put(CAPABILITIES, value);
|
||||||
|
@ -2040,7 +2059,7 @@ public class RecipientDatabase extends Database {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
RecipientId id = Recipient.self().getId();
|
RecipientId id = Recipient.self().getId();
|
||||||
RecipientId newId = getAndPossiblyMerge(Recipient.self().requireUuid(), e164, true);
|
RecipientId newId = getAndPossiblyMerge(Recipient.self().requireUuid(), e164, true, true);
|
||||||
|
|
||||||
if (id.equals(newId)) {
|
if (id.equals(newId)) {
|
||||||
Log.i(TAG, "[updateSelfPhone] Phone updated for self");
|
Log.i(TAG, "[updateSelfPhone] Phone updated for self");
|
||||||
|
@ -3159,6 +3178,7 @@ public class RecipientDatabase extends Database {
|
||||||
private final Recipient.Capability groupsV1MigrationCapability;
|
private final Recipient.Capability groupsV1MigrationCapability;
|
||||||
private final Recipient.Capability senderKeyCapability;
|
private final Recipient.Capability senderKeyCapability;
|
||||||
private final Recipient.Capability announcementGroupCapability;
|
private final Recipient.Capability announcementGroupCapability;
|
||||||
|
private final Recipient.Capability changeNumberCapability;
|
||||||
private final InsightsBannerTier insightsBannerTier;
|
private final InsightsBannerTier insightsBannerTier;
|
||||||
private final byte[] storageId;
|
private final byte[] storageId;
|
||||||
private final MentionSetting mentionSetting;
|
private final MentionSetting mentionSetting;
|
||||||
|
@ -3251,6 +3271,7 @@ public class RecipientDatabase extends Database {
|
||||||
this.groupsV1MigrationCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.GROUPS_V1_MIGRATION, Capabilities.BIT_LENGTH));
|
this.groupsV1MigrationCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.GROUPS_V1_MIGRATION, Capabilities.BIT_LENGTH));
|
||||||
this.senderKeyCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.SENDER_KEY, Capabilities.BIT_LENGTH));
|
this.senderKeyCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.SENDER_KEY, Capabilities.BIT_LENGTH));
|
||||||
this.announcementGroupCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.ANNOUNCEMENT_GROUPS, Capabilities.BIT_LENGTH));
|
this.announcementGroupCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.ANNOUNCEMENT_GROUPS, Capabilities.BIT_LENGTH));
|
||||||
|
this.changeNumberCapability = Recipient.Capability.deserialize((int) Bitmask.read(capabilities, Capabilities.CHANGE_NUMBER, Capabilities.BIT_LENGTH));
|
||||||
this.insightsBannerTier = insightsBannerTier;
|
this.insightsBannerTier = insightsBannerTier;
|
||||||
this.storageId = storageId;
|
this.storageId = storageId;
|
||||||
this.mentionSetting = mentionSetting;
|
this.mentionSetting = mentionSetting;
|
||||||
|
@ -3408,6 +3429,10 @@ public class RecipientDatabase extends Database {
|
||||||
return announcementGroupCapability;
|
return announcementGroupCapability;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NonNull Recipient.Capability getChangeNumberCapability() {
|
||||||
|
return changeNumberCapability;
|
||||||
|
}
|
||||||
|
|
||||||
public @Nullable byte[] getStorageId() {
|
public @Nullable byte[] getStorageId() {
|
||||||
return storageId;
|
return storageId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -270,8 +271,8 @@ public class SmsDatabase extends MessageDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NonNull SqlUtil.Query buildMeaningfulMessagesQuery(long threadId) {
|
private @NonNull SqlUtil.Query buildMeaningfulMessagesQuery(long threadId) {
|
||||||
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND TYPE != ?)";
|
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND TYPE != ? AND TYPE != ?)";
|
||||||
return SqlUtil.buildQuery(query, threadId, IGNORABLE_TYPESMASK_WHEN_COUNTING, Types.PROFILE_CHANGE_TYPE);
|
return SqlUtil.buildQuery(query, threadId, IGNORABLE_TYPESMASK_WHEN_COUNTING, Types.PROFILE_CHANGE_TYPE, Types.CHANGE_NUMBER_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1027,6 +1028,53 @@ public class SmsDatabase extends MessageDatabase {
|
||||||
databaseHelper.getSignalWritableDatabase().insert(TABLE_NAME, null, values);
|
databaseHelper.getSignalWritableDatabase().insert(TABLE_NAME, null, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertNumberChangeMessages(@NonNull Recipient recipient) {
|
||||||
|
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||||
|
List<GroupDatabase.GroupRecord> groupRecords = DatabaseFactory.getGroupDatabase(context).getGroupsContainingMember(recipient.getId(), false);
|
||||||
|
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||||
|
|
||||||
|
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||||
|
db.beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
threadIdsToUpdate.add(threadDatabase.getThreadIdFor(recipient.getId()));
|
||||||
|
for (GroupDatabase.GroupRecord groupRecord : groupRecords) {
|
||||||
|
if (groupRecord.isActive()) {
|
||||||
|
threadIdsToUpdate.add(threadDatabase.getThreadIdFor(groupRecord.getRecipientId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
threadIdsToUpdate.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.forEach(threadId -> {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(RECIPIENT_ID, recipient.getId().serialize());
|
||||||
|
values.put(ADDRESS_DEVICE_ID, 1);
|
||||||
|
values.put(DATE_RECEIVED, System.currentTimeMillis());
|
||||||
|
values.put(DATE_SENT, System.currentTimeMillis());
|
||||||
|
values.put(READ, 1);
|
||||||
|
values.put(TYPE, Types.CHANGE_NUMBER_TYPE);
|
||||||
|
values.put(THREAD_ID, threadId);
|
||||||
|
values.putNull(BODY);
|
||||||
|
|
||||||
|
db.insert(TABLE_NAME, null, values);
|
||||||
|
});
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
threadIdsToUpdate.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.forEach(threadId -> {
|
||||||
|
TrimThreadJob.enqueueAsync(threadId);
|
||||||
|
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
|
||||||
|
notifyConversationListeners(threadId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, long type) {
|
public Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, long type) {
|
||||||
if (message.isJoined()) {
|
if (message.isJoined()) {
|
||||||
|
|
|
@ -1514,7 +1514,8 @@ public class ThreadDatabase extends Database {
|
||||||
|
|
||||||
private boolean isSilentType(long type) {
|
private boolean isSilentType(long type) {
|
||||||
return MmsSmsColumns.Types.isProfileChange(type) ||
|
return MmsSmsColumns.Types.isProfileChange(type) ||
|
||||||
MmsSmsColumns.Types.isGroupV1MigrationEvent(type);
|
MmsSmsColumns.Types.isGroupV1MigrationEvent(type) ||
|
||||||
|
MmsSmsColumns.Types.isChangeNumber(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Reader readerFor(Cursor cursor) {
|
public Reader readerFor(Cursor cursor) {
|
||||||
|
|
|
@ -178,6 +178,10 @@ public abstract class DisplayRecord {
|
||||||
return SmsDatabase.Types.isProfileChange(type);
|
return SmsDatabase.Types.isProfileChange(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isChangeNumber() {
|
||||||
|
return SmsDatabase.Types.isChangeNumber(type);
|
||||||
|
}
|
||||||
|
|
||||||
public int getDeliveryStatus() {
|
public int getDeliveryStatus() {
|
||||||
return deliveryStatus;
|
return deliveryStatus;
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,6 +187,8 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||||
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||||
} else if (isProfileChange()) {
|
} else if (isProfileChange()) {
|
||||||
return staticUpdateDescription(getProfileChangeDescription(context), R.drawable.ic_update_profile_16);
|
return staticUpdateDescription(getProfileChangeDescription(context), R.drawable.ic_update_profile_16);
|
||||||
|
} else if (isChangeNumber()) {
|
||||||
|
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_changed_their_number_to_a_new_number, r.getDisplayName(context)), R.drawable.ic_phone_16);
|
||||||
} else if (isEndSession()) {
|
} else if (isEndSession()) {
|
||||||
if (isOutgoing()) return staticUpdateDescription(context.getString(R.string.SmsMessageRecord_secure_session_reset), R.drawable.ic_update_info_16);
|
if (isOutgoing()) return staticUpdateDescription(context.getString(R.string.SmsMessageRecord_secure_session_reset), R.drawable.ic_update_info_16);
|
||||||
else return fromRecipient(getIndividualRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
else return fromRecipient(getIndividualRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||||
|
@ -484,7 +486,8 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||||
public boolean isUpdate() {
|
public boolean isUpdate() {
|
||||||
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
|
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
|
||||||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
|
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
|
||||||
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType();
|
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType() ||
|
||||||
|
isChangeNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMediaPending() {
|
public boolean isMediaPending() {
|
||||||
|
|
|
@ -131,6 +131,7 @@ public final class JobManagerFactories {
|
||||||
put(PushNotificationReceiveJob.KEY, new PushNotificationReceiveJob.Factory());
|
put(PushNotificationReceiveJob.KEY, new PushNotificationReceiveJob.Factory());
|
||||||
put(PushTextSendJob.KEY, new PushTextSendJob.Factory());
|
put(PushTextSendJob.KEY, new PushTextSendJob.Factory());
|
||||||
put(ReactionSendJob.KEY, new ReactionSendJob.Factory());
|
put(ReactionSendJob.KEY, new ReactionSendJob.Factory());
|
||||||
|
put(RecipientChangedNumberJob.KEY, new RecipientChangedNumberJob.Factory());
|
||||||
put(RefreshAttributesJob.KEY, new RefreshAttributesJob.Factory());
|
put(RefreshAttributesJob.KEY, new RefreshAttributesJob.Factory());
|
||||||
put(RefreshOwnProfileJob.KEY, new RefreshOwnProfileJob.Factory());
|
put(RefreshOwnProfileJob.KEY, new RefreshOwnProfileJob.Factory());
|
||||||
put(RefreshPreKeysJob.KEY, new RefreshPreKeysJob.Factory());
|
put(RefreshPreKeysJob.KEY, new RefreshPreKeysJob.Factory());
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.thoughtcrime.securesms.jobs
|
||||||
|
|
||||||
|
import org.signal.core.util.logging.Log
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
|
import org.thoughtcrime.securesms.jobmanager.Data
|
||||||
|
import org.thoughtcrime.securesms.jobmanager.Job
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
|
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert change number update items in all threads (1:1 and group) with [recipientId].
|
||||||
|
*/
|
||||||
|
class RecipientChangedNumberJob(parameters: Parameters, private val recipientId: RecipientId) : BaseJob(parameters) {
|
||||||
|
|
||||||
|
constructor(recipientId: RecipientId) : this(
|
||||||
|
Parameters.Builder().setQueue("RecipientChangedNumberJob_${recipientId.toQueueKey()}").build(),
|
||||||
|
recipientId
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun serialize(): Data {
|
||||||
|
return Data.Builder()
|
||||||
|
.putString(KEY_RECIPIENT_ID, recipientId.serialize())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFactoryKey(): String {
|
||||||
|
return KEY
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRun() {
|
||||||
|
val recipient: Recipient = Recipient.resolved(recipientId)
|
||||||
|
|
||||||
|
if (!recipient.isBlocked && !recipient.isGroup && !recipient.isSelf) {
|
||||||
|
Log.i(TAG, "Writing a number change event.")
|
||||||
|
DatabaseFactory.getSmsDatabase(context).insertNumberChangeMessages(recipient)
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "Number changed but not relevant. blocked: ${recipient.isBlocked} isGroup: ${recipient.isGroup} isSelf: ${recipient.isSelf}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onShouldRetry(e: Exception): Boolean = false
|
||||||
|
|
||||||
|
override fun onFailure() = Unit
|
||||||
|
|
||||||
|
class Factory : Job.Factory<RecipientChangedNumberJob> {
|
||||||
|
override fun create(parameters: Parameters, data: Data): RecipientChangedNumberJob {
|
||||||
|
return RecipientChangedNumberJob(parameters, RecipientId.from(data.getString(KEY_RECIPIENT_ID)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KEY = "RecipientChangedNumberJob"
|
||||||
|
|
||||||
|
private val TAG = Log.tag(RecipientChangedNumberJob::class.java)
|
||||||
|
private const val KEY_RECIPIENT_ID = "recipient_id"
|
||||||
|
}
|
||||||
|
}
|
|
@ -103,6 +103,7 @@ public class RefreshAttributesJob extends BaseJob {
|
||||||
"\n GV1 Migration? " + capabilities.isGv1Migration() +
|
"\n GV1 Migration? " + capabilities.isGv1Migration() +
|
||||||
"\n Sender Key? " + capabilities.isSenderKey() +
|
"\n Sender Key? " + capabilities.isSenderKey() +
|
||||||
"\n Announcement Groups? " + capabilities.isAnnouncementGroup() +
|
"\n Announcement Groups? " + capabilities.isAnnouncementGroup() +
|
||||||
|
"\n Change Number? " + capabilities.isChangeNumber() +
|
||||||
"\n UUID? " + capabilities.isUuid());
|
"\n UUID? " + capabilities.isUuid());
|
||||||
|
|
||||||
SignalServiceAccountManager signalAccountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
SignalServiceAccountManager signalAccountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
||||||
|
|
|
@ -35,11 +35,13 @@ public final class LogSectionCapabilities implements LogSection {
|
||||||
.append("GV1 Migration : ").append(capabilities.isGv1Migration()).append("\n")
|
.append("GV1 Migration : ").append(capabilities.isGv1Migration()).append("\n")
|
||||||
.append("Sender Key : ").append(capabilities.isSenderKey()).append("\n")
|
.append("Sender Key : ").append(capabilities.isSenderKey()).append("\n")
|
||||||
.append("Announcement Groups: ").append(capabilities.isAnnouncementGroup()).append("\n")
|
.append("Announcement Groups: ").append(capabilities.isAnnouncementGroup()).append("\n")
|
||||||
|
.append("Change Number : ").append(capabilities.isChangeNumber()).append("\n")
|
||||||
.append("\n")
|
.append("\n")
|
||||||
.append("-- Global").append("\n")
|
.append("-- Global").append("\n")
|
||||||
.append("GV2 : ").append(self.getGroupsV2Capability()).append("\n")
|
.append("GV2 : ").append(self.getGroupsV2Capability()).append("\n")
|
||||||
.append("GV1 Migration : ").append(self.getGroupsV1MigrationCapability()).append("\n")
|
.append("GV1 Migration : ").append(self.getGroupsV1MigrationCapability()).append("\n")
|
||||||
.append("Sender Key : ").append(self.getSenderKeyCapability()).append("\n")
|
.append("Sender Key : ").append(self.getSenderKeyCapability()).append("\n")
|
||||||
.append("Announcement Groups: ").append(self.getAnnouncementGroupCapability()).append("\n");
|
.append("Announcement Groups: ").append(self.getAnnouncementGroupCapability()).append("\n")
|
||||||
|
.append("Change Number : ").append(self.getChangeNumberCapability()).append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.migrations;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
@ -40,7 +41,8 @@ public class ApplicationMigrations {
|
||||||
|
|
||||||
private static final int LEGACY_CANONICAL_VERSION = 455;
|
private static final int LEGACY_CANONICAL_VERSION = 455;
|
||||||
|
|
||||||
private static final class Version {
|
@VisibleForTesting
|
||||||
|
static final class Version {
|
||||||
static final int LEGACY = 1;
|
static final int LEGACY = 1;
|
||||||
static final int RECIPIENT_ID = 2;
|
static final int RECIPIENT_ID = 2;
|
||||||
static final int RECIPIENT_SEARCH = 3;
|
static final int RECIPIENT_SEARCH = 3;
|
||||||
|
@ -84,9 +86,10 @@ public class ApplicationMigrations {
|
||||||
static final int STICKER_MY_DAILY_LIFE = 42;
|
static final int STICKER_MY_DAILY_LIFE = 42;
|
||||||
static final int SENDER_KEY_3 = 43;
|
static final int SENDER_KEY_3 = 43;
|
||||||
static final int CHANGE_NUMBER_SYNC = 44;
|
static final int CHANGE_NUMBER_SYNC = 44;
|
||||||
|
static final int CHANGE_NUMBER_CAPABILITY = 45;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int CURRENT_VERSION = 43;
|
public static final int CURRENT_VERSION = 45;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
|
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
|
||||||
|
@ -372,6 +375,10 @@ public class ApplicationMigrations {
|
||||||
jobs.put(Version.CHANGE_NUMBER_SYNC, new AccountRecordMigrationJob());
|
jobs.put(Version.CHANGE_NUMBER_SYNC, new AccountRecordMigrationJob());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lastSeenVersion < Version.CHANGE_NUMBER_CAPABILITY) {
|
||||||
|
jobs.put(Version.CHANGE_NUMBER_CAPABILITY, new AttributesMigrationJob());
|
||||||
|
}
|
||||||
|
|
||||||
return jobs;
|
return jobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.thoughtcrime.securesms.recipients;
|
package org.thoughtcrime.securesms.recipients;
|
||||||
|
|
||||||
import static org.thoughtcrime.securesms.database.RecipientDatabase.InsightsBannerTier;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
@ -63,6 +61,8 @@ import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.thoughtcrime.securesms.database.RecipientDatabase.InsightsBannerTier;
|
||||||
|
|
||||||
public class Recipient {
|
public class Recipient {
|
||||||
|
|
||||||
private static final String TAG = Log.tag(Recipient.class);
|
private static final String TAG = Log.tag(Recipient.class);
|
||||||
|
@ -110,6 +110,7 @@ public class Recipient {
|
||||||
private final Capability groupsV1MigrationCapability;
|
private final Capability groupsV1MigrationCapability;
|
||||||
private final Capability senderKeyCapability;
|
private final Capability senderKeyCapability;
|
||||||
private final Capability announcementGroupCapability;
|
private final Capability announcementGroupCapability;
|
||||||
|
private final Capability changeNumberCapability;
|
||||||
private final InsightsBannerTier insightsBannerTier;
|
private final InsightsBannerTier insightsBannerTier;
|
||||||
private final byte[] storageId;
|
private final byte[] storageId;
|
||||||
private final MentionSetting mentionSetting;
|
private final MentionSetting mentionSetting;
|
||||||
|
@ -362,6 +363,7 @@ public class Recipient {
|
||||||
this.groupsV1MigrationCapability = Capability.UNKNOWN;
|
this.groupsV1MigrationCapability = Capability.UNKNOWN;
|
||||||
this.senderKeyCapability = Capability.UNKNOWN;
|
this.senderKeyCapability = Capability.UNKNOWN;
|
||||||
this.announcementGroupCapability = Capability.UNKNOWN;
|
this.announcementGroupCapability = Capability.UNKNOWN;
|
||||||
|
this.changeNumberCapability = Capability.UNKNOWN;
|
||||||
this.storageId = null;
|
this.storageId = null;
|
||||||
this.mentionSetting = MentionSetting.ALWAYS_NOTIFY;
|
this.mentionSetting = MentionSetting.ALWAYS_NOTIFY;
|
||||||
this.wallpaper = null;
|
this.wallpaper = null;
|
||||||
|
@ -414,6 +416,7 @@ public class Recipient {
|
||||||
this.groupsV1MigrationCapability = details.groupsV1MigrationCapability;
|
this.groupsV1MigrationCapability = details.groupsV1MigrationCapability;
|
||||||
this.senderKeyCapability = details.senderKeyCapability;
|
this.senderKeyCapability = details.senderKeyCapability;
|
||||||
this.announcementGroupCapability = details.announcementGroupCapability;
|
this.announcementGroupCapability = details.announcementGroupCapability;
|
||||||
|
this.changeNumberCapability = details.changeNumberCapability;
|
||||||
this.storageId = details.storageId;
|
this.storageId = details.storageId;
|
||||||
this.mentionSetting = details.mentionSetting;
|
this.mentionSetting = details.mentionSetting;
|
||||||
this.wallpaper = details.wallpaper;
|
this.wallpaper = details.wallpaper;
|
||||||
|
@ -918,6 +921,10 @@ public class Recipient {
|
||||||
return announcementGroupCapability;
|
return announcementGroupCapability;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NonNull Capability getChangeNumberCapability() {
|
||||||
|
return changeNumberCapability;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if this recipient supports the message retry system, or false if we should use the legacy session reset system.
|
* True if this recipient supports the message retry system, or false if we should use the legacy session reset system.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -65,6 +65,7 @@ public class RecipientDetails {
|
||||||
final Recipient.Capability groupsV1MigrationCapability;
|
final Recipient.Capability groupsV1MigrationCapability;
|
||||||
final Recipient.Capability senderKeyCapability;
|
final Recipient.Capability senderKeyCapability;
|
||||||
final Recipient.Capability announcementGroupCapability;
|
final Recipient.Capability announcementGroupCapability;
|
||||||
|
final Recipient.Capability changeNumberCapability;
|
||||||
final InsightsBannerTier insightsBannerTier;
|
final InsightsBannerTier insightsBannerTier;
|
||||||
final byte[] storageId;
|
final byte[] storageId;
|
||||||
final MentionSetting mentionSetting;
|
final MentionSetting mentionSetting;
|
||||||
|
@ -121,6 +122,7 @@ public class RecipientDetails {
|
||||||
this.groupsV1MigrationCapability = settings.getGroupsV1MigrationCapability();
|
this.groupsV1MigrationCapability = settings.getGroupsV1MigrationCapability();
|
||||||
this.senderKeyCapability = settings.getSenderKeyCapability();
|
this.senderKeyCapability = settings.getSenderKeyCapability();
|
||||||
this.announcementGroupCapability = settings.getAnnouncementGroupCapability();
|
this.announcementGroupCapability = settings.getAnnouncementGroupCapability();
|
||||||
|
this.changeNumberCapability = settings.getChangeNumberCapability();
|
||||||
this.insightsBannerTier = settings.getInsightsBannerTier();
|
this.insightsBannerTier = settings.getInsightsBannerTier();
|
||||||
this.storageId = settings.getStorageId();
|
this.storageId = settings.getStorageId();
|
||||||
this.mentionSetting = settings.getMentionSetting();
|
this.mentionSetting = settings.getMentionSetting();
|
||||||
|
@ -177,6 +179,7 @@ public class RecipientDetails {
|
||||||
this.groupsV1MigrationCapability = Recipient.Capability.UNKNOWN;
|
this.groupsV1MigrationCapability = Recipient.Capability.UNKNOWN;
|
||||||
this.senderKeyCapability = Recipient.Capability.UNKNOWN;
|
this.senderKeyCapability = Recipient.Capability.UNKNOWN;
|
||||||
this.announcementGroupCapability = Recipient.Capability.UNKNOWN;
|
this.announcementGroupCapability = Recipient.Capability.UNKNOWN;
|
||||||
|
this.changeNumberCapability = Recipient.Capability.UNKNOWN;
|
||||||
this.storageId = null;
|
this.storageId = null;
|
||||||
this.mentionSetting = MentionSetting.ALWAYS_NOTIFY;
|
this.mentionSetting = MentionSetting.ALWAYS_NOTIFY;
|
||||||
this.wallpaper = null;
|
this.wallpaper = null;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="16dp"
|
||||||
|
android:height="16dp"
|
||||||
|
android:viewportWidth="16"
|
||||||
|
android:viewportHeight="16">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M2.41,3.05a3.15,3.15 0,0 0,-0.16 3.12,13.11 13.11,0 0,0 7.58,7.58A3.15,3.15 0,0 0,13 13.59a2.83,2.83 0,0 0,1 -1.16,1.27 1.27,0 0,0 -0.4,-1.62l-2,-1.38a1.27,1.27 0,0 0,-1.65 0.16c-0.22,0.24 -0.37,0.4 -0.54,0.6a0.65,0.65 0,0 1,-0.87 0.12A15.06,15.06 0,0 1,7 9a15.06,15.06 0,0 1,-1.29 -1.5,0.65 0.65,0 0,1 0.12,-0.87l0.6,-0.54a1.27,1.27 0,0 0,0.16 -1.65l-1.38,-2a1.27,1.27 0,0 0,-1.62 -0.4A2.83,2.83 0,0 0,2.41 3.05Z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="16dp"
|
||||||
|
android:height="16dp"
|
||||||
|
android:viewportWidth="16"
|
||||||
|
android:viewportHeight="16">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M11.17,14.14a4.94,4.94 0,0 1,-1.63 -0.32,12.87 12.87,0 0,1 -4.47,-2.89A12.87,12.87 0,0 1,2.18 6.46,3.49 3.49,0 0,1 2.39,3.1h0a3.17,3.17 0,0 1,1.22 -1,1.69 1.69,0 0,1 2.18,0.51L7.08,4.42A1.68,1.68 0,0 1,6.86 6.6l-0.56,0.52s-0.07,0.1 0,0.13A11.37,11.37 0,0 0,7.41 8.59,10.62 10.62,0 0,0 8.75,9.75s0.09,0 0.13,0c0.17,-0.2 0.31,-0.35 0.52,-0.57a1.68,1.68 0,0 1,2.18 -0.22l1.84,1.29A1.68,1.68 0,0 1,14 12.35a3.15,3.15 0,0 1,-1 1.26A3,3 0,0 1,11.17 14.14ZM4.42,2.86a0.68,0.68 0,0 0,-0.31 0.08,2.13 2.13,0 0,0 -0.9,0.74h0a2.47,2.47 0,0 0,-0.09 2.45,11.77 11.77,0 0,0 6.75,6.75 2.47,2.47 0,0 0,2.45 -0.09,2.12 2.12,0 0,0 0.72,-0.85 0.7,0.7 0,0 0,-0.19 -0.91L11,9.74a0.67,0.67 0,0 0,-0.88 0.08c-0.21,0.22 -0.34,0.36 -0.5,0.55a1.09,1.09 0,0 1,-1.48 0.18A13.27,13.27 0,0 1,6.7 9.3,13.27 13.27,0 0,1 5.45,7.85a1.09,1.09 0,0 1,0.18 -1.48c0.19,-0.16 0.33,-0.29 0.55,-0.5A0.67,0.67 0,0 0,6.26 5L5,3.15A0.73,0.73 0,0 0,4.42 2.86Z"/>
|
||||||
|
</vector>
|
|
@ -1209,6 +1209,7 @@
|
||||||
<string name="MessageRecord_you_marked_your_safety_number_with_s_unverified">You marked your safety number with %s unverified</string>
|
<string name="MessageRecord_you_marked_your_safety_number_with_s_unverified">You marked your safety number with %s unverified</string>
|
||||||
<string name="MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device">You marked your safety number with %s unverified from another device</string>
|
<string name="MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device">You marked your safety number with %s unverified from another device</string>
|
||||||
<string name="MessageRecord_a_message_from_s_couldnt_be_delivered">A message from %s couldn\'t be delivered</string>
|
<string name="MessageRecord_a_message_from_s_couldnt_be_delivered">A message from %s couldn\'t be delivered</string>
|
||||||
|
<string name="MessageRecord_s_changed_their_number_to_a_new_number">%1$s changed their number to a new number.</string>
|
||||||
|
|
||||||
<!-- Group Calling update messages -->
|
<!-- Group Calling update messages -->
|
||||||
<string name="MessageRecord_s_started_a_group_call_s">%1$s started a group call · %2$s</string>
|
<string name="MessageRecord_s_started_a_group_call_s">%1$s started a group call · %2$s</string>
|
||||||
|
@ -1950,6 +1951,7 @@
|
||||||
<string name="ConversationUpdateItem_call_is_full">Call is full</string>
|
<string name="ConversationUpdateItem_call_is_full">Call is full</string>
|
||||||
<string name="ConversationUpdateItem_invite_friends">Invite friends</string>
|
<string name="ConversationUpdateItem_invite_friends">Invite friends</string>
|
||||||
<string name="ConversationUpdateItem_enable_call_notifications">Enable Call Notifications</string>
|
<string name="ConversationUpdateItem_enable_call_notifications">Enable Call Notifications</string>
|
||||||
|
<string name="ConversationUpdateItem_update_contact">Update contact</string>
|
||||||
<string name="ConversationUpdateItem_no_groups_in_common_review_requests_carefully">No groups in common. Review requests carefully.</string>
|
<string name="ConversationUpdateItem_no_groups_in_common_review_requests_carefully">No groups in common. Review requests carefully.</string>
|
||||||
<string name="ConversationUpdateItem_no_contacts_in_this_group_review_requests_carefully">No contacts in this group. Review requests carefully.</string>
|
<string name="ConversationUpdateItem_no_contacts_in_this_group_review_requests_carefully">No contacts in this group. Review requests carefully.</string>
|
||||||
<string name="ConversationUpdateItem_view">View</string>
|
<string name="ConversationUpdateItem_view">View</string>
|
||||||
|
@ -3505,7 +3507,7 @@
|
||||||
<string name="ChangeNumberEnterPhoneNumberFragment__new_phone_number">New phone number</string>
|
<string name="ChangeNumberEnterPhoneNumberFragment__new_phone_number">New phone number</string>
|
||||||
<string name="ChangeNumberEnterPhoneNumberFragment__the_phone_number_you_entered_doesnt_match_your_accounts">The phone number you entered doesn\'t match your account\'s.</string>
|
<string name="ChangeNumberEnterPhoneNumberFragment__the_phone_number_you_entered_doesnt_match_your_accounts">The phone number you entered doesn\'t match your account\'s.</string>
|
||||||
<string name="ChangeNumberEnterPhoneNumberFragment__you_must_specify_your_old_number_country_code">You must specify your old number\'s country code</string>
|
<string name="ChangeNumberEnterPhoneNumberFragment__you_must_specify_your_old_number_country_code">You must specify your old number\'s country code</string>
|
||||||
<string name="ChangeNumberEnterPhoneNumberFragment__you_must_specify_your_old_phone_number">You must specify your old number</string>
|
<string name="ChangeNumberEnterPhoneNumberFragment__you_must_specify_your_old_phone_number">You must specify your old phone number</string>
|
||||||
<string name="ChangeNumberEnterPhoneNumberFragment__you_must_specify_your_new_number_country_code">You must specify your new number\'s country code</string>
|
<string name="ChangeNumberEnterPhoneNumberFragment__you_must_specify_your_new_number_country_code">You must specify your new number\'s country code</string>
|
||||||
<string name="ChangeNumberEnterPhoneNumberFragment__you_must_specify_your_new_phone_number">You must specify your new phone number</string>
|
<string name="ChangeNumberEnterPhoneNumberFragment__you_must_specify_your_new_phone_number">You must specify your new phone number</string>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.thoughtcrime.securesms.migrations
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
|
||||||
|
class ApplicationMigrationsTest {
|
||||||
|
@Test
|
||||||
|
fun `ensure ApplicationMigration CURRENT_VERSION matches max version`() {
|
||||||
|
val fields: Array<Field> = ApplicationMigrations.Version::class.java.declaredFields
|
||||||
|
|
||||||
|
val maxField: Int? = fields.filter { Modifier.isStatic(it.modifiers) && it.type == Int::class.java }
|
||||||
|
.map { it.getInt(null) }
|
||||||
|
.maxOrNull()
|
||||||
|
|
||||||
|
assertEquals(ApplicationMigrations.CURRENT_VERSION, maxField)
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,8 +9,6 @@ package org.whispersystems.signalservice.api.account;
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
|
||||||
|
|
||||||
public class AccountAttributes {
|
public class AccountAttributes {
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
|
@ -134,16 +132,20 @@ public class AccountAttributes {
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private boolean announcementGroup;
|
private boolean announcementGroup;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private boolean changeNumber;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public Capabilities() {}
|
public Capabilities() {}
|
||||||
|
|
||||||
public Capabilities(boolean uuid, boolean gv2, boolean storage, boolean gv1Migration, boolean senderKey, boolean announcementGroup) {
|
public Capabilities(boolean uuid, boolean gv2, boolean storage, boolean gv1Migration, boolean senderKey, boolean announcementGroup, boolean changeNumber) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.gv2 = gv2;
|
this.gv2 = gv2;
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
this.gv1Migration = gv1Migration;
|
this.gv1Migration = gv1Migration;
|
||||||
this.senderKey = senderKey;
|
this.senderKey = senderKey;
|
||||||
this.announcementGroup = announcementGroup;
|
this.announcementGroup = announcementGroup;
|
||||||
|
this.changeNumber = changeNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUuid() {
|
public boolean isUuid() {
|
||||||
|
@ -169,5 +171,9 @@ public class AccountAttributes {
|
||||||
public boolean isAnnouncementGroup() {
|
public boolean isAnnouncementGroup() {
|
||||||
return announcementGroup;
|
return announcementGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isChangeNumber() {
|
||||||
|
return changeNumber;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,9 @@ public class SignalServiceProfile {
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private boolean announcementGroup;
|
private boolean announcementGroup;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private boolean changeNumber;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public Capabilities() {}
|
public Capabilities() {}
|
||||||
|
|
||||||
|
@ -149,6 +152,10 @@ public class SignalServiceProfile {
|
||||||
public boolean isAnnouncementGroup() {
|
public boolean isAnnouncementGroup() {
|
||||||
return announcementGroup;
|
return announcementGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isChangeNumber() {
|
||||||
|
return changeNumber;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProfileKeyCredentialResponse getProfileKeyCredentialResponse() {
|
public ProfileKeyCredentialResponse getProfileKeyCredentialResponse() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ public final class AccountAttributesTest {
|
||||||
"reglock1234",
|
"reglock1234",
|
||||||
new byte[10],
|
new byte[10],
|
||||||
false,
|
false,
|
||||||
new AccountAttributes.Capabilities(true, true, true, true, true, true),
|
new AccountAttributes.Capabilities(true, true, true, true, true, true, true),
|
||||||
false));
|
false));
|
||||||
assertEquals("{\"signalingKey\":\"skey\"," +
|
assertEquals("{\"signalingKey\":\"skey\"," +
|
||||||
"\"registrationId\":123," +
|
"\"registrationId\":123," +
|
||||||
|
@ -28,18 +28,18 @@ public final class AccountAttributesTest {
|
||||||
"\"unidentifiedAccessKey\":\"AAAAAAAAAAAAAA==\"," +
|
"\"unidentifiedAccessKey\":\"AAAAAAAAAAAAAA==\"," +
|
||||||
"\"unrestrictedUnidentifiedAccess\":false," +
|
"\"unrestrictedUnidentifiedAccess\":false," +
|
||||||
"\"discoverableByPhoneNumber\":false," +
|
"\"discoverableByPhoneNumber\":false," +
|
||||||
"\"capabilities\":{\"uuid\":true,\"storage\":true,\"senderKey\":true,\"announcementGroup\":true,\"gv2-3\":true,\"gv1-migration\":true}}", json);
|
"\"capabilities\":{\"uuid\":true,\"storage\":true,\"senderKey\":true,\"announcementGroup\":true,\"changeNumber\":true,\"gv2-3\":true,\"gv1-migration\":true}}", json);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void gv2_true() {
|
public void gv2_true() {
|
||||||
String json = JsonUtil.toJson(new AccountAttributes.Capabilities(false, true, false, false, false, false));
|
String json = JsonUtil.toJson(new AccountAttributes.Capabilities(false, true, false, false, false, false, false));
|
||||||
assertEquals("{\"uuid\":false,\"storage\":false,\"senderKey\":false,\"announcementGroup\":false,\"gv2-3\":true,\"gv1-migration\":false}", json);
|
assertEquals("{\"uuid\":false,\"storage\":false,\"senderKey\":false,\"announcementGroup\":false,\"changeNumber\":false,\"gv2-3\":true,\"gv1-migration\":false}", json);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void gv2_false() {
|
public void gv2_false() {
|
||||||
String json = JsonUtil.toJson(new AccountAttributes.Capabilities(false, false, false, false, false, false));
|
String json = JsonUtil.toJson(new AccountAttributes.Capabilities(false, false, false, false, false, false, false));
|
||||||
assertEquals("{\"uuid\":false,\"storage\":false,\"senderKey\":false,\"announcementGroup\":false,\"gv2-3\":false,\"gv1-migration\":false}", json);
|
assertEquals("{\"uuid\":false,\"storage\":false,\"senderKey\":false,\"announcementGroup\":false,\"changeNumber\":false,\"gv2-3\":false,\"gv1-migration\":false}", json);
|
||||||
}
|
}
|
||||||
}
|
}
|
Ładowanie…
Reference in New Issue