()
@@ -30,20 +33,22 @@ internal class TimelineEventFactory(private val roomMemberExtractor: SenderRoomM
val sender = eventEntity.sender
val cacheKey = sender + eventEntity.stateIndex
val senderData = cached.getOrPut(cacheKey) {
- val senderRoomMember = roomMemberExtractor.extractFrom(eventEntity,realm)
+ val senderRoomMember = roomMemberExtractor.extractFrom(eventEntity, realm)
SenderData(senderRoomMember?.displayName, senderRoomMember?.avatarUrl)
}
+ val relations = relationExtractor.extractFrom(eventEntity, realm)
return TimelineEvent(
eventEntity.asDomain(),
eventEntity.localId,
eventEntity.displayIndex,
senderData.senderName,
senderData.senderAvatar,
- eventEntity.sendState
+ eventEntity.sendState,
+ relations
)
}
- fun clear(){
+ fun clear() {
cached.clear()
}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt
index 283b807c7e..ec85c558ac 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TokenChunkEventPersistor.kt
@@ -24,12 +24,14 @@ import im.vector.matrix.android.internal.database.helper.addStateEvents
import im.vector.matrix.android.internal.database.helper.deleteOnCascade
import im.vector.matrix.android.internal.database.helper.isUnlinked
import im.vector.matrix.android.internal.database.helper.merge
+import im.vector.matrix.android.internal.database.mapper.EventMapper
import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.query.create
import im.vector.matrix.android.internal.database.query.find
import im.vector.matrix.android.internal.database.query.findAllIncludingEvents
import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.room.EventRelationsAggregationUpdater
import im.vector.matrix.android.internal.util.tryTransactionSync
import io.realm.kotlin.createObject
import timber.log.Timber
@@ -37,7 +39,8 @@ import timber.log.Timber
/**
* Insert Chunk in DB, and eventually merge with existing chunk event
*/
-internal class TokenChunkEventPersistor(private val monarchy: Monarchy) {
+internal class TokenChunkEventPersistor(private val monarchy: Monarchy,
+ private val eventRelationsAggregationUpdater: EventRelationsAggregationUpdater) {
/**
*
@@ -147,6 +150,9 @@ internal class TokenChunkEventPersistor(private val monarchy: Monarchy) {
} else {
Timber.v("Add ${receivedChunk.events.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}")
currentChunk.addAll(roomId, receivedChunk.events, direction, isUnlinked = currentChunk.isUnlinked())
+
+ //Event
+ eventRelationsAggregationUpdater.update(realm,roomId,receivedChunk.events.toList())
// Then we merge chunks if needed
if (currentChunk != prevChunk && prevChunk != null) {
currentChunk = handleMerge(roomEntity, direction, currentChunk, prevChunk)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
index 24dff3398a..d5ec714c7b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt
@@ -31,6 +31,7 @@ import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.query.find
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
import im.vector.matrix.android.internal.database.query.where
+import im.vector.matrix.android.internal.session.room.EventRelationsAggregationUpdater
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
@@ -45,7 +46,8 @@ import timber.log.Timber
internal class RoomSyncHandler(private val monarchy: Monarchy,
private val readReceiptHandler: ReadReceiptHandler,
private val roomSummaryUpdater: RoomSummaryUpdater,
- private val roomTagHandler: RoomTagHandler) {
+ private val roomTagHandler: RoomTagHandler,
+ private val eventRelationsAggregationUpdater: EventRelationsAggregationUpdater) {
sealed class HandlingStrategy {
data class JOINED(val data: Map) : HandlingStrategy()
@@ -120,6 +122,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
}
}
roomSummaryUpdater.update(realm, roomId, roomSync.summary, roomSync.unreadNotifications)
+ eventRelationsAggregationUpdater.update(realm,roomId,roomSync.timeline?.events)
if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) {
handleEphemeral(realm, roomId, roomSync.ephemeral)
@@ -174,6 +177,9 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
lastChunk?.isLastForward = false
chunkEntity.isLastForward = true
chunkEntity.addAll(roomId, eventList, PaginationDirection.FORWARDS, stateIndexOffset)
+
+ //update eventAnnotationSummary here?
+
return chunkEntity
}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
index d0f6040520..d601406116 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt
@@ -40,7 +40,7 @@ internal class SyncModule {
}
scope(DefaultSession.SCOPE) {
- RoomSyncHandler(get(), get(), get(), get())
+ RoomSyncHandler(get(), get(), get(), get(), get())
}
scope(DefaultSession.SCOPE) {
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
index 60d1aebbbb..507bf4cd93 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/RoomDetailFragment.kt
@@ -59,6 +59,7 @@ import im.vector.matrix.android.api.session.user.model.User
import im.vector.riotredesign.R
import im.vector.riotredesign.core.dialogs.DialogListItem
import im.vector.riotredesign.core.epoxy.LayoutManagerStateRestorer
+import im.vector.riotredesign.core.extensions.hideKeyboard
import im.vector.riotredesign.core.extensions.observeEvent
import im.vector.riotredesign.core.glide.GlideApp
import im.vector.riotredesign.core.platform.ToolbarConfigurable
@@ -460,6 +461,7 @@ class RoomDetailFragment :
Timber.e("Missing RoomId, cannot open bottomsheet")
return false
}
+ this.view?.hideKeyboard()
MessageActionsBottomSheet
.newInstance(roomId, informationData)
.show(requireActivity().supportFragmentManager, "MESSAGE_CONTEXTUAL_ACTIONS")
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
index 320332ba43..180bacc09f 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/MessageActionsBottomSheet.kt
@@ -89,7 +89,7 @@ class MessageActionsBottomSheet : BaseMvRxBottomSheetDialog() {
var quickReactionFragment = cfm.findFragmentByTag("QuickReaction") as? QuickReactionFragment
if (quickReactionFragment == null) {
- quickReactionFragment = QuickReactionFragment.newInstance()
+ quickReactionFragment = QuickReactionFragment.newInstance(arguments!!.get(MvRx.KEY_ARG) as ParcelableArgs)
cfm.beginTransaction()
.replace(R.id.bottom_sheet_quick_reaction_container, quickReactionFragment, "QuickReaction")
.commit()
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt
index a8593a2e97..70bb18c6c6 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionFragment.kt
@@ -25,6 +25,7 @@ import androidx.transition.TransitionManager
import butterknife.BindView
import butterknife.ButterKnife
import com.airbnb.mvrx.BaseMvRxFragment
+import com.airbnb.mvrx.MvRx
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import im.vector.riotredesign.R
@@ -62,10 +63,10 @@ class QuickReactionFragment : BaseMvRxFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- quickReact1Text.text = viewModel.agreePositive
- quickReact2Text.text = viewModel.agreeNegative
- quickReact3Text.text = viewModel.likePositive
- quickReact4Text.text = viewModel.likeNegative
+ quickReact1Text.text = QuickReactionViewModel.agreePositive
+ quickReact2Text.text = QuickReactionViewModel.agreeNegative
+ quickReact3Text.text = QuickReactionViewModel.likePositive
+ quickReact4Text.text = QuickReactionViewModel.likeNegative
//configure click listeners
quickReact1Text.setOnClickListener {
@@ -127,8 +128,12 @@ class QuickReactionFragment : BaseMvRxFragment() {
}
companion object {
- fun newInstance(): QuickReactionFragment {
- return QuickReactionFragment()
+ fun newInstance(pa: MessageActionsBottomSheet.ParcelableArgs): QuickReactionFragment {
+ val args = Bundle()
+ args.putParcelable(MvRx.KEY_ARG, pa)
+ val fragment = QuickReactionFragment()
+ fragment.arguments = args
+ return fragment
}
}
}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionViewModel.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionViewModel.kt
index a4b9834444..2bc1a8dd55 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionViewModel.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/action/QuickReactionViewModel.kt
@@ -18,7 +18,9 @@ package im.vector.riotredesign.features.home.room.detail.timeline.action
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
+import im.vector.matrix.android.api.session.Session
import im.vector.riotredesign.core.platform.VectorViewModel
+import org.koin.android.ext.android.get
/**
* Quick reactions state, it's a toggle with 3rd state
@@ -37,11 +39,6 @@ data class QuickReactionState(val agreeTrigleState: TriggleState, val likeTriggl
*/
class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel(initialState) {
- val agreePositive = "đ"
- val agreeNegative = "đ"
- val likePositive = "đ"
- val likeNegative = "đ"
-
fun toggleAgree(isFirst: Boolean) = withState {
if (isFirst) {
@@ -99,10 +96,37 @@ class QuickReactionViewModel(initialState: QuickReactionState) : VectorViewModel
companion object : MvRxViewModelFactory {
+ val agreePositive = "đ"
+ val agreeNegative = "đ"
+ val likePositive = "đ"
+ val likeNegative = "đ"
+
override fun initialState(viewModelContext: ViewModelContext): QuickReactionState? {
// Args are accessible from the context.
// val foo = vieWModelContext.args.foo
- return QuickReactionState(TriggleState.NONE, TriggleState.NONE)
+ val currentSession = viewModelContext.activity.get()
+ val parcel = viewModelContext.args as MessageActionsBottomSheet.ParcelableArgs
+ val event = currentSession.getRoom(parcel.roomId)?.getTimeLineEvent(parcel.eventId)
+ ?: return null
+ var agreeTriggle: TriggleState = TriggleState.NONE
+ var likeTriggle: TriggleState = TriggleState.NONE
+ event.annotations?.reactionsSummary?.forEach {
+ //it.addedByMe
+ if (it.addedByMe) {
+ if (agreePositive == it.key) {
+ agreeTriggle = TriggleState.FIRST
+ } else if (agreeNegative == it.key) {
+ agreeTriggle = TriggleState.SECOND
+ }
+
+ if (likePositive == it.key) {
+ likeTriggle = TriggleState.FIRST
+ } else if (likeNegative == it.key) {
+ likeTriggle = TriggleState.SECOND
+ }
+ }
+ }
+ return QuickReactionState(agreeTriggle, likeTriggle)
}
}
}
\ No newline at end of file
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt
index f8ba03de0e..8afdf200a8 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/factory/MessageItemFactory.kt
@@ -71,7 +71,8 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
val avatarUrl = event.senderAvatar
val memberName = event.senderName ?: event.root.sender ?: ""
val formattedMemberName = span(memberName) {
- textColor = colorProvider.getColor(AvatarRenderer.getColorFromUserId(event.root.sender ?: ""))
+ textColor = colorProvider.getColor(AvatarRenderer.getColorFromUserId(event.root.sender
+ ?: ""))
}
val informationData = MessageInformationData(eventId = eventId,
senderId = event.root.sender ?: "",
@@ -79,7 +80,9 @@ class MessageItemFactory(private val colorProvider: ColorProvider,
time = time,
avatarUrl = avatarUrl,
memberName = formattedMemberName,
- showInformation = showInformation)
+ showInformation = showInformation,
+ orderedReactionList = event.annotations?.reactionsSummary?.map { Triple(it.key, it.count, it.addedByMe) }
+ )
//Test for reactions UX
//informationData.orderedReactionList = listOf( Triple("đ",1,false), Triple("đ",2,false))
diff --git a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/AbsMessageItem.kt b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/AbsMessageItem.kt
index 94492e3638..045bb1c76d 100644
--- a/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/AbsMessageItem.kt
+++ b/vector/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/item/AbsMessageItem.kt
@@ -19,6 +19,7 @@ package im.vector.riotredesign.features.home.room.detail.timeline.item
import android.os.Build
import android.view.View
import android.view.ViewGroup
+import android.view.ViewStub
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.helper.widget.Flow
@@ -76,14 +77,19 @@ abstract class AbsMessageItem : BaseEventItem() {
holder.view.setOnLongClickListener(longClickListener)
if (informationData.orderedReactionList.isNullOrEmpty()) {
- holder.reactionWrapper.isVisible = false
+ holder.reactionWrapper?.isVisible = false
} else {
- holder.reactionWrapper.isVisible = true
+ //inflate if needed
+ if (holder.reactionFlowHelper == null) {
+ holder.reactionWrapper = holder.view.findViewById(R.id.messageBottomInfo).inflate() as? ViewGroup
+ holder.reactionFlowHelper = holder.view.findViewById(R.id.reactionsFlowHelper)
+ }
+ holder.reactionWrapper?.isVisible = true
//clear all reaction buttons (but not the Flow helper!)
- holder.reactionWrapper.children.forEach { (it as? ReactionButton)?.isGone = true }
+ holder.reactionWrapper?.children?.forEach { (it as? ReactionButton)?.isGone = true }
val idToRefInFlow = ArrayList()
informationData.orderedReactionList?.forEachIndexed { index, reaction ->
- (holder.reactionWrapper.children.elementAt(index) as? ReactionButton)?.let { reactionButton ->
+ (holder.reactionWrapper?.children?.elementAt(index) as? ReactionButton)?.let { reactionButton ->
reactionButton.isVisible = true
idToRefInFlow.add(reactionButton.id)
reactionButton.reactionString = reaction.first
@@ -93,9 +99,9 @@ abstract class AbsMessageItem : BaseEventItem() {
}
// Just setting the view as gone will break the FlowHelper (and invisible will take too much space),
// so have to update ref ids
- holder.reactionFlowHelper.referencedIds = idToRefInFlow.toIntArray()
+ holder.reactionFlowHelper?.referencedIds = idToRefInFlow.toIntArray()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && !holder.view.isInLayout) {
- holder.reactionFlowHelper.requestLayout()
+ holder.reactionFlowHelper?.requestLayout()
}
}
@@ -112,8 +118,8 @@ abstract class AbsMessageItem : BaseEventItem() {
val memberNameView by bind(R.id.messageMemberNameView)
val timeView by bind(R.id.messageTimeView)
- val reactionWrapper: ViewGroup by bind(R.id.messageBottomInfo)
- val reactionFlowHelper: Flow by bind(R.id.reactionsFlowHelper)
+ var reactionWrapper: ViewGroup? = null
+ var reactionFlowHelper: Flow? = null
}
}
\ No newline at end of file
diff --git a/vector/src/main/res/drawable/rounded_rect_shape.xml b/vector/src/main/res/drawable/rounded_rect_shape.xml
index dbb12374ae..cf083254f3 100644
--- a/vector/src/main/res/drawable/rounded_rect_shape.xml
+++ b/vector/src/main/res/drawable/rounded_rect_shape.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/vector/src/main/res/drawable/rounded_rect_shape_off.xml b/vector/src/main/res/drawable/rounded_rect_shape_off.xml
index e72c738356..8dac3020e3 100644
--- a/vector/src/main/res/drawable/rounded_rect_shape_off.xml
+++ b/vector/src/main/res/drawable/rounded_rect_shape_off.xml
@@ -4,9 +4,9 @@
-
+
-
+
diff --git a/vector/src/main/res/layout/item_timeline_event_base.xml b/vector/src/main/res/layout/item_timeline_event_base.xml
index 89c3b31871..dc2e2ed67e 100644
--- a/vector/src/main/res/layout/item_timeline_event_base.xml
+++ b/vector/src/main/res/layout/item_timeline_event_base.xml
@@ -82,116 +82,23 @@
tools:ignore="MissingConstraints" />
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/vector/src/main/res/layout/item_timeline_event_bottom_reactions_stub.xml b/vector/src/main/res/layout/item_timeline_event_bottom_reactions_stub.xml
new file mode 100644
index 0000000000..13ca78ae48
--- /dev/null
+++ b/vector/src/main/res/layout/item_timeline_event_bottom_reactions_stub.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vector/src/main/res/values/styles_riot.xml b/vector/src/main/res/values/styles_riot.xml
index 7ab2caa12a..530108f397 100644
--- a/vector/src/main/res/values/styles_riot.xml
+++ b/vector/src/main/res/values/styles_riot.xml
@@ -252,7 +252,7 @@
- wrap_content
- 8dp
- 8dp
- - 8dp
+ - 4dp
- 4dp
- parent
- parent