Search in sources :

Example 6 with Draft

use of org.thoughtcrime.securesms.database.DraftDatabase.Draft in project mollyim-android by mollyim.

the class ConversationParentFragment method sendMessage.

private void sendMessage(@Nullable String metricId) {
    if (inputPanel.isRecordingInLockedMode()) {
        inputPanel.releaseRecordingLock();
        return;
    }
    Draft voiceNote = draftViewModel.getVoiceNoteDraft();
    if (voiceNote != null) {
        AudioSlide audioSlide = AudioSlide.createFromVoiceNoteDraft(requireContext(), voiceNote);
        sendVoiceNote(Objects.requireNonNull(audioSlide.getUri()), audioSlide.getFileSize());
        draftViewModel.clearVoiceNoteDraft();
        return;
    }
    try {
        Recipient recipient = getRecipient();
        if (recipient == null) {
            throw new RecipientFormattingException("Badly formatted");
        }
        String message = getMessage();
        TransportOption transport = sendButton.getSelectedTransport();
        boolean forceSms = (recipient.isForceSmsSelection() || sendButton.isManualSelection()) && transport.isSms();
        int subscriptionId = sendButton.getSelectedTransport().getSimSubscriptionId().or(-1);
        long expiresIn = TimeUnit.SECONDS.toMillis(recipient.getExpiresInSeconds());
        boolean initiating = threadId == -1;
        boolean needsSplit = !transport.isSms() && message.length() > transport.calculateCharacters(message).maxPrimaryMessageSize;
        boolean isMediaMessage = attachmentManager.isAttachmentPresent() || recipient.isGroup() || recipient.getEmail().isPresent() || inputPanel.getQuote().isPresent() || composeText.hasMentions() || linkPreviewViewModel.hasLinkPreview() || needsSplit;
        Log.i(TAG, "[sendMessage] recipient: " + recipient.getId() + ", threadId: " + threadId + ",  forceSms: " + forceSms + ", isManual: " + sendButton.isManualSelection());
        if (!forceSms && (identityRecords.isUnverified(true) || identityRecords.isUntrusted(true))) {
            handleRecentSafetyNumberChange();
        } else if (isMediaMessage) {
            sendMediaMessage(forceSms, expiresIn, false, subscriptionId, initiating, metricId);
        } else {
            sendTextMessage(forceSms, expiresIn, subscriptionId, initiating, metricId);
        }
    } catch (RecipientFormattingException ex) {
        Toast.makeText(requireContext(), R.string.ConversationActivity_recipient_is_not_a_valid_sms_or_email_address_exclamation, Toast.LENGTH_LONG).show();
        Log.w(TAG, ex);
    } catch (InvalidMessageException ex) {
        Toast.makeText(requireContext(), R.string.ConversationActivity_message_is_empty_exclamation, Toast.LENGTH_SHORT).show();
        Log.w(TAG, ex);
    }
}
Also used : TransportOption(org.thoughtcrime.securesms.TransportOption) VoiceNoteDraft(org.thoughtcrime.securesms.components.voice.VoiceNoteDraft) Draft(org.thoughtcrime.securesms.database.DraftDatabase.Draft) InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) AudioSlide(org.thoughtcrime.securesms.mms.AudioSlide) LiveRecipient(org.thoughtcrime.securesms.recipients.LiveRecipient) Recipient(org.thoughtcrime.securesms.recipients.Recipient) SpannableString(android.text.SpannableString) RecipientFormattingException(org.thoughtcrime.securesms.recipients.RecipientFormattingException) SuppressLint(android.annotation.SuppressLint)

Example 7 with Draft

use of org.thoughtcrime.securesms.database.DraftDatabase.Draft in project mollyim-android by mollyim.

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;
}
Also used : SettableFuture(org.thoughtcrime.securesms.util.concurrent.SettableFuture) EmojiEventListener(org.thoughtcrime.securesms.components.emoji.EmojiEventListener) OnFocusChangeListener(android.view.View.OnFocusChangeListener) OnKeyListener(android.view.View.OnKeyListener) StickerEventListener(org.thoughtcrime.securesms.stickers.StickerEventListener) AssertedSuccessListener(org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener) OnKeyboardShownListener(org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout.OnKeyboardShownListener) OnClickListener(android.view.View.OnClickListener) DraftDatabase(org.thoughtcrime.securesms.database.DraftDatabase) SpannableString(android.text.SpannableString) ArrayList(java.util.ArrayList) IdentityRecordList(org.thoughtcrime.securesms.database.identity.IdentityRecordList) List(java.util.List) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Pair(org.whispersystems.libsignal.util.Pair) Context(android.content.Context) UpdatedBodyAndMentions(org.thoughtcrime.securesms.database.MentionUtil.UpdatedBodyAndMentions) IOException(java.io.IOException) Drafts(org.thoughtcrime.securesms.database.DraftDatabase.Drafts) SpannableString(android.text.SpannableString) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) VoiceNoteDraft(org.thoughtcrime.securesms.components.voice.VoiceNoteDraft) Draft(org.thoughtcrime.securesms.database.DraftDatabase.Draft) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Spannable(android.text.Spannable)

