mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-26 11:26:01 +03:00
Toggle Quick React (agree/disagree like/dislike)
This commit is contained in:
parent
44d1d063e9
commit
5dfc0b3c0e
13 changed files with 214 additions and 72 deletions
|
@ -35,4 +35,12 @@ interface ReactionService {
|
||||||
*/
|
*/
|
||||||
fun undoReaction(reaction: String, targetEventId: String, myUserId: String)//: Cancelable
|
fun undoReaction(reaction: String, targetEventId: String, myUserId: String)//: Cancelable
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo a reaction (emoji) to the targetedEvent.
|
||||||
|
* @param reaction the reaction (preferably emoji)
|
||||||
|
* @param targetEventId the id of the event being reacted
|
||||||
|
*/
|
||||||
|
fun updateQuickReaction(reaction: String, oppositeReaction: String, targetEventId: String, myUserId: String)
|
||||||
|
|
||||||
}
|
}
|
|
@ -21,6 +21,7 @@ import im.vector.matrix.android.api.session.room.Room
|
||||||
import im.vector.matrix.android.internal.session.room.membership.DefaultMembershipService
|
import im.vector.matrix.android.internal.session.room.membership.DefaultMembershipService
|
||||||
import im.vector.matrix.android.internal.session.room.annotation.FindReactionEventForUndoTask
|
import im.vector.matrix.android.internal.session.room.annotation.FindReactionEventForUndoTask
|
||||||
import im.vector.matrix.android.internal.session.room.annotation.DefaultReactionService
|
import im.vector.matrix.android.internal.session.room.annotation.DefaultReactionService
|
||||||
|
import im.vector.matrix.android.internal.session.room.annotation.UpdateQuickReactionTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask
|
import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.SenderRoomMemberExtractor
|
import im.vector.matrix.android.internal.session.room.membership.SenderRoomMemberExtractor
|
||||||
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
|
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
|
||||||
|
@ -48,6 +49,7 @@ internal class RoomFactory(private val monarchy: Monarchy,
|
||||||
private val contextOfEventTask: GetContextOfEventTask,
|
private val contextOfEventTask: GetContextOfEventTask,
|
||||||
private val setReadMarkersTask: SetReadMarkersTask,
|
private val setReadMarkersTask: SetReadMarkersTask,
|
||||||
private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
|
private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
|
||||||
|
private val updateQuickReactionTask: UpdateQuickReactionTask,
|
||||||
private val joinRoomTask: JoinRoomTask,
|
private val joinRoomTask: JoinRoomTask,
|
||||||
private val leaveRoomTask: LeaveRoomTask) {
|
private val leaveRoomTask: LeaveRoomTask) {
|
||||||
|
|
||||||
|
@ -56,7 +58,7 @@ internal class RoomFactory(private val monarchy: Monarchy,
|
||||||
val timelineEventFactory = TimelineEventFactory(roomMemberExtractor, EventRelationExtractor())
|
val timelineEventFactory = TimelineEventFactory(roomMemberExtractor, EventRelationExtractor())
|
||||||
val timelineService = DefaultTimelineService(roomId, monarchy, taskExecutor, timelineEventFactory, contextOfEventTask, paginationTask)
|
val timelineService = DefaultTimelineService(roomId, monarchy, taskExecutor, timelineEventFactory, contextOfEventTask, paginationTask)
|
||||||
val sendService = DefaultSendService(roomId, eventFactory, monarchy)
|
val sendService = DefaultSendService(roomId, eventFactory, monarchy)
|
||||||
val reactionService = DefaultReactionService(roomId, eventFactory, monarchy, findReactionEventForUndoTask, taskExecutor)
|
val reactionService = DefaultReactionService(roomId, eventFactory, findReactionEventForUndoTask, updateQuickReactionTask, taskExecutor)
|
||||||
val stateService = DefaultStateService(roomId, taskExecutor, sendStateTask)
|
val stateService = DefaultStateService(roomId, taskExecutor, sendStateTask)
|
||||||
val roomMembersService = DefaultMembershipService(roomId, monarchy, taskExecutor, loadRoomMembersTask, inviteTask, joinRoomTask, leaveRoomTask)
|
val roomMembersService = DefaultMembershipService(roomId, monarchy, taskExecutor, loadRoomMembersTask, inviteTask, joinRoomTask, leaveRoomTask)
|
||||||
val readService = DefaultReadService(roomId, monarchy, taskExecutor, setReadMarkersTask)
|
val readService = DefaultReadService(roomId, monarchy, taskExecutor, setReadMarkersTask)
|
||||||
|
|
|
@ -18,7 +18,9 @@ package im.vector.matrix.android.internal.session.room
|
||||||
|
|
||||||
import im.vector.matrix.android.internal.session.DefaultSession
|
import im.vector.matrix.android.internal.session.DefaultSession
|
||||||
import im.vector.matrix.android.internal.session.room.annotation.DefaultFindReactionEventForUndoTask
|
import im.vector.matrix.android.internal.session.room.annotation.DefaultFindReactionEventForUndoTask
|
||||||
|
import im.vector.matrix.android.internal.session.room.annotation.DefaultUpdateQuickReactionTask
|
||||||
import im.vector.matrix.android.internal.session.room.annotation.FindReactionEventForUndoTask
|
import im.vector.matrix.android.internal.session.room.annotation.FindReactionEventForUndoTask
|
||||||
|
import im.vector.matrix.android.internal.session.room.annotation.UpdateQuickReactionTask
|
||||||
import im.vector.matrix.android.internal.session.room.create.CreateRoomTask
|
import im.vector.matrix.android.internal.session.room.create.CreateRoomTask
|
||||||
import im.vector.matrix.android.internal.session.room.create.DefaultCreateRoomTask
|
import im.vector.matrix.android.internal.session.room.create.DefaultCreateRoomTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.DefaultLoadRoomMembersTask
|
import im.vector.matrix.android.internal.session.room.membership.DefaultLoadRoomMembersTask
|
||||||
|
@ -75,7 +77,7 @@ class RoomModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
RoomFactory(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
|
RoomFactory(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
|
||||||
}
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
|
@ -102,6 +104,10 @@ class RoomModule {
|
||||||
DefaultFindReactionEventForUndoTask(get()) as FindReactionEventForUndoTask
|
DefaultFindReactionEventForUndoTask(get()) as FindReactionEventForUndoTask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope(DefaultSession.SCOPE) {
|
||||||
|
DefaultUpdateQuickReactionTask(get()) as UpdateQuickReactionTask
|
||||||
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
DefaultPruneEventTask(get()) as PruneEventTask
|
DefaultPruneEventTask(get()) as PruneEventTask
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package im.vector.matrix.android.internal.session.room.annotation
|
package im.vector.matrix.android.internal.session.room.annotation
|
||||||
|
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
import com.zhuinden.monarchy.Monarchy
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.model.annotation.ReactionService
|
import im.vector.matrix.android.api.session.room.model.annotation.ReactionService
|
||||||
|
@ -39,8 +38,8 @@ private val WORK_CONSTRAINTS = Constraints.Builder()
|
||||||
|
|
||||||
internal class DefaultReactionService(private val roomId: String,
|
internal class DefaultReactionService(private val roomId: String,
|
||||||
private val eventFactory: LocalEchoEventFactory,
|
private val eventFactory: LocalEchoEventFactory,
|
||||||
private val monarchy: Monarchy,
|
|
||||||
private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
|
private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
|
||||||
|
private val updateQuickReactionTask: UpdateQuickReactionTask,
|
||||||
private val taskExecutor: TaskExecutor)
|
private val taskExecutor: TaskExecutor)
|
||||||
: ReactionService {
|
: ReactionService {
|
||||||
|
|
||||||
|
@ -95,6 +94,32 @@ internal class DefaultReactionService(private val roomId: String,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun updateQuickReaction(reaction: String, oppositeReaction: String, targetEventId: String, myUserId: String) {
|
||||||
|
|
||||||
|
val params = UpdateQuickReactionTask.Params(
|
||||||
|
roomId,
|
||||||
|
targetEventId,
|
||||||
|
reaction,
|
||||||
|
oppositeReaction,
|
||||||
|
myUserId
|
||||||
|
)
|
||||||
|
|
||||||
|
updateQuickReactionTask.configureWith(params)
|
||||||
|
.dispatchTo(object : MatrixCallback<UpdateQuickReactionTask.Result> {
|
||||||
|
override fun onSuccess(data: UpdateQuickReactionTask.Result) {
|
||||||
|
data.reactionToAdd?.also { sendReaction(it, targetEventId) }
|
||||||
|
data.reactionToRedact.forEach {
|
||||||
|
val redactWork = createRedactEventWork(it, null)
|
||||||
|
WorkManager.getInstance()
|
||||||
|
.beginUniqueWork(buildWorkIdentifier(REACTION_WORK), ExistingWorkPolicy.APPEND, redactWork)
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.executeBy(taskExecutor)
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildWorkIdentifier(identifier: String): String {
|
private fun buildWorkIdentifier(identifier: String): String {
|
||||||
return "${roomId}_$identifier"
|
return "${roomId}_$identifier"
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import android.content.Context
|
||||||
import androidx.work.Worker
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.annotation.ReactionContent
|
import im.vector.matrix.android.api.session.room.model.annotation.ReactionContent
|
||||||
|
@ -66,6 +67,11 @@ class SendRelationWorker(context: Context, params: WorkerParameters)
|
||||||
content = localEvent.content
|
content = localEvent.content
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return result.fold({ Result.retry() }, { Result.success() })
|
return result.fold({
|
||||||
|
when (it) {
|
||||||
|
is Failure.NetworkConnection -> Result.retry()
|
||||||
|
else -> Result.failure()
|
||||||
|
}
|
||||||
|
}, { Result.success() })
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package im.vector.matrix.android.internal.session.room.annotation
|
||||||
|
|
||||||
|
import arrow.core.Try
|
||||||
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.ReactionAggregatedSummaryEntityFields
|
||||||
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.task.Task
|
||||||
|
import io.realm.Realm
|
||||||
|
|
||||||
|
|
||||||
|
internal interface UpdateQuickReactionTask : Task<UpdateQuickReactionTask.Params, UpdateQuickReactionTask.Result> {
|
||||||
|
|
||||||
|
data class Params(
|
||||||
|
val roomId: String,
|
||||||
|
val eventId: String,
|
||||||
|
val reaction: String,
|
||||||
|
val oppositeReaction: String,
|
||||||
|
val myUserId: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Result(
|
||||||
|
val reactionToAdd: String?,
|
||||||
|
val reactionToRedact: List<String>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultUpdateQuickReactionTask(private val monarchy: Monarchy) : UpdateQuickReactionTask {
|
||||||
|
override fun execute(params: UpdateQuickReactionTask.Params): Try<UpdateQuickReactionTask.Result> {
|
||||||
|
return Try {
|
||||||
|
var res: Pair<String?, List<String>?>? = null
|
||||||
|
monarchy.doWithRealm { realm ->
|
||||||
|
res = updateQuickReaction(realm, params.reaction, params.oppositeReaction, params.eventId, params.myUserId)
|
||||||
|
}
|
||||||
|
UpdateQuickReactionTask.Result(res?.first, res?.second ?: emptyList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun updateQuickReaction(realm: Realm, reaction: String, oppositeReaction: String, eventId: String, myUserId: String): Pair<String?, List<String>?> {
|
||||||
|
//the emoji reaction has been selected, we need to check if we have reacted it or not
|
||||||
|
val existingSummary = EventAnnotationsSummaryEntity.where(realm, eventId).findFirst()
|
||||||
|
?: return Pair(reaction, null)
|
||||||
|
|
||||||
|
//Ok there is already reactions on this event, have we reacted to it
|
||||||
|
val aggregationForReaction = existingSummary.reactionsSummary.where()
|
||||||
|
.equalTo(ReactionAggregatedSummaryEntityFields.KEY, reaction)
|
||||||
|
.findFirst()
|
||||||
|
val aggregationForOppositeReaction = existingSummary.reactionsSummary.where()
|
||||||
|
.equalTo(ReactionAggregatedSummaryEntityFields.KEY, oppositeReaction)
|
||||||
|
.findFirst()
|
||||||
|
|
||||||
|
if (aggregationForReaction == null || !aggregationForReaction.addedByMe) {
|
||||||
|
//i haven't yet reacted to it, so need to add it, but do I need to redact the opposite?
|
||||||
|
val toRedact = aggregationForOppositeReaction?.sourceEvents?.mapNotNull {
|
||||||
|
//find source event
|
||||||
|
val entity = EventEntity.where(realm, it).findFirst()
|
||||||
|
if (entity?.sender == myUserId) entity.eventId else null
|
||||||
|
}
|
||||||
|
return Pair(reaction, toRedact)
|
||||||
|
} else {
|
||||||
|
//I already added it, so i need to undo it (like a toggle)
|
||||||
|
// find all m.redaction coming from me to readact them
|
||||||
|
val toRedact = aggregationForReaction.sourceEvents.mapNotNull {
|
||||||
|
//find source event
|
||||||
|
val entity = EventEntity.where(realm, it).findFirst()
|
||||||
|
if (entity?.sender == myUserId) entity.eventId else null
|
||||||
|
}
|
||||||
|
return Pair(null, toRedact)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ sealed class RoomDetailActions {
|
||||||
data class SendReaction(val reaction: String, val targetEventId: String) : RoomDetailActions()
|
data class SendReaction(val reaction: String, val targetEventId: String) : RoomDetailActions()
|
||||||
data class RedactAction(val targetEventId: String, val reason: String? = "") : RoomDetailActions()
|
data class RedactAction(val targetEventId: String, val reason: String? = "") : RoomDetailActions()
|
||||||
data class UndoReaction(val targetEventId: String, val key: String, val reason: String? = "") : RoomDetailActions()
|
data class UndoReaction(val targetEventId: String, val key: String, val reason: String? = "") : RoomDetailActions()
|
||||||
|
data class UpdateQuickReactAction(val targetEventId: String,val selectedReaction: String,val opposite: String) : RoomDetailActions()
|
||||||
object AcceptInvite : RoomDetailActions()
|
object AcceptInvite : RoomDetailActions()
|
||||||
object RejectInvite : RoomDetailActions()
|
object RejectInvite : RoomDetailActions()
|
||||||
|
|
||||||
|
|
|
@ -54,11 +54,7 @@ import com.otaliastudios.autocomplete.AutocompleteCallback
|
||||||
import com.otaliastudios.autocomplete.CharPolicy
|
import com.otaliastudios.autocomplete.CharPolicy
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.room.model.Membership
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
|
import im.vector.matrix.android.api.session.room.model.message.*
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
|
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.matrix.android.api.session.user.model.User
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
|
@ -69,15 +65,7 @@ import im.vector.riotredesign.core.extensions.observeEvent
|
||||||
import im.vector.riotredesign.core.glide.GlideApp
|
import im.vector.riotredesign.core.glide.GlideApp
|
||||||
import im.vector.riotredesign.core.platform.ToolbarConfigurable
|
import im.vector.riotredesign.core.platform.ToolbarConfigurable
|
||||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||||
import im.vector.riotredesign.core.utils.LiveEvent
|
import im.vector.riotredesign.core.utils.*
|
||||||
import im.vector.riotredesign.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
|
|
||||||
import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_CAMERA
|
|
||||||
import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_NATIVE_CAMERA
|
|
||||||
import im.vector.riotredesign.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_NATIVE_VIDEO_CAMERA
|
|
||||||
import im.vector.riotredesign.core.utils.checkPermissions
|
|
||||||
import im.vector.riotredesign.core.utils.copyToClipboard
|
|
||||||
import im.vector.riotredesign.core.utils.openCamera
|
|
||||||
import im.vector.riotredesign.core.utils.shareMedia
|
|
||||||
import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandPresenter
|
import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandPresenter
|
||||||
import im.vector.riotredesign.features.autocomplete.command.CommandAutocompletePolicy
|
import im.vector.riotredesign.features.autocomplete.command.CommandAutocompletePolicy
|
||||||
import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserPresenter
|
import im.vector.riotredesign.features.autocomplete.user.AutocompleteUserPresenter
|
||||||
|
@ -522,7 +510,7 @@ class RoomDetailFragment :
|
||||||
roomDetailViewModel.process(RoomDetailActions.SendReaction(reaction, informationData.eventId))
|
roomDetailViewModel.process(RoomDetailActions.SendReaction(reaction, informationData.eventId))
|
||||||
} else {
|
} else {
|
||||||
//I need to redact a reaction
|
//I need to redact a reaction
|
||||||
roomDetailViewModel.process(RoomDetailActions.UndoReaction(informationData.eventId,reaction))
|
roomDetailViewModel.process(RoomDetailActions.UndoReaction(informationData.eventId, reaction))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +537,7 @@ class RoomDetailFragment :
|
||||||
}
|
}
|
||||||
MessageMenuViewModel.ACTION_DELETE -> {
|
MessageMenuViewModel.ACTION_DELETE -> {
|
||||||
val eventId = actionData.data?.toString() ?: return
|
val eventId = actionData.data?.toString() ?: return
|
||||||
roomDetailViewModel.process(RoomDetailActions.RedactAction(eventId,context?.getString(R.string.event_redacted_by_user_reason)))
|
roomDetailViewModel.process(RoomDetailActions.RedactAction(eventId, context?.getString(R.string.event_redacted_by_user_reason)))
|
||||||
}
|
}
|
||||||
MessageMenuViewModel.ACTION_SHARE -> {
|
MessageMenuViewModel.ACTION_SHARE -> {
|
||||||
//TODO current data communication is too limited
|
//TODO current data communication is too limited
|
||||||
|
@ -595,8 +583,9 @@ class RoomDetailFragment :
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
MessageMenuViewModel.ACTION_QUICK_REACT -> {
|
MessageMenuViewModel.ACTION_QUICK_REACT -> {
|
||||||
(actionData.data as? Pair<String, String>)?.let { pairData ->
|
//eventId,ClickedOn,Opposite
|
||||||
roomDetailViewModel.process(RoomDetailActions.SendReaction(pairData.second, pairData.first))
|
(actionData.data as? Triple<String, String, String>)?.let { (eventId, clickedOn, opposite) ->
|
||||||
|
roomDetailViewModel.process(RoomDetailActions.UpdateQuickReactAction(eventId, clickedOn, opposite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
|
@ -81,9 +81,12 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
|
||||||
is RoomDetailActions.AcceptInvite -> handleAcceptInvite()
|
is RoomDetailActions.AcceptInvite -> handleAcceptInvite()
|
||||||
is RoomDetailActions.RejectInvite -> handleRejectInvite()
|
is RoomDetailActions.RejectInvite -> handleRejectInvite()
|
||||||
is RoomDetailActions.RedactAction -> handleRedactEvent(action)
|
is RoomDetailActions.RedactAction -> handleRedactEvent(action)
|
||||||
|
is RoomDetailActions.UndoReaction -> handleUndoReact(action)
|
||||||
|
is RoomDetailActions.UpdateQuickReactAction -> handleUpdateQuickReaction(action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val _sendMessageResultLiveData = MutableLiveData<LiveEvent<SendMessageResult>>()
|
private val _sendMessageResultLiveData = MutableLiveData<LiveEvent<SendMessageResult>>()
|
||||||
val sendMessageResultLiveData: LiveData<LiveEvent<SendMessageResult>>
|
val sendMessageResultLiveData: LiveData<LiveEvent<SendMessageResult>>
|
||||||
get() = _sendMessageResultLiveData
|
get() = _sendMessageResultLiveData
|
||||||
|
@ -201,6 +204,11 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun handleUpdateQuickReaction(action: RoomDetailActions.UpdateQuickReactAction) {
|
||||||
|
room.updateQuickReaction(action.selectedReaction, action.opposite, action.targetEventId, session.sessionParams.credentials.userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun handleSendMedia(action: RoomDetailActions.SendMedia) {
|
private fun handleSendMedia(action: RoomDetailActions.SendMedia) {
|
||||||
val attachments = action.mediaFiles.map {
|
val attachments = action.mediaFiles.map {
|
||||||
ContentAttachmentData(
|
ContentAttachmentData(
|
||||||
|
@ -238,6 +246,7 @@ class RoomDetailViewModel(initialState: RoomDetailViewState,
|
||||||
room.join(object : MatrixCallback<Unit> {})
|
room.join(object : MatrixCallback<Unit> {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun observeEventDisplayedActions() {
|
private fun observeEventDisplayedActions() {
|
||||||
// We are buffering scroll events for one second
|
// We are buffering scroll events for one second
|
||||||
// and keep the most recent one to set the read receipt on.
|
// and keep the most recent one to set the read receipt on.
|
||||||
|
|
|
@ -95,13 +95,8 @@ class MessageActionsBottomSheet : BaseMvRxBottomSheetDialog() {
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
quickReactionFragment.interactionListener = object : QuickReactionFragment.InteractionListener {
|
quickReactionFragment.interactionListener = object : QuickReactionFragment.InteractionListener {
|
||||||
override fun didQuickReactWith(clikedOn: String, reactions: List<String>, eventId: String) {
|
override fun didQuickReactWith(clikedOn: String, opposite: String, reactions: List<String>, eventId: String) {
|
||||||
if (reactions.contains(clikedOn)) {
|
actionHandlerModel.fireAction(MessageMenuViewModel.ACTION_QUICK_REACT, Triple(eventId, clikedOn, opposite))
|
||||||
//it's an add
|
|
||||||
actionHandlerModel.fireAction(MessageMenuViewModel.ACTION_QUICK_REACT, Pair(eventId,clikedOn))
|
|
||||||
} else {
|
|
||||||
//it's a remove
|
|
||||||
}
|
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,12 +119,14 @@ class QuickReactionFragment : BaseMvRxFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.selectionResult != null) {
|
if (it.selectionResult != null) {
|
||||||
interactionListener?.didQuickReactWith(it.selectionResult.first, it.selectionResult.second, it.eventId)
|
val clikedOn = it.selectionResult.first
|
||||||
|
interactionListener?.didQuickReactWith(clikedOn, QuickReactionViewModel.getOpposite(clikedOn)
|
||||||
|
?: "", it.selectionResult.second, it.eventId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InteractionListener {
|
interface InteractionListener {
|
||||||
fun didQuickReactWith(clikedOn: String, reactions: List<String>, eventId: String)
|
fun didQuickReactWith(clikedOn: String, opposite: String, reactions: List<String>, eventId: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -110,6 +110,16 @@ class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel
|
||||||
val likePositive = "🙂"
|
val likePositive = "🙂"
|
||||||
val likeNegative = "😔"
|
val likeNegative = "😔"
|
||||||
|
|
||||||
|
fun getOpposite(reaction: String): String? {
|
||||||
|
return when (reaction) {
|
||||||
|
agreePositive -> agreeNegative
|
||||||
|
agreeNegative -> agreePositive
|
||||||
|
likePositive -> likeNegative
|
||||||
|
likeNegative -> likePositive
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun initialState(viewModelContext: ViewModelContext): QuickReactionState? {
|
override fun initialState(viewModelContext: ViewModelContext): QuickReactionState? {
|
||||||
// Args are accessible from the context.
|
// Args are accessible from the context.
|
||||||
// val foo = vieWModelContext.args<MyArgs>.foo
|
// val foo = vieWModelContext.args<MyArgs>.foo
|
||||||
|
|
|
@ -125,7 +125,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && !holder.view.isInLayout) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && !holder.view.isInLayout) {
|
||||||
holder.reactionFlowHelper?.requestLayout()
|
holder.reactionFlowHelper?.requestLayout()
|
||||||
}
|
}
|
||||||
|
holder.reactionWrapper?.setOnLongClickListener(longClickListener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue