use of org.thoughtcrime.securesms.util.concurrent.SettableFuture in project Signal-Android by WhisperSystems.
the class ConversationParentFragment method initializeDraftFromDatabase.
private ListenableFuture<Boolean> initializeDraftFromDatabase() {
SettableFuture<Boolean> future = new SettableFuture<>();
final Context context = requireContext().getApplicationContext();
new AsyncTask<Void, Void, Pair<Drafts, CharSequence>>() {
@Override
protected Pair<Drafts, CharSequence> doInBackground(Void... params) {
DraftDatabase draftDatabase = SignalDatabase.drafts();
Drafts results = draftDatabase.getDrafts(threadId);
Draft mentionsDraft = results.getDraftOfType(Draft.MENTION);
Spannable updatedText = null;
if (mentionsDraft != null) {
String text = results.getDraftOfType(Draft.TEXT).getValue();
List<Mention> mentions = MentionUtil.bodyRangeListToMentions(context, Base64.decodeOrThrow(mentionsDraft.getValue()));
UpdatedBodyAndMentions updated = MentionUtil.updateBodyAndMentionsWithDisplayNames(context, text, mentions);
updatedText = new SpannableString(updated.getBody());
MentionAnnotation.setMentionAnnotations(updatedText, updated.getMentions());
}
draftDatabase.clearDrafts(threadId);
return new Pair<>(results, updatedText);
}
@Override
protected void onPostExecute(Pair<Drafts, CharSequence> draftsWithUpdatedMentions) {
Drafts drafts = Objects.requireNonNull(draftsWithUpdatedMentions.first());
CharSequence updatedText = draftsWithUpdatedMentions.second();
if (drafts.isEmpty()) {
future.set(false);
updateToggleButtonState();
return;
}
AtomicInteger draftsRemaining = new AtomicInteger(drafts.size());
AtomicBoolean success = new AtomicBoolean(false);
ListenableFuture.Listener<Boolean> listener = new AssertedSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
success.compareAndSet(false, result);
if (draftsRemaining.decrementAndGet() <= 0) {
future.set(success.get());
}
}
};
for (Draft draft : drafts) {
try {
switch(draft.getType()) {
case Draft.TEXT:
composeText.setText(updatedText == null ? draft.getValue() : updatedText);
listener.onSuccess(true);
break;
case Draft.LOCATION:
attachmentManager.setLocation(SignalPlace.deserialize(draft.getValue()), getCurrentMediaConstraints()).addListener(listener);
break;
case Draft.IMAGE:
setMedia(Uri.parse(draft.getValue()), MediaType.IMAGE).addListener(listener);
break;
case Draft.AUDIO:
setMedia(Uri.parse(draft.getValue()), MediaType.AUDIO).addListener(listener);
break;
case Draft.VIDEO:
setMedia(Uri.parse(draft.getValue()), MediaType.VIDEO).addListener(listener);
break;
case Draft.QUOTE:
SettableFuture<Boolean> quoteResult = new SettableFuture<>();
new QuoteRestorationTask(draft.getValue(), quoteResult).execute();
quoteResult.addListener(listener);
break;
case Draft.VOICE_NOTE:
draftViewModel.setVoiceNoteDraft(recipient.getId(), draft);
break;
}
} catch (IOException e) {
Log.w(TAG, e);
}
}
updateToggleButtonState();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return future;
}
use of org.thoughtcrime.securesms.util.concurrent.SettableFuture in project Signal-Android by WhisperSystems.
the class ConversationParentFragment method initializeDraft.
// /// Initializers
private ListenableFuture<Boolean> initializeDraft(@NonNull ConversationIntents.Args args) {
final SettableFuture<Boolean> result = new SettableFuture<>();
final CharSequence draftText = args.getDraftText();
final Uri draftMedia = requireActivity().getIntent().getData();
final String draftContentType = requireActivity().getIntent().getType();
final MediaType draftMediaType = MediaType.from(draftContentType);
final List<Media> mediaList = args.getMedia();
final StickerLocator stickerLocator = args.getStickerLocator();
final boolean borderless = args.isBorderless();
if (stickerLocator != null && draftMedia != null) {
Log.d(TAG, "Handling shared sticker.");
sendSticker(stickerLocator, Objects.requireNonNull(draftContentType), draftMedia, 0, true);
return new SettableFuture<>(false);
}
if (draftMedia != null && draftContentType != null && borderless) {
SimpleTask.run(getLifecycle(), () -> getKeyboardImageDetails(draftMedia), details -> sendKeyboardImage(draftMedia, draftContentType, details));
return new SettableFuture<>(false);
}
if (!Util.isEmpty(mediaList)) {
Log.d(TAG, "Handling shared Media.");
Intent sendIntent = MediaSelectionActivity.editor(requireContext(), sendButton.getSelectedTransport(), mediaList, recipient.getId(), draftText);
startActivityForResult(sendIntent, MEDIA_SENDER);
return new SettableFuture<>(false);
}
if (draftText != null) {
composeText.setText("");
composeText.append(draftText);
result.set(true);
}
if (draftMedia != null && draftMediaType != null) {
Log.d(TAG, "Handling shared Data.");
return setMedia(draftMedia, draftMediaType);
}
if (draftText == null && draftMedia == null && draftMediaType == null) {
return initializeDraftFromDatabase();
} else {
updateToggleButtonState();
result.set(false);
}
return result;
}
use of org.thoughtcrime.securesms.util.concurrent.SettableFuture in project Signal-Android by WhisperSystems.
the class ConversationParentFragment method sendMediaMessage.
private ListenableFuture<Void> sendMediaMessage(@NonNull RecipientId recipientId, final boolean forceSms, @NonNull String body, SlideDeck slideDeck, QuoteModel quote, List<Contact> contacts, List<LinkPreview> previews, List<Mention> mentions, final long expiresIn, final boolean viewOnce, final int subscriptionId, final boolean initiating, final boolean clearComposeBox, @Nullable final String metricId) {
if (!isDefaultSms && (!isSecureText || forceSms) && recipient.get().hasSmsAddress()) {
showDefaultSmsPrompt();
return new SettableFuture<>(null);
}
final boolean sendPush = (isSecureText && !forceSms) || recipient.get().isServiceIdOnly();
final long thread = this.threadId;
if (sendPush) {
MessageUtil.SplitResult splitMessage = MessageUtil.getSplitMessage(requireContext(), body, sendButton.getSelectedTransport().calculateCharacters(body).maxPrimaryMessageSize);
body = splitMessage.getBody();
if (splitMessage.getTextSlide().isPresent()) {
slideDeck.addSlide(splitMessage.getTextSlide().get());
}
}
OutgoingMediaMessage outgoingMessageCandidate = new OutgoingMediaMessage(Recipient.resolved(recipientId), slideDeck, body, System.currentTimeMillis(), subscriptionId, expiresIn, viewOnce, distributionType, quote, contacts, previews, mentions);
final SettableFuture<Void> future = new SettableFuture<>();
final Context context = requireContext().getApplicationContext();
final OutgoingMediaMessage outgoingMessage;
if (sendPush) {
outgoingMessage = new OutgoingSecureMediaMessage(outgoingMessageCandidate);
ApplicationDependencies.getTypingStatusSender().onTypingStopped(thread);
} else {
outgoingMessage = outgoingMessageCandidate;
}
Permissions.with(this).request(Manifest.permission.SEND_SMS, Manifest.permission.READ_SMS).ifNecessary(!sendPush).withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_needs_sms_permission_in_order_to_send_an_sms)).onAllGranted(() -> {
if (clearComposeBox) {
inputPanel.clearQuote();
attachmentManager.clear(glideRequests, false);
silentlySetComposeText("");
}
final long id = fragment.stageOutgoingMessage(outgoingMessage);
SimpleTask.run(() -> {
return MessageSender.send(context, outgoingMessage, thread, forceSms, metricId, null);
}, result -> {
sendComplete(result);
future.set(null);
});
}).onAnyDenied(() -> future.set(null)).execute();
return future;
}
use of org.thoughtcrime.securesms.util.concurrent.SettableFuture in project Signal-Android by WhisperSystems.
the class ConversationParentFragment method initializeIdentityRecords.
private ListenableFuture<Boolean> initializeIdentityRecords() {
final SettableFuture<Boolean> future = new SettableFuture<>();
final Context context = requireContext().getApplicationContext();
if (SignalStore.account().getAci() == null || SignalStore.account().getPni() == null) {
Log.w(TAG, "Not registered! Skipping initializeIdentityRecords()");
future.set(false);
return future;
}
new AsyncTask<Recipient, Void, Pair<IdentityRecordList, String>>() {
@Override
@NonNull
protected Pair<IdentityRecordList, String> doInBackground(Recipient... params) {
List<Recipient> recipients;
if (params[0].isGroup()) {
recipients = SignalDatabase.groups().getGroupMembers(params[0].requireGroupId(), GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
} else {
recipients = Collections.singletonList(params[0]);
}
long startTime = System.currentTimeMillis();
IdentityRecordList identityRecordList = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecords(recipients);
Log.i(TAG, String.format(Locale.US, "Loaded %d identities in %d ms", recipients.size(), System.currentTimeMillis() - startTime));
String message = null;
if (identityRecordList.isUnverified()) {
message = IdentityUtil.getUnverifiedBannerDescription(context, identityRecordList.getUnverifiedRecipients());
}
return new Pair<>(identityRecordList, message);
}
@Override
protected void onPostExecute(@NonNull Pair<IdentityRecordList, String> result) {
Log.i(TAG, "Got identity records: " + result.first().isUnverified());
identityRecords = result.first();
if (result.second() != null) {
Log.d(TAG, "Replacing banner...");
unverifiedBannerView.get().display(result.second(), result.first().getUnverifiedRecords(), new UnverifiedClickedListener(), new UnverifiedDismissedListener());
} else if (unverifiedBannerView.resolved()) {
Log.d(TAG, "Clearing banner...");
unverifiedBannerView.get().hide();
}
titleView.setVerified(isSecureText && identityRecords.isVerified());
future.set(true);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, recipient.get());
return future;
}
use of org.thoughtcrime.securesms.util.concurrent.SettableFuture in project Signal-Android by WhisperSystems.
the class IdentityUtil method getRemoteIdentityKey.
public static ListenableFuture<Optional<IdentityRecord>> getRemoteIdentityKey(final Context context, final Recipient recipient) {
final SettableFuture<Optional<IdentityRecord>> future = new SettableFuture<>();
final RecipientId recipientId = recipient.getId();
SimpleTask.run(SignalExecutors.BOUNDED, () -> ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipientId), future::set);
return future;
}
Aggregations