Safety number check and profile refresh for group sends.

fork-5.53.8
Alex Hart 2022-03-30 09:25:36 -03:00 zatwierdzone przez Cody Henthorne
rodzic 14849d6e45
commit 76a9342afa
2 zmienionych plików z 98 dodań i 31 usunięć

Wyświetl plik

@ -11,17 +11,25 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.kotlin.subscribeBy
import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard import org.thoughtcrime.securesms.components.emoji.MediaKeyboard
import org.thoughtcrime.securesms.components.mention.MentionAnnotation import org.thoughtcrime.securesms.components.mention.MentionAnnotation
import org.thoughtcrime.securesms.components.settings.DSLConfiguration import org.thoughtcrime.securesms.components.settings.DSLConfiguration
import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.conversation.colors.Colorizer import org.thoughtcrime.securesms.conversation.colors.Colorizer
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog
import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerFragment import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerFragment
import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerViewModel import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerViewModel
import org.thoughtcrime.securesms.database.model.Mention
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob
import org.thoughtcrime.securesms.keyboard.KeyboardPage import org.thoughtcrime.securesms.keyboard.KeyboardPage
import org.thoughtcrime.securesms.keyboard.KeyboardPagerViewModel import org.thoughtcrime.securesms.keyboard.KeyboardPagerViewModel
import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardCallback import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardCallback
import org.thoughtcrime.securesms.mediasend.v2.UntrustedRecords
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiBottomSheetDialogFragment import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiBottomSheetDialogFragment
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientId
@ -51,7 +59,8 @@ class StoryGroupReplyFragment :
BottomSheetBehaviorDelegate, BottomSheetBehaviorDelegate,
StoryReplyComposer.Callback, StoryReplyComposer.Callback,
EmojiKeyboardCallback, EmojiKeyboardCallback,
ReactWithAnyEmojiBottomSheetDialogFragment.Callback { ReactWithAnyEmojiBottomSheetDialogFragment.Callback,
SafetyNumberChangeDialog.Callback {
private val viewModel: StoryGroupReplyViewModel by viewModels( private val viewModel: StoryGroupReplyViewModel by viewModels(
factoryProducer = { factoryProducer = {
@ -81,6 +90,10 @@ class StoryGroupReplyFragment :
private lateinit var composer: StoryReplyComposer private lateinit var composer: StoryReplyComposer
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
SignalExecutors.BOUNDED.execute {
RetrieveProfileJob.enqueue(groupRecipientId)
}
recyclerView = view.findViewById(R.id.recycler) recyclerView = view.findViewById(R.id.recycler)
composer = view.findViewById(R.id.composer) composer = view.findViewById(R.id.composer)
@ -194,9 +207,12 @@ class StoryGroupReplyFragment :
recyclerView.isNestedScrollingEnabled = child == StoryViewsAndRepliesPagerParent.Child.REPLIES recyclerView.isNestedScrollingEnabled = child == StoryViewsAndRepliesPagerParent.Child.REPLIES
} }
private var resendBody: CharSequence? = null
private var resendMentions: List<Mention> = emptyList()
override fun onSendActionClicked() { override fun onSendActionClicked() {
val (body, mentions) = composer.consumeInput() val (body, mentions) = composer.consumeInput()
lifecycleDisposable += StoryGroupReplySender.sendReply(requireContext(), storyId, body, mentions).subscribe() performSend(body, mentions)
} }
override fun onPickReactionClicked() { override fun onPickReactionClicked() {
@ -299,6 +315,8 @@ class StoryGroupReplyFragment :
} }
companion object { companion object {
private val TAG = Log.tag(StoryGroupReplyFragment::class.java)
private const val ARG_STORY_ID = "arg.story.id" private const val ARG_STORY_ID = "arg.story.id"
private const val ARG_GROUP_RECIPIENT_ID = "arg.group.recipient.id" private const val ARG_GROUP_RECIPIENT_ID = "arg.group.recipient.id"
@ -312,6 +330,43 @@ class StoryGroupReplyFragment :
} }
} }
private fun performSend(body: CharSequence, mentions: List<Mention>) {
lifecycleDisposable += StoryGroupReplySender.sendReply(requireContext(), storyId, body, mentions)
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onError = {
if (it is UntrustedRecords.UntrustedRecordsException) {
resendBody = body
resendMentions = mentions
SafetyNumberChangeDialog.show(childFragmentManager, it.untrustedRecords)
} else {
Log.w(TAG, "Failed to send reply", it)
val context = context
if (context != null) {
Toast.makeText(context, R.string.message_details_recipient__failed_to_send, Toast.LENGTH_SHORT).show()
}
}
}
)
}
override fun onSendAnywayAfterSafetyNumberChange(changedRecipients: MutableList<RecipientId>) {
val resendBody = resendBody
if (resendBody != null) {
performSend(resendBody, resendMentions)
}
}
override fun onMessageResentAfterSafetyNumberChange() {
error("Should never get here.")
}
override fun onCanceled() {
resendBody = null
resendMentions = emptyList()
}
interface Callback { interface Callback {
fun onStartDirectReply(recipientId: RecipientId) fun onStartDirectReply(recipientId: RecipientId)
} }

Wyświetl plik

@ -2,11 +2,14 @@ package org.thoughtcrime.securesms.stories.viewer.reply.group
import android.content.Context import android.content.Context
import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.Mention import org.thoughtcrime.securesms.database.model.Mention
import org.thoughtcrime.securesms.database.model.ParentStoryId import org.thoughtcrime.securesms.database.model.ParentStoryId
import org.thoughtcrime.securesms.database.model.StoryType import org.thoughtcrime.securesms.database.model.StoryType
import org.thoughtcrime.securesms.mediasend.v2.UntrustedRecords
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage import org.thoughtcrime.securesms.mms.OutgoingMediaMessage
import org.thoughtcrime.securesms.sms.MessageSender import org.thoughtcrime.securesms.sms.MessageSender
@ -24,38 +27,47 @@ object StoryGroupReplySender {
} }
private fun sendInternal(context: Context, storyId: Long, body: CharSequence, mentions: List<Mention>, isReaction: Boolean): Completable { private fun sendInternal(context: Context, storyId: Long, body: CharSequence, mentions: List<Mention>, isReaction: Boolean): Completable {
return Completable.create { val messageAndRecipient = Single.fromCallable {
val message = SignalDatabase.mms.getMessageRecord(storyId) val message = SignalDatabase.mms.getMessageRecord(storyId)
val recipient = SignalDatabase.threads.getRecipientForThreadId(message.threadId)!! val recipient = SignalDatabase.threads.getRecipientForThreadId(message.threadId)!!
MessageSender.send( message to recipient
context, }
OutgoingMediaMessage(
recipient, return messageAndRecipient.flatMapCompletable { (message, recipient) ->
body.toString(), UntrustedRecords.checkForBadIdentityRecords(setOf(ContactSearchKey.KnownRecipient(recipient.id)))
emptyList(), .andThen(
System.currentTimeMillis(), Completable.create {
0,
0L, MessageSender.send(
false, context,
0, OutgoingMediaMessage(
StoryType.NONE, recipient,
ParentStoryId.GroupReply(message.id), body.toString(),
isReaction, emptyList(),
null, System.currentTimeMillis(),
emptyList(), 0,
emptyList(), 0L,
mentions, false,
emptySet(), 0,
emptySet() StoryType.NONE,
), ParentStoryId.GroupReply(message.id),
message.threadId, isReaction,
false, null,
null emptyList(),
) { emptyList(),
it.onComplete() mentions,
} emptySet(),
emptySet()
),
message.threadId,
false,
null
) {
it.onComplete()
}
}
)
}.subscribeOn(Schedulers.io()) }.subscribeOn(Schedulers.io())
} }
} }