Clear compose input immediately on send to match behavior of v1.

This commit is contained in:
Cody Henthorne
2023-07-24 13:32:16 -04:00
parent 05fc30e6e8
commit 73792905a2
4 changed files with 36 additions and 55 deletions

View File

@@ -86,7 +86,6 @@ import org.signal.core.util.dp
import org.signal.core.util.logging.Log
import org.signal.core.util.orNull
import org.signal.core.util.setActionItemTint
import org.signal.libsignal.protocol.InvalidMessageException
import org.signal.ringrtc.CallLinkRootKey
import org.thoughtcrime.securesms.BlockUnblockDialog
import org.thoughtcrime.securesms.GroupMembersDialog
@@ -258,7 +257,6 @@ import org.thoughtcrime.securesms.reactions.ReactionsBottomSheetDialogFragment
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiBottomSheetDialogFragment
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientExporter
import org.thoughtcrime.securesms.recipients.RecipientFormattingException
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment
import org.thoughtcrime.securesms.recipients.ui.disappearingmessages.RecipientDisappearingMessagesActivity
@@ -901,7 +899,7 @@ class ConversationFragment :
.addTo(disposables)
viewModel
.identityRecords
.identityRecordsObservable
.distinctUntilChanged()
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy { presentIdentityRecordsState(it) }
@@ -1652,6 +1650,14 @@ class ConversationFragment :
isViewOnce: Boolean = false,
afterSendComplete: () -> Unit = {}
) {
val threadRecipient = viewModel.recipientSnapshot
if (threadRecipient == null) {
Log.w(TAG, "Unable to send due to invalid thread recipient")
toast(R.string.ConversationActivity_recipient_is_not_a_valid_sms_or_email_address_exclamation, Toast.LENGTH_LONG)
return
}
if (scheduledDate != -1L && ReenableScheduledMessagesDialogFragment.showIfNeeded(requireContext(), childFragmentManager, null, scheduledDate)) {
return
}
@@ -1676,10 +1682,23 @@ class ConversationFragment :
}
}
if (body.isEmpty() && slideDeck?.containsMediaSlide() != true && preUploadResults.isEmpty() && contacts.isEmpty()) {
Log.i(TAG, "Unable to send due to empty message")
toast(R.string.ConversationActivity_message_is_empty_exclamation)
return
}
if (viewModel.identityRecordsState.hasRecentSafetyNumberChange() && !bypassPreSendSafetyNumberCheck) {
Log.i(TAG, "Unable to send due to SNC")
handleRecentSafetyNumberChange(viewModel.identityRecordsState.getRecentSafetyNumberChangeRecords())
return
}
val metricId = viewModel.recipientSnapshot?.let { if (it.isGroup) SignalLocalMetrics.GroupMessageSend.start() else SignalLocalMetrics.IndividualMessageSend.start() }
val send: Completable = viewModel.sendMessage(
metricId = metricId,
threadRecipient = threadRecipient,
body = body,
slideDeck = slideDeck,
scheduledDate = scheduledDate,
@@ -1690,28 +1709,20 @@ class ConversationFragment :
contacts = contacts,
linkPreviews = linkPreviews,
preUploadResults = preUploadResults,
bypassPreSendSafetyNumberCheck = bypassPreSendSafetyNumberCheck,
isViewOnce = isViewOnce
)
disposables += send
.doOnSubscribe { scrollToPositionDelegate.markListCommittedVersion() }
.doOnSubscribe {
if (clearCompose) {
composeText.setText("")
attachmentManager.clear(GlideApp.with(this@ConversationFragment), false)
inputPanel.clearQuote()
}
scrollToPositionDelegate.markListCommittedVersion()
}
.subscribeBy(
onError = { t ->
Log.w(TAG, "Error sending", t)
when (t) {
is InvalidMessageException -> toast(R.string.ConversationActivity_message_is_empty_exclamation)
is RecipientFormattingException -> toast(R.string.ConversationActivity_recipient_is_not_a_valid_sms_or_email_address_exclamation, Toast.LENGTH_LONG)
is RecentSafetyNumberChangeException -> handleRecentSafetyNumberChange(t.changedRecords)
}
},
onComplete = {
if (clearCompose) {
composeText.setText("")
attachmentManager.clear(GlideApp.with(this@ConversationFragment), false)
inputPanel.clearQuote()
}
onSendComplete()
afterSendComplete()
}

View File

@@ -28,7 +28,6 @@ import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.dp
import org.signal.core.util.logging.Log
import org.signal.core.util.toOptional
import org.signal.libsignal.protocol.InvalidMessageException
import org.signal.paging.PagedData
import org.signal.paging.PagingConfig
import org.thoughtcrime.securesms.R
@@ -88,7 +87,6 @@ import org.thoughtcrime.securesms.mms.SlideDeck
import org.thoughtcrime.securesms.profiles.spoofing.ReviewUtil
import org.thoughtcrime.securesms.providers.BlobProvider
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientFormattingException
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.search.MessageResult
import org.thoughtcrime.securesms.sms.MessageSender
@@ -203,7 +201,7 @@ class ConversationRepository(
fun sendMessage(
threadId: Long,
threadRecipient: Recipient?,
threadRecipient: Recipient,
metricId: String?,
body: String,
slideDeck: SlideDeck?,
@@ -215,25 +213,9 @@ class ConversationRepository(
contacts: List<Contact>,
linkPreviews: List<LinkPreview>,
preUploadResults: List<PreUploadResult>,
identityRecordsState: IdentityRecordsState?,
isViewOnce: Boolean
): Completable {
val sendCompletable = Completable.create { emitter ->
if (body.isEmpty() && slideDeck?.containsMediaSlide() != true && preUploadResults.isEmpty() && contacts.isEmpty()) {
emitter.onError(InvalidMessageException("Message is empty!"))
return@create
}
if (threadRecipient == null) {
emitter.onError(RecipientFormattingException("Badly formatted"))
return@create
}
if (identityRecordsState != null && identityRecordsState.hasRecentSafetyNumberChange()) {
emitter.onError(RecentSafetyNumberChangeException(identityRecordsState.getRecentSafetyNumberChangeRecords()))
return@create
}
val splitMessage: MessageUtil.SplitResult = MessageUtil.getSplitMessage(
applicationContext,
body,

View File

@@ -131,7 +131,9 @@ class ConversationViewModel(
private val refreshIdentityRecords: Subject<Unit> = PublishSubject.create()
private val identityRecordsStore: RxStore<IdentityRecordsState> = RxStore(IdentityRecordsState())
val identityRecords: Observable<IdentityRecordsState> = identityRecordsStore.stateFlowable.toObservable()
val identityRecordsObservable: Observable<IdentityRecordsState> = identityRecordsStore.stateFlowable.toObservable()
val identityRecordsState: IdentityRecordsState
get() = identityRecordsStore.state
private val _searchQuery = BehaviorSubject.createDefault("")
val searchQuery: Observable<String> = _searchQuery
@@ -336,6 +338,7 @@ class ConversationViewModel(
fun sendMessage(
metricId: String?,
threadRecipient: Recipient,
body: String,
slideDeck: SlideDeck?,
scheduledDate: Long,
@@ -346,12 +349,11 @@ class ConversationViewModel(
contacts: List<Contact>,
linkPreviews: List<LinkPreview>,
preUploadResults: List<MessageSender.PreUploadResult>,
bypassPreSendSafetyNumberCheck: Boolean,
isViewOnce: Boolean
): Completable {
return repository.sendMessage(
threadId = threadId,
threadRecipient = recipientSnapshot,
threadRecipient = threadRecipient,
metricId = metricId,
body = body,
slideDeck = slideDeck,
@@ -363,7 +365,6 @@ class ConversationViewModel(
contacts = contacts,
linkPreviews = linkPreviews,
preUploadResults = preUploadResults,
identityRecordsState = if (bypassPreSendSafetyNumberCheck) null else identityRecordsStore.state,
isViewOnce = isViewOnce
).observeOn(AndroidSchedulers.mainThread())
}

View File

@@ -1,13 +0,0 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.conversation.v2
import org.thoughtcrime.securesms.database.model.IdentityRecord
/**
* Emitted when safety numbers changed recently before a send attempt.
*/
class RecentSafetyNumberChangeException(val changedRecords: List<IdentityRecord>) : Exception()