Merge pull request #214 from vector-im/feature/update_quick_reactions

Feature/ Update quick reactions
This commit is contained in:
Valere
2019-06-25 15:47:17 +02:00
committed by GitHub
13 changed files with 144 additions and 411 deletions

View File

@ -63,19 +63,6 @@ interface RelationService {
fun undoReaction(reaction: String, targetEventId: String, myUserId: String)//: Cancelable
/**
* Update a quick reaction (toggle).
* If you have reacted with agree and then you click on disagree, this call will delete(redact)
* the disagree and add the agree
* If you click on a reaction that you already reacted with, it will undo it
* @param reaction the reaction (preferably emoji)
* @param oppositeReaction the opposite reaction(preferably emoji)
* @param targetEventId the id of the event being reacted
* @param myUserId used to know if a reaction event was made by the user
*/
fun updateQuickReaction(reaction: String, oppositeReaction: String, targetEventId: String, myUserId: String)
/**
* Edit a text message body. Limited to "m.text" contentType
* @param targetEventId The event to edit

View File

@ -29,7 +29,6 @@ import im.vector.matrix.android.internal.session.room.read.DefaultReadService
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
import im.vector.matrix.android.internal.session.room.relation.DefaultRelationService
import im.vector.matrix.android.internal.session.room.relation.FindReactionEventForUndoTask
import im.vector.matrix.android.internal.session.room.relation.UpdateQuickReactionTask
import im.vector.matrix.android.internal.session.room.send.DefaultSendService
import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
import im.vector.matrix.android.internal.session.room.state.DefaultStateService
@ -51,7 +50,6 @@ internal class RoomFactory(private val monarchy: Monarchy,
private val setReadMarkersTask: SetReadMarkersTask,
private val cryptoService: CryptoService,
private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
private val updateQuickReactionTask: UpdateQuickReactionTask,
private val joinRoomTask: JoinRoomTask,
private val leaveRoomTask: LeaveRoomTask) {
@ -64,7 +62,7 @@ internal class RoomFactory(private val monarchy: Monarchy,
val stateService = DefaultStateService(roomId, taskExecutor, sendStateTask)
val roomMembersService = DefaultMembershipService(roomId, monarchy, taskExecutor, loadRoomMembersTask, inviteTask, joinRoomTask, leaveRoomTask)
val readService = DefaultReadService(roomId, monarchy, taskExecutor, setReadMarkersTask)
val reactionService = DefaultRelationService(roomId, eventFactory, findReactionEventForUndoTask, updateQuickReactionTask, monarchy, taskExecutor)
val reactionService = DefaultRelationService(roomId, eventFactory, findReactionEventForUndoTask, monarchy, taskExecutor)
return DefaultRoom(
roomId,

View File

@ -32,9 +32,7 @@ import im.vector.matrix.android.internal.session.room.prune.PruneEventTask
import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkersTask
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
import im.vector.matrix.android.internal.session.room.relation.DefaultFindReactionEventForUndoTask
import im.vector.matrix.android.internal.session.room.relation.DefaultUpdateQuickReactionTask
import im.vector.matrix.android.internal.session.room.relation.FindReactionEventForUndoTask
import im.vector.matrix.android.internal.session.room.relation.UpdateQuickReactionTask
import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
import im.vector.matrix.android.internal.session.room.send.LocalEchoUpdater
import im.vector.matrix.android.internal.session.room.state.DefaultSendStateTask
@ -82,7 +80,7 @@ class RoomModule {
}
scope(DefaultSession.SCOPE) {
RoomFactory(get(), get(), 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) {
@ -109,10 +107,6 @@ class RoomModule {
DefaultFindReactionEventForUndoTask(get()) as FindReactionEventForUndoTask
}
scope(DefaultSession.SCOPE) {
DefaultUpdateQuickReactionTask(get()) as UpdateQuickReactionTask
}
scope(DefaultSession.SCOPE) {
DefaultPruneEventTask(get()) as PruneEventTask
}

View File

@ -46,7 +46,6 @@ import timber.log.Timber
internal class DefaultRelationService(private val roomId: String,
private val eventFactory: LocalEchoEventFactory,
private val findReactionEventForUndoTask: FindReactionEventForUndoTask,
private val updateQuickReactionTask: UpdateQuickReactionTask,
private val monarchy: Monarchy,
private val taskExecutor: TaskExecutor)
: RelationService {
@ -105,31 +104,6 @@ internal class DefaultRelationService(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 redactEvent = eventFactory.createRedactEvent(roomId, it, null).also {
saveLocalEcho(it)
}
val redactWork = createRedactEventWork(redactEvent, it, null)
TimelineSendEventWorkCommon.postWork(roomId, redactWork)
}
}
})
.executeBy(taskExecutor)
}
private fun buildWorkIdentifier(identifier: String): String {
return "${roomId}_$identifier"

View File

@ -1,89 +0,0 @@
/*
* 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.relation
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 suspend 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)
}
}
}