use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class GroupDescriptionDialog method onCreateDialog.
@Override
@NonNull
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
View dialogView = LayoutInflater.from(getContext()).inflate(R.layout.group_description_dialog, null, false);
String argumentTitle = requireArguments().getString(ARGUMENT_TITLE, null);
String argumentDescription = requireArguments().getString(ARGUMENT_DESCRIPTION, null);
GroupId argumentGroupId = ParcelableGroupId.get(requireArguments().getParcelable(ARGUMENT_GROUP_ID));
boolean linkify = requireArguments().getBoolean(ARGUMENT_LINKIFY, false);
LiveGroup liveGroup = argumentGroupId != null ? new LiveGroup(argumentGroupId) : null;
descriptionText = dialogView.findViewById(R.id.group_description_dialog_text);
descriptionText.setMovementMethod(LongClickMovementMethod.getInstance(requireContext()));
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext(), R.style.Signal_ThemeOverlay_Dialog_Rounded);
Dialog dialog = builder.setTitle(TextUtils.isEmpty(argumentTitle) ? getString(R.string.GroupDescriptionDialog__group_description) : argumentTitle).setView(dialogView).setPositiveButton(android.R.string.ok, null).create();
if (argumentDescription != null) {
GroupDescriptionUtil.setText(requireContext(), descriptionText, argumentDescription, linkify, null);
} else if (liveGroup != null) {
liveGroup.getDescription().observe(this, d -> GroupDescriptionUtil.setText(requireContext(), descriptionText, d, linkify, null));
}
if (TextUtils.isEmpty(argumentTitle) && liveGroup != null) {
liveGroup.getTitle().observe(this, dialog::setTitle);
}
return dialog;
}
use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class SendRetryReceiptJob method onRun.
@Override
protected void onRun() throws Exception {
Recipient recipient = Recipient.resolved(recipientId);
if (recipient.isUnregistered()) {
Log.w(TAG, recipient.getId() + " not registered!");
return;
}
SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient);
Optional<UnidentifiedAccessPair> access = UnidentifiedAccessUtil.getAccessFor(context, recipient);
Optional<byte[]> group = groupId.transform(GroupId::getDecodedId);
Log.i(TAG, "Sending retry receipt for " + errorMessage.getTimestamp() + " to " + recipientId + ", device: " + errorMessage.getDeviceId());
ApplicationDependencies.getSignalServiceMessageSender().sendRetryReceipt(address, access, group, errorMessage);
}
use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class RemoteDeleteSendJob method deliver.
@NonNull
private List<Recipient> deliver(@NonNull Recipient conversationRecipient, @NonNull List<Recipient> destinations, long targetSentTimestamp) throws IOException, UntrustedIdentityException {
SignalServiceDataMessage.Builder dataMessageBuilder = SignalServiceDataMessage.newBuilder().withTimestamp(System.currentTimeMillis()).withRemoteDelete(new SignalServiceDataMessage.RemoteDelete(targetSentTimestamp));
if (conversationRecipient.isGroup()) {
GroupUtil.setDataMessageGroupContext(context, dataMessageBuilder, conversationRecipient.requireGroupId().requirePush());
}
SignalServiceDataMessage dataMessage = dataMessageBuilder.build();
List<SendMessageResult> results = GroupSendUtil.sendResendableDataMessage(context, conversationRecipient.getGroupId().transform(GroupId::requireV2).orNull(), destinations, false, ContentHint.RESENDABLE, new MessageId(messageId, isMms), dataMessage);
return GroupSendJobHelper.getCompletedSends(destinations, results);
}
use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class ResendMessageJob method onRun.
@Override
protected void onRun() throws Exception {
if (SignalStore.internalValues().delayResends()) {
Log.w(TAG, "Delaying resend by 10 sec because of an internal preference.");
ThreadUtil.sleep(10000);
}
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
Recipient recipient = Recipient.resolved(recipientId);
if (recipient.isUnregistered()) {
Log.w(TAG, recipient.getId() + " is unregistered!");
return;
}
SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient);
Optional<UnidentifiedAccessPair> access = UnidentifiedAccessUtil.getAccessFor(context, recipient);
Content contentToSend = content;
if (distributionId != null) {
Optional<GroupRecord> groupRecord = SignalDatabase.groups().getGroupByDistributionId(distributionId);
if (!groupRecord.isPresent()) {
Log.w(TAG, "Could not find a matching group for the distributionId! Skipping message send.");
return;
} else if (!groupRecord.get().getMembers().contains(recipientId)) {
Log.w(TAG, "The target user is no longer in the group! Skipping message send.");
return;
}
SenderKeyDistributionMessage senderKeyDistributionMessage = messageSender.getOrCreateNewGroupSession(distributionId);
ByteString distributionBytes = ByteString.copyFrom(senderKeyDistributionMessage.serialize());
contentToSend = contentToSend.toBuilder().setSenderKeyDistributionMessage(distributionBytes).build();
}
SendMessageResult result = messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.fromNullable(groupId).transform(GroupId::getDecodedId));
if (result.isSuccess() && distributionId != null) {
List<SignalProtocolAddress> addresses = result.getSuccess().getDevices().stream().map(device -> recipient.requireServiceId().toProtocolAddress(device)).collect(Collectors.toList());
ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses);
}
}
use of org.thoughtcrime.securesms.groups.GroupId in project Signal-Android by WhisperSystems.
the class LinkPreviewRepository method fetchGroupLinkPreview.
private static RequestController fetchGroupLinkPreview(@NonNull Context context, @NonNull String groupUrl, @NonNull Callback callback) {
SignalExecutors.UNBOUNDED.execute(() -> {
try {
GroupInviteLinkUrl groupInviteLinkUrl = GroupInviteLinkUrl.fromUri(groupUrl);
if (groupInviteLinkUrl == null) {
throw new AssertionError();
}
GroupMasterKey groupMasterKey = groupInviteLinkUrl.getGroupMasterKey();
GroupId.V2 groupId = GroupId.v2(groupMasterKey);
Optional<GroupDatabase.GroupRecord> group = SignalDatabase.groups().getGroup(groupId);
if (group.isPresent()) {
Log.i(TAG, "Creating preview for locally available group");
GroupDatabase.GroupRecord groupRecord = group.get();
String title = groupRecord.getTitle();
int memberCount = groupRecord.getMembers().size();
String description = getMemberCountDescription(context, memberCount);
Optional<Attachment> thumbnail = Optional.absent();
if (AvatarHelper.hasAvatar(context, groupRecord.getRecipientId())) {
Recipient recipient = Recipient.resolved(groupRecord.getRecipientId());
Bitmap bitmap = AvatarUtil.loadIconBitmapSquareNoCache(context, recipient, 512, 512);
thumbnail = bitmapToAttachment(bitmap, Bitmap.CompressFormat.WEBP, MediaUtil.IMAGE_WEBP);
}
callback.onSuccess(new LinkPreview(groupUrl, title, description, 0, thumbnail));
} else {
Log.i(TAG, "Group is not locally available for preview generation, fetching from server");
DecryptedGroupJoinInfo joinInfo = GroupManager.getGroupJoinInfoFromServer(context, groupMasterKey, groupInviteLinkUrl.getPassword());
String description = getMemberCountDescription(context, joinInfo.getMemberCount());
Optional<Attachment> thumbnail = Optional.absent();
byte[] avatarBytes = AvatarGroupsV2DownloadJob.downloadGroupAvatarBytes(context, groupMasterKey, joinInfo.getAvatar());
if (avatarBytes != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length);
thumbnail = bitmapToAttachment(bitmap, Bitmap.CompressFormat.WEBP, MediaUtil.IMAGE_WEBP);
if (bitmap != null)
bitmap.recycle();
}
callback.onSuccess(new LinkPreview(groupUrl, joinInfo.getTitle(), description, 0, thumbnail));
}
} catch (ExecutionException | InterruptedException | IOException | VerificationFailedException e) {
Log.w(TAG, "Failed to fetch group link preview.", e);
callback.onError(Error.PREVIEW_NOT_AVAILABLE);
} catch (GroupInviteLinkUrl.InvalidGroupLinkException | GroupInviteLinkUrl.UnknownGroupLinkVersionException e) {
Log.w(TAG, "Bad group link.", e);
callback.onError(Error.PREVIEW_NOT_AVAILABLE);
} catch (GroupLinkNotActiveException e) {
Log.w(TAG, "Group link not active.", e);
callback.onError(Error.GROUP_LINK_INACTIVE);
}
});
return () -> Log.i(TAG, "Cancelled group link preview fetch -- no effect.");
}
Aggregations