Example 8 with Draft

use of org.thoughtcrime.securesms.database.DraftDatabase.Draft in project mollyim-android by mollyim.

the class ConversationParentFragment method saveDraft.

protected ListenableFuture<Long> saveDraft() {
    final SettableFuture<Long> future = new SettableFuture<>();
    if (this.recipient == null) {
        future.set(threadId);
        return future;
    }
    final Context context = requireContext().getApplicationContext();
    final Drafts drafts = getDraftsForCurrentState();
    final long thisThreadId = this.threadId;
    final RecipientId recipientId = this.recipient.getId();
    final int thisDistributionType = this.distributionType;
    final ListenableFuture<VoiceNoteDraft> voiceNoteDraftFuture = draftViewModel.consumeVoiceNoteDraftFuture();
    new AsyncTask<Long, Void, Long>() {

        @Override
        protected Long doInBackground(Long... params) {
            if (voiceNoteDraftFuture != null) {
                try {
                    Draft voiceNoteDraft = voiceNoteDraftFuture.get().asDraft();
                    draftViewModel.setVoiceNoteDraft(recipientId, voiceNoteDraft);
                    drafts.add(voiceNoteDraft);
                } catch (ExecutionException | InterruptedException e) {
                    Log.w(TAG, "Could not extract voice note draft data.", e);
                }
            }
            ThreadDatabase threadDatabase = SignalDatabase.threads();
            DraftDatabase draftDatabase = SignalDatabase.drafts();
            long threadId = params[0];
            if (drafts.size() > 0) {
                if (threadId == -1)
                    threadId = threadDatabase.getOrCreateThreadIdFor(getRecipient(), thisDistributionType);
                draftDatabase.replaceDrafts(threadId, drafts);
                threadDatabase.updateSnippet(threadId, drafts.getSnippet(context), drafts.getUriSnippet(), System.currentTimeMillis(), Types.BASE_DRAFT_TYPE, true);
            } else if (threadId > 0) {
                threadDatabase.update(threadId, false);
            }
            if (drafts.isEmpty()) {
                draftDatabase.clearDrafts(threadId);
            }
            return threadId;
        }

        @Override
        protected void onPostExecute(Long result) {
            future.set(result);
        }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, thisThreadId);
    return future;
}
Also used : SettableFuture(org.thoughtcrime.securesms.util.concurrent.SettableFuture) Context(android.content.Context) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) DraftDatabase(org.thoughtcrime.securesms.database.DraftDatabase) VoiceNoteDraft(org.thoughtcrime.securesms.components.voice.VoiceNoteDraft) ThreadDatabase(org.thoughtcrime.securesms.database.ThreadDatabase) SuppressLint(android.annotation.SuppressLint) Drafts(org.thoughtcrime.securesms.database.DraftDatabase.Drafts) VoiceNoteDraft(org.thoughtcrime.securesms.components.voice.VoiceNoteDraft) Draft(org.thoughtcrime.securesms.database.DraftDatabase.Draft)

Example 9 with Draft

use of org.thoughtcrime.securesms.database.DraftDatabase.Draft 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;
}
Also used : SettableFuture(org.thoughtcrime.securesms.util.concurrent.SettableFuture) EmojiEventListener(org.thoughtcrime.securesms.components.emoji.EmojiEventListener) OnFocusChangeListener(android.view.View.OnFocusChangeListener) OnKeyListener(android.view.View.OnKeyListener) StickerEventListener(org.thoughtcrime.securesms.stickers.StickerEventListener) AssertedSuccessListener(org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener) OnKeyboardShownListener(org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout.OnKeyboardShownListener) OnClickListener(android.view.View.OnClickListener) DraftDatabase(org.thoughtcrime.securesms.database.DraftDatabase) SpannableString(android.text.SpannableString) ArrayList(java.util.ArrayList) IdentityRecordList(org.thoughtcrime.securesms.database.identity.IdentityRecordList) List(java.util.List) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Pair(org.whispersystems.libsignal.util.Pair) Context(android.content.Context) UpdatedBodyAndMentions(org.thoughtcrime.securesms.database.MentionUtil.UpdatedBodyAndMentions) IOException(java.io.IOException) Drafts(org.thoughtcrime.securesms.database.DraftDatabase.Drafts) SpannableString(android.text.SpannableString) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) VoiceNoteDraft(org.thoughtcrime.securesms.components.voice.VoiceNoteDraft) Draft(org.thoughtcrime.securesms.database.DraftDatabase.Draft) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Spannable(android.text.Spannable)

Example 10 with Draft

use of org.thoughtcrime.securesms.database.DraftDatabase.Draft in project Signal-Android by signalapp.

the class ConversationParentFragment method saveDraft.

protected ListenableFuture<Long> saveDraft() {
    final SettableFuture<Long> future = new SettableFuture<>();
    if (this.recipient == null) {
        future.set(threadId);
        return future;
    }
    final Context context = requireContext().getApplicationContext();
    final Drafts drafts = getDraftsForCurrentState();
    final long thisThreadId = this.threadId;
    final RecipientId recipientId = this.recipient.getId();
    final int thisDistributionType = this.distributionType;
    final ListenableFuture<VoiceNoteDraft> voiceNoteDraftFuture = draftViewModel.consumeVoiceNoteDraftFuture();
    new AsyncTask<Long, Void, Long>() {

        @Override
        protected Long doInBackground(Long... params) {
            if (voiceNoteDraftFuture != null) {
                try {
                    Draft voiceNoteDraft = voiceNoteDraftFuture.get().asDraft();
                    draftViewModel.setVoiceNoteDraft(recipientId, voiceNoteDraft);
                    drafts.add(voiceNoteDraft);
                } catch (ExecutionException | InterruptedException e) {
                    Log.w(TAG, "Could not extract voice note draft data.", e);
                }
            }
            ThreadDatabase threadDatabase = SignalDatabase.threads();
            DraftDatabase draftDatabase = SignalDatabase.drafts();
            long threadId = params[0];
            if (drafts.size() > 0) {
                if (threadId == -1)
                    threadId = threadDatabase.getOrCreateThreadIdFor(getRecipient(), thisDistributionType);
                draftDatabase.replaceDrafts(threadId, drafts);
                threadDatabase.updateSnippet(threadId, drafts.getSnippet(context), drafts.getUriSnippet(), System.currentTimeMillis(), Types.BASE_DRAFT_TYPE, true);
            } else if (threadId > 0) {
                threadDatabase.update(threadId, false);
            }
            if (drafts.isEmpty()) {
                draftDatabase.clearDrafts(threadId);
            }
            return threadId;
        }

        @Override
        protected void onPostExecute(Long result) {
            future.set(result);
        }
    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, thisThreadId);
    return future;
}
Also used : SettableFuture(org.thoughtcrime.securesms.util.concurrent.SettableFuture) Context(android.content.Context) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) DraftDatabase(org.thoughtcrime.securesms.database.DraftDatabase) VoiceNoteDraft(org.thoughtcrime.securesms.components.voice.VoiceNoteDraft) ThreadDatabase(org.thoughtcrime.securesms.database.ThreadDatabase) SuppressLint(android.annotation.SuppressLint) Drafts(org.thoughtcrime.securesms.database.DraftDatabase.Drafts) VoiceNoteDraft(org.thoughtcrime.securesms.components.voice.VoiceNoteDraft) Draft(org.thoughtcrime.securesms.database.DraftDatabase.Draft)

Aggregations

VoiceNoteDraft (org.thoughtcrime.securesms.components.voice.VoiceNoteDraft)12 Draft (org.thoughtcrime.securesms.database.DraftDatabase.Draft)12 Drafts (org.thoughtcrime.securesms.database.DraftDatabase.Drafts)9 SuppressLint (android.annotation.SuppressLint)6 Context (android.content.Context)6 SpannableString (android.text.SpannableString)6 DraftDatabase (org.thoughtcrime.securesms.database.DraftDatabase)6 AudioSlide (org.thoughtcrime.securesms.mms.AudioSlide)6 SettableFuture (org.thoughtcrime.securesms.util.concurrent.SettableFuture)6 Spannable (android.text.Spannable)3 OnClickListener (android.view.View.OnClickListener)3 OnFocusChangeListener (android.view.View.OnFocusChangeListener)3 OnKeyListener (android.view.View.OnKeyListener)3 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3 TransportOption (org.thoughtcrime.securesms.TransportOption)3 OnKeyboardShownListener (org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout.OnKeyboardShownListener)3