Add reaction support to CFV2.

This commit is contained in:
Alex Hart
2023-06-12 10:23:57 -03:00
committed by Cody Henthorne
parent b9e002f7b1
commit f3b629bc06
3 changed files with 82 additions and 3 deletions

View File

@@ -208,6 +208,7 @@ import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.profiles.spoofing.ReviewCardDialogFragment
import org.thoughtcrime.securesms.ratelimit.RecaptchaProofBottomSheetFragment
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
@@ -258,7 +259,10 @@ import java.util.concurrent.ExecutionException
/**
* A single unified fragment for Conversations.
*/
class ConversationFragment : LoggingFragment(R.layout.v2_conversation_fragment) {
class ConversationFragment :
LoggingFragment(R.layout.v2_conversation_fragment),
ReactWithAnyEmojiBottomSheetDialogFragment.Callback,
ReactionsBottomSheetDialogFragment.Callback {
companion object {
private val TAG = Log.tag(ConversationFragment::class.java)
@@ -442,6 +446,18 @@ class ConversationFragment : LoggingFragment(R.layout.v2_conversation_fragment)
}
}
override fun onReactWithAnyEmojiDialogDismissed() {
reactionDelegate.hide()
}
override fun onReactWithAnyEmojiSelected(emoji: String) {
reactionDelegate.hide()
}
override fun onReactionsDialogDismissed() {
clearFocusedItem()
}
private fun observeConversationThread() {
var firstRender = true
disposables += viewModel
@@ -1580,13 +1596,13 @@ class ConversationFragment : LoggingFragment(R.layout.v2_conversation_fragment)
context ?: return
val reactionsTag = "REACTIONS"
if (parentFragmentManager.findFragmentByTag(reactionsTag) == null) {
ReactionsBottomSheetDialogFragment.create(messageId, isMms).show(parentFragmentManager, reactionsTag)
ReactionsBottomSheetDialogFragment.create(messageId, isMms).show(childFragmentManager, reactionsTag)
}
}
override fun onGroupMemberClicked(recipientId: RecipientId, groupId: GroupId) {
context ?: return
RecipientBottomSheetDialogFragment.create(recipientId, groupId).show(parentFragmentManager, "BOTTOM")
RecipientBottomSheetDialogFragment.create(recipientId, groupId).show(childFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
}
override fun onMessageWithErrorClicked(messageRecord: MessageRecord) {
@@ -2150,10 +2166,23 @@ class ConversationFragment : LoggingFragment(R.layout.v2_conversation_fragment)
private inner class OnReactionsSelectedListener : ConversationReactionOverlay.OnReactionSelectedListener {
override fun onReactionSelected(messageRecord: MessageRecord, emoji: String?) {
reactionDelegate.hide()
if (emoji != null) {
disposables += viewModel.updateReaction(messageRecord, emoji).subscribe()
}
}
override fun onCustomReactionSelected(messageRecord: MessageRecord, hasAddedCustomEmoji: Boolean) {
reactionDelegate.hide()
disposables += viewModel.updateCustomReaction(messageRecord, hasAddedCustomEmoji)
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = {
ReactWithAnyEmojiBottomSheetDialogFragment
.createForMessageRecord(messageRecord, -1)
.show(childFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
}
)
}
}

View File

@@ -63,8 +63,10 @@ import org.thoughtcrime.securesms.database.model.GroupRecord
import org.thoughtcrime.securesms.database.model.IdentityRecord
import org.thoughtcrime.securesms.database.model.Mention
import org.thoughtcrime.securesms.database.model.MessageId
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.database.model.Quote
import org.thoughtcrime.securesms.database.model.ReactionRecord
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.jobs.MultiDeviceViewOnceOpenJob
@@ -159,6 +161,26 @@ class ConversationRepository(
.subscribeOn(Schedulers.io())
}
fun sendReactionRemoval(messageRecord: MessageRecord, oldRecord: ReactionRecord): Completable {
return Completable.fromAction {
MessageSender.sendReactionRemoval(
applicationContext,
MessageId(messageRecord.id),
oldRecord
)
}.subscribeOn(Schedulers.io())
}
fun sendNewReaction(messageRecord: MessageRecord, emoji: String): Completable {
return Completable.fromAction {
MessageSender.sendNewReaction(
applicationContext,
MessageId(messageRecord.id),
emoji
)
}.subscribeOn(Schedulers.io())
}
fun sendMessage(
threadId: Long,
threadRecipient: Recipient?,

View File

@@ -41,6 +41,7 @@ import org.thoughtcrime.securesms.database.model.MessageId
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.database.model.Quote
import org.thoughtcrime.securesms.database.model.ReactionRecord
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob
@@ -248,6 +249,33 @@ class ConversationViewModel(
}
}
fun updateReaction(messageRecord: MessageRecord, emoji: String): Completable {
val oldRecord = messageRecord.oldReactionRecord()
return if (oldRecord != null && oldRecord.emoji == emoji) {
repository.sendReactionRemoval(messageRecord, oldRecord)
} else {
repository.sendNewReaction(messageRecord, emoji)
}
}
/**
* @return Maybe which only emits if the "React with any" sheet should be displayed.
*/
fun updateCustomReaction(messageRecord: MessageRecord, hasAddedCustomEmoji: Boolean): Maybe<Unit> {
val oldRecord = messageRecord.oldReactionRecord()
return if (oldRecord != null && hasAddedCustomEmoji) {
repository.sendReactionRemoval(messageRecord, oldRecord).toMaybe()
} else {
Maybe.just(Unit)
}
}
private fun MessageRecord.oldReactionRecord(): ReactionRecord? {
return reactions.firstOrNull { it.author == Recipient.self().id }
}
fun sendMessage(
metricId: String?,
body: String,