use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.
the class GroupDatabase method removeUnmigratedV1Members.
/**
* Removes the specified members from the list of 'unmigrated V1 members' -- the list of members
* that were either dropped or had to be invited when migrating the group from V1->V2.
*/
public void removeUnmigratedV1Members(@NonNull GroupId.V2 id, @NonNull List<RecipientId> toRemove) {
Optional<GroupRecord> group = getGroup(id);
if (!group.isPresent()) {
Log.w(TAG, "Couldn't find the group!", new Throwable());
return;
}
List<RecipientId> newUnmigrated = group.get().getUnmigratedV1Members();
newUnmigrated.removeAll(toRemove);
ContentValues values = new ContentValues();
values.put(UNMIGRATED_V1_MEMBERS, newUnmigrated.isEmpty() ? null : RecipientId.toSerializedList(newUnmigrated));
databaseHelper.getSignalWritableDatabase().update(TABLE_NAME, values, GROUP_ID + " = ?", SqlUtil.buildArgs(id));
Recipient.live(Recipient.externalGroupExact(context, id).getId()).refresh();
}
use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.
the class GroupDatabase method create.
/**
* @param groupMasterKey null for V1, must be non-null for V2 (presence dictates group version).
*/
private void create(@NonNull GroupId groupId, @Nullable String title, @NonNull Collection<RecipientId> memberCollection, @Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay, @Nullable GroupMasterKey groupMasterKey, @Nullable DecryptedGroup groupState) {
RecipientDatabase recipientDatabase = SignalDatabase.recipients();
RecipientId groupRecipientId = recipientDatabase.getOrInsertFromGroupId(groupId);
List<RecipientId> members = new ArrayList<>(new HashSet<>(memberCollection));
Collections.sort(members);
ContentValues contentValues = new ContentValues();
contentValues.put(RECIPIENT_ID, groupRecipientId.serialize());
contentValues.put(GROUP_ID, groupId.toString());
contentValues.put(TITLE, title);
contentValues.put(MEMBERS, RecipientId.toSerializedList(members));
if (avatar != null) {
contentValues.put(AVATAR_ID, avatar.getRemoteId().getV2().get());
contentValues.put(AVATAR_KEY, avatar.getKey());
contentValues.put(AVATAR_CONTENT_TYPE, avatar.getContentType());
contentValues.put(AVATAR_DIGEST, avatar.getDigest().orNull());
} else {
contentValues.put(AVATAR_ID, 0);
}
contentValues.put(AVATAR_RELAY, relay);
contentValues.put(TIMESTAMP, System.currentTimeMillis());
if (groupId.isV2()) {
contentValues.put(ACTIVE, groupState != null && gv2GroupActive(groupState) ? 1 : 0);
contentValues.put(DISTRIBUTION_ID, DistributionId.create().toString());
} else if (groupId.isV1()) {
contentValues.put(ACTIVE, 1);
contentValues.put(EXPECTED_V2_ID, groupId.requireV1().deriveV2MigrationGroupId().toString());
} else {
contentValues.put(ACTIVE, 1);
}
contentValues.put(MMS, groupId.isMms());
List<RecipientId> groupMembers = members;
if (groupMasterKey != null) {
if (groupState == null) {
throw new AssertionError("V2 master key but no group state");
}
groupId.requireV2();
groupMembers = getV2GroupMembers(groupState, true);
contentValues.put(V2_MASTER_KEY, groupMasterKey.serialize());
contentValues.put(V2_REVISION, groupState.getRevision());
contentValues.put(V2_DECRYPTED_GROUP, groupState.toByteArray());
contentValues.put(MEMBERS, RecipientId.toSerializedList(groupMembers));
} else {
if (groupId.isV2()) {
throw new AssertionError("V2 group id but no master key");
}
}
databaseHelper.getSignalWritableDatabase().insert(TABLE_NAME, null, contentValues);
if (groupState != null && groupState.hasDisappearingMessagesTimer()) {
recipientDatabase.setExpireMessages(groupRecipientId, groupState.getDisappearingMessagesTimer().getDuration());
}
if (groupMembers != null && (groupId.isMms() || Recipient.resolved(groupRecipientId).isProfileSharing())) {
recipientDatabase.setHasGroupsInCommon(groupMembers);
}
Recipient.live(groupRecipientId).refresh();
notifyConversationListListeners();
}
use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.
the class NotificationChannels method ensureCustomChannelConsistency.
@TargetApi(26)
@WorkerThread
public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) {
if (!supported()) {
return;
}
Log.d(TAG, "ensureCustomChannelConsistency()");
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
RecipientDatabase db = SignalDatabase.recipients();
List<Recipient> customRecipients = new ArrayList<>();
Set<String> customChannelIds = new HashSet<>();
try (RecipientDatabase.RecipientReader reader = db.getRecipientsWithNotificationChannels()) {
Recipient recipient;
while ((recipient = reader.getNext()) != null) {
customRecipients.add(recipient);
customChannelIds.add(recipient.getNotificationChannel());
}
}
Set<String> existingChannelIds = Stream.of(notificationManager.getNotificationChannels()).map(NotificationChannel::getId).collect(Collectors.toSet());
for (NotificationChannel existingChannel : notificationManager.getNotificationChannels()) {
if ((existingChannel.getId().startsWith(CONTACT_PREFIX) || existingChannel.getId().startsWith(MESSAGES_PREFIX)) && Build.VERSION.SDK_INT >= CONVERSATION_SUPPORT_VERSION && existingChannel.getConversationId() != null) {
if (customChannelIds.contains(existingChannel.getId())) {
continue;
}
RecipientId id = ConversationUtil.getRecipientId(existingChannel.getConversationId());
if (id != null) {
Log.i(TAG, "Consistency: Conversation channel created outside of app, update " + id + " to use '" + existingChannel.getId() + "'");
db.setNotificationChannel(id, existingChannel.getId());
} else {
Log.i(TAG, "Consistency: Conversation channel created outside of app with no matching recipient, deleting channel '" + existingChannel.getId() + "'");
notificationManager.deleteNotificationChannel(existingChannel.getId());
}
} else if (existingChannel.getId().startsWith(CONTACT_PREFIX) && !customChannelIds.contains(existingChannel.getId())) {
Log.i(TAG, "Consistency: Deleting channel '" + existingChannel.getId() + "' because the DB has no record of it.");
notificationManager.deleteNotificationChannel(existingChannel.getId());
} else if (existingChannel.getId().startsWith(MESSAGES_PREFIX) && !existingChannel.getId().equals(getMessagesChannel(context))) {
Log.i(TAG, "Consistency: Deleting channel '" + existingChannel.getId() + "' because it's out of date.");
notificationManager.deleteNotificationChannel(existingChannel.getId());
}
}
for (Recipient customRecipient : customRecipients) {
if (!existingChannelIds.contains(customRecipient.getNotificationChannel())) {
Log.i(TAG, "Consistency: Removing custom channel '" + customRecipient.getNotificationChannel() + "' because the system doesn't have it.");
db.setNotificationChannel(customRecipient.getId(), null);
}
}
}
use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.
the class MarkReadReceiver method process.
public static void process(@NonNull Context context, @NonNull List<MarkedMessageInfo> markedReadMessages) {
if (markedReadMessages.isEmpty())
return;
List<SyncMessageId> syncMessageIds = Stream.of(markedReadMessages).map(MarkedMessageInfo::getSyncMessageId).toList();
List<ExpirationInfo> mmsExpirationInfo = Stream.of(markedReadMessages).map(MarkedMessageInfo::getExpirationInfo).filter(ExpirationInfo::isMms).filter(info -> info.getExpiresIn() > 0 && info.getExpireStarted() <= 0).toList();
List<ExpirationInfo> smsExpirationInfo = Stream.of(markedReadMessages).map(MarkedMessageInfo::getExpirationInfo).filterNot(ExpirationInfo::isMms).filter(info -> info.getExpiresIn() > 0 && info.getExpireStarted() <= 0).toList();
scheduleDeletion(context, smsExpirationInfo, mmsExpirationInfo);
MultiDeviceReadUpdateJob.enqueue(syncMessageIds);
Map<Long, List<MarkedMessageInfo>> threadToInfo = Stream.of(markedReadMessages).collect(Collectors.groupingBy(MarkedMessageInfo::getThreadId));
Stream.of(threadToInfo).forEach(threadToInfoEntry -> {
Map<RecipientId, List<MarkedMessageInfo>> recipientIdToInfo = Stream.of(threadToInfoEntry.getValue()).map(info -> info).collect(Collectors.groupingBy(info -> info.getSyncMessageId().getRecipientId()));
Stream.of(recipientIdToInfo).forEach(entry -> {
long threadId = threadToInfoEntry.getKey();
RecipientId recipientId = entry.getKey();
List<MarkedMessageInfo> infos = entry.getValue();
SendReadReceiptJob.enqueue(threadId, recipientId, infos);
});
});
}
use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.
the class QuoteId method deserialize.
@Nullable
public static QuoteId deserialize(@NonNull Context context, @NonNull String serialized) {
try {
JSONObject json = new JSONObject(serialized);
RecipientId id = json.has(AUTHOR) ? RecipientId.from(json.getString(AUTHOR)) : Recipient.external(context, json.getString(AUTHOR_DEPRECATED)).getId();
return new QuoteId(json.getLong(ID), id);
} catch (JSONException e) {
Log.e(TAG, "Failed to deserialize from json", e);
return null;
}
}
Aggregations