Read marker: final refact [WIP]

This commit is contained in:
ganfra 2019-09-24 22:52:43 +02:00
parent c6d01fbcf4
commit 63b43de4b8
17 changed files with 152 additions and 115 deletions

View file

@ -37,7 +37,7 @@ class ReadMarkerView @JvmOverloads constructor(
) : View(context, attrs, defStyleAttr) {
interface Callback {
fun onReadMarkerLongBound()
fun onReadMarkerLongBound(isDisplayed: Boolean)
}
private var eventId: String? = null
@ -57,7 +57,7 @@ class ReadMarkerView @JvmOverloads constructor(
if (hasReadMarker) {
callbackDispatcherJob = GlobalScope.launch(Dispatchers.Main) {
delay(DELAY_IN_MS)
callback?.onReadMarkerLongBound()
callback?.onReadMarkerLongBound(displayReadMarker)
}
}
}

View file

@ -30,10 +30,25 @@ class ReadMarkerHelper @Inject constructor() {
lateinit var layoutManager: LinearLayoutManager
var callback: Callback? = null
private var onReadMarkerLongDisplayed = false
private var readMarkerVisible: Boolean = true
private var state: RoomDetailViewState? = null
fun updateState(state: RoomDetailViewState) {
this.state = state
fun readMarkerVisible(): Boolean {
return readMarkerVisible
}
fun onResume() {
onReadMarkerLongDisplayed = false
}
fun onReadMarkerLongDisplayed() {
onReadMarkerLongDisplayed = true
}
fun updateWith(newState: RoomDetailViewState) {
state = newState
checkReadMarkerVisibility()
checkJumpToReadMarkerVisibility()
}
@ -41,34 +56,47 @@ class ReadMarkerHelper @Inject constructor() {
checkJumpToReadMarkerVisibility()
}
private fun checkReadMarkerVisibility() {
val nonNullState = this.state ?: return
val firstVisibleItem = layoutManager.findFirstVisibleItemPosition()
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
readMarkerVisible = if (!onReadMarkerLongDisplayed) {
true
} else {
if (nonNullState.timeline?.isLive == false) {
true
} else {
!(firstVisibleItem == 0 && lastVisibleItem > 0)
}
}
}
private fun checkJumpToReadMarkerVisibility() {
val nonNullState = this.state ?: return
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
val readMarkerId = nonNullState.asyncRoomSummary()?.readMarkerId
if (readMarkerId == null) {
callback?.onVisibilityUpdated(false, null)
callback?.onJumpToReadMarkerVisibilityUpdate(false, null)
}
val positionOfReadMarker = timelineEventController.searchPositionOfEvent(readMarkerId)
Timber.v("Position of readMarker: $positionOfReadMarker")
Timber.v("Position of lastVisibleItem: $lastVisibleItem")
if (positionOfReadMarker == null) {
if (nonNullState.timeline?.isLive == true && lastVisibleItem > 0) {
callback?.onVisibilityUpdated(true, readMarkerId)
callback?.onJumpToReadMarkerVisibilityUpdate(true, readMarkerId)
} else {
callback?.onVisibilityUpdated(false, readMarkerId)
callback?.onJumpToReadMarkerVisibilityUpdate(false, readMarkerId)
}
} else {
if (positionOfReadMarker > lastVisibleItem) {
callback?.onVisibilityUpdated(true, readMarkerId)
callback?.onJumpToReadMarkerVisibilityUpdate(true, readMarkerId)
} else {
callback?.onVisibilityUpdated(false, readMarkerId)
callback?.onJumpToReadMarkerVisibilityUpdate(false, readMarkerId)
}
}
}
interface Callback {
fun onVisibilityUpdated(show: Boolean, readMarkerId: String?)
fun onJumpToReadMarkerVisibilityUpdate(show: Boolean, readMarkerId: String?)
}

View file

@ -28,12 +28,7 @@ import android.os.Parcelable
import android.text.Editable
import android.text.Spannable
import android.text.TextUtils
import android.view.HapticFeedbackConstants
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.Window
import android.view.*
import android.view.inputmethod.InputMethodManager
import android.widget.TextView
import android.widget.Toast
@ -51,13 +46,7 @@ import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import com.airbnb.epoxy.EpoxyModel
import com.airbnb.epoxy.EpoxyVisibilityTracker
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.args
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import com.airbnb.mvrx.*
import com.github.piasy.biv.BigImageViewer
import com.github.piasy.biv.loader.ImageLoader
import com.google.android.material.snackbar.Snackbar
@ -71,13 +60,7 @@ import im.vector.matrix.android.api.permalinks.PermalinkFactory
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.events.model.Event
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.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.MessageTextContent
import im.vector.matrix.android.api.session.room.model.message.MessageType
import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
import im.vector.matrix.android.api.session.room.model.message.*
import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
@ -124,17 +107,8 @@ import im.vector.riotx.features.home.room.detail.composer.TextComposerViewModel
import im.vector.riotx.features.home.room.detail.composer.TextComposerViewState
import im.vector.riotx.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
import im.vector.riotx.features.home.room.detail.timeline.action.ActionsHandler
import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
import im.vector.riotx.features.home.room.detail.timeline.action.SimpleAction
import im.vector.riotx.features.home.room.detail.timeline.action.ViewEditHistoryBottomSheet
import im.vector.riotx.features.home.room.detail.timeline.action.ViewReactionBottomSheet
import im.vector.riotx.features.home.room.detail.timeline.item.AbsMessageItem
import im.vector.riotx.features.home.room.detail.timeline.item.MessageFileItem
import im.vector.riotx.features.home.room.detail.timeline.item.MessageImageVideoItem
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
import im.vector.riotx.features.home.room.detail.timeline.item.MessageTextItem
import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData
import im.vector.riotx.features.home.room.detail.timeline.action.*
import im.vector.riotx.features.home.room.detail.timeline.item.*
import im.vector.riotx.features.html.EventHtmlRenderer
import im.vector.riotx.features.html.PillImageSpan
import im.vector.riotx.features.invite.VectorInviteView
@ -432,8 +406,8 @@ class RoomDetailFragment :
}
override fun onResume() {
readMarkerHelper.onResume()
super.onResume()
notificationDrawerManager.setCurrentRoom(roomDetailArgs.roomId)
}
@ -483,7 +457,7 @@ class RoomDetailFragment :
readMarkerHelper.timelineEventController = timelineEventController
readMarkerHelper.layoutManager = layoutManager
readMarkerHelper.callback = object : ReadMarkerHelper.Callback {
override fun onVisibilityUpdated(show: Boolean, readMarkerId: String?) {
override fun onJumpToReadMarkerVisibilityUpdate(show: Boolean, readMarkerId: String?) {
jumpToReadMarkerView.render(show, readMarkerId)
}
}
@ -707,13 +681,13 @@ class RoomDetailFragment :
}
private fun renderState(state: RoomDetailViewState) {
readMarkerHelper.updateState(state)
readMarkerHelper.updateWith(state)
renderRoomSummary(state)
val summary = state.asyncRoomSummary()
val inviter = state.asyncInviter()
if (summary?.membership == Membership.JOIN) {
scrollOnHighlightedEventCallback.timeline = state.timeline
timelineEventController.update(state)
timelineEventController.update(state, readMarkerHelper.readMarkerVisible())
inviteView.visibility = View.GONE
val uid = session.myUserId
val meMember = session.getRoom(state.roomId)?.getRoomMember(uid)
@ -974,7 +948,10 @@ class RoomDetailFragment :
.show(requireActivity().supportFragmentManager, "DISPLAY_READ_RECEIPTS")
}
override fun onReadMarkerLongDisplayed() = withState(roomDetailViewModel) { state ->
override fun onReadMarkerLongBound(isDisplayed: Boolean) {
if (isDisplayed) {
readMarkerHelper.onReadMarkerLongDisplayed()
}
val firstVisibleItem = layoutManager.findFirstVisibleItemPosition()
val nextReadMarkerId = timelineEventController.searchEventIdAtPosition(firstVisibleItem)
if (nextReadMarkerId != null) {
@ -982,6 +959,7 @@ class RoomDetailFragment :
}
}
// AutocompleteUserPresenter.Callback
override fun onQueryUsers(query: CharSequence?) {

View file

@ -21,8 +21,6 @@ import android.text.TextUtils
import androidx.annotation.IdRes
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import arrow.core.Option
import arrow.core.getOrElse
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.Success
@ -43,13 +41,11 @@ import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.model.message.MessageType
import im.vector.matrix.android.api.session.room.model.message.getFileUrl
import im.vector.matrix.android.api.session.room.model.relation.ReactionContent
import im.vector.matrix.android.api.session.room.model.tombstone.RoomTombstoneContent
import im.vector.matrix.android.api.session.room.send.UserDraft
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.api.session.room.timeline.getTextEditableContent
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
import im.vector.matrix.rx.rx
@ -62,11 +58,11 @@ import im.vector.riotx.core.utils.LiveEvent
import im.vector.riotx.core.utils.subscribeLogError
import im.vector.riotx.features.command.CommandParser
import im.vector.riotx.features.command.ParsedCommand
import im.vector.riotx.features.home.room.detail.timeline.TimelineLayoutManagerHolder
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
import im.vector.riotx.features.settings.VectorPreferences
import io.reactivex.Observable
import io.reactivex.functions.BiFunction
import io.reactivex.functions.Function3
import io.reactivex.rxkotlin.subscribeBy
import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer
@ -76,6 +72,7 @@ import java.util.concurrent.TimeUnit
class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState,
private val timelineLayoutManagerHolder: TimelineLayoutManagerHolder,
private val userPreferencesProvider: UserPreferencesProvider,
private val vectorPreferences: VectorPreferences,
private val session: Session
@ -119,8 +116,9 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
observeRoomSummary()
observeEventDisplayedActions()
observeSummaryState()
observeReadMarkerVisibility()
observeDrafts()
observeReadMarkerVisibility()
observeOwnState()
room.rx().loadRoomMembersIfNeeded().subscribeLogError().disposeOnClear()
timeline.start()
setState { copy(timeline = this@RoomDetailViewModel.timeline) }
@ -711,23 +709,6 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
}
}
private fun observeReadMarkerVisibility() {
Observable
.combineLatest(
room.rx().liveReadMarker(),
room.rx().liveReadReceipt(),
BiFunction<Optional<String>, Optional<String>, Boolean> { readMarker, readReceipt ->
readMarker.getOrNull() == readReceipt.getOrNull()
}
)
.startWith(false)
.subscribe {
setState { copy(hideReadMarker = it) }
}
.disposeOnClear()
}
private fun observeSummaryState() {
asyncSubscribe(RoomDetailViewState::asyncRoomSummary) { summary ->
if (summary.membership == Membership.INVITE) {
@ -743,6 +724,22 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
}
}
private fun observeReadMarkerVisibility() {
Observable
.combineLatest(
room.rx().liveReadMarker(),
room.rx().liveReadReceipt(),
BiFunction<Optional<String>, Optional<String>, Boolean> { readMarker, readReceipt ->
readMarker.getOrNull() != readReceipt.getOrNull()
}
)
.subscribe {
setState { copy(readMarkerVisible = it) }
}
.disposeOnClear()
}
override fun onCleared() {
timeline.dispose()
super.onCleared()

View file

@ -53,7 +53,7 @@ data class RoomDetailViewState(
val tombstoneEventHandling: Async<String> = Uninitialized,
val syncState: SyncState = SyncState.IDLE,
val highlightedEventId: String? = null,
val hideReadMarker: Boolean = false
val readMarkerVisible: Boolean = false
) : MvRxState {
constructor(args: RoomDetailArgs) : this(roomId = args.roomId, eventId = args.eventId)

View file

@ -34,7 +34,10 @@ import im.vector.riotx.core.extensions.localDateTime
import im.vector.riotx.features.home.room.detail.RoomDetailViewState
import im.vector.riotx.features.home.room.detail.timeline.factory.MergedHeaderItemFactory
import im.vector.riotx.features.home.room.detail.timeline.factory.TimelineItemFactory
import im.vector.riotx.features.home.room.detail.timeline.helper.*
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineEventDiffUtilCallback
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineEventVisibilityStateChangedListener
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
import im.vector.riotx.features.home.room.detail.timeline.helper.nextOrNull
import im.vector.riotx.features.home.room.detail.timeline.item.*
import im.vector.riotx.features.media.ImageContentRenderer
import im.vector.riotx.features.media.VideoContentRenderer
@ -79,7 +82,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
interface ReadReceiptsCallback {
fun onReadReceiptsClicked(readReceipts: List<ReadReceiptData>)
fun onReadMarkerLongDisplayed()
fun onReadMarkerLongBound(isDisplayed: Boolean)
}
interface UrlClickCallback {
@ -141,7 +144,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
requestModelBuild()
}
fun update(viewState: RoomDetailViewState) {
fun update(viewState: RoomDetailViewState, readMarkerVisible: Boolean) {
if (timeline != viewState.timeline) {
timeline = viewState.timeline
timeline?.listener = this
@ -166,8 +169,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
eventIdToHighlight = viewState.highlightedEventId
requestModelBuild = true
}
if (hideReadMarker != viewState.hideReadMarker) {
hideReadMarker = viewState.hideReadMarker
if (this.readMarkerVisible != readMarkerVisible) {
this.readMarkerVisible = readMarkerVisible
requestModelBuild = true
}
if (requestModelBuild) {
@ -175,7 +178,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
}
}
private var hideReadMarker: Boolean = false
private var readMarkerVisible: Boolean = false
private var eventIdToHighlight: String? = null
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
@ -255,11 +258,19 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
val date = event.root.localDateTime()
val nextDate = nextEvent?.root?.localDateTime()
val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
val eventModel = timelineItemFactory.create(event, nextEvent, eventIdToHighlight, hideReadMarker, callback).also {
val eventModel = timelineItemFactory.create(event, nextEvent, eventIdToHighlight, readMarkerVisible, callback).also {
it.id(event.localId)
it.setOnVisibilityStateChanged(TimelineEventVisibilityStateChangedListener(callback, event))
}
val mergedHeaderModel = mergedHeaderItemFactory.create(event, nextEvent, items, addDaySeparator, currentPosition, eventIdToHighlight, callback) {
val mergedHeaderModel = mergedHeaderItemFactory.create(event,
nextEvent = nextEvent,
items = items,
addDaySeparator = addDaySeparator,
readMarkerVisible = readMarkerVisible,
currentPosition = currentPosition,
eventIdToHighlight = eventIdToHighlight,
callback = callback
) {
requestModelBuild()
}
val daySeparatorItem = buildDaySeparatorItem(addDaySeparator, date)

View file

@ -0,0 +1,29 @@
/*
* 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.riotx.features.home.room.detail.timeline
import androidx.recyclerview.widget.LinearLayoutManager
import im.vector.riotx.core.di.ScreenScope
import javax.inject.Inject
@ScreenScope
class TimelineLayoutManagerHolder @Inject constructor() {
lateinit var layoutManager: LinearLayoutManager
}

View file

@ -31,7 +31,7 @@ class DefaultItemFactory @Inject constructor(private val avatarSizeProvider: Ava
fun create(event: TimelineEvent,
highlight: Boolean,
hideReadMarker: Boolean,
readMarkerVisible: Boolean,
callback: TimelineEventController.Callback?,
exception: Exception? = null): DefaultItem? {
val text = if (exception == null) {
@ -40,7 +40,7 @@ class DefaultItemFactory @Inject constructor(private val avatarSizeProvider: Ava
"an exception occurred when rendering the event ${event.root.eventId}"
}
val informationData = informationDataFactory.create(event, null, hideReadMarker)
val informationData = informationDataFactory.create(event, null, readMarkerVisible)
return DefaultItem_()
.leftGuideline(avatarSizeProvider.leftGuideline)

View file

@ -41,7 +41,7 @@ class EncryptedItemFactory @Inject constructor(private val messageInformationDat
fun create(event: TimelineEvent,
nextEvent: TimelineEvent?,
highlight: Boolean,
hideReadMarker: Boolean,
readMarkerVisible: Boolean,
callback: TimelineEventController.Callback?): VectorEpoxyModel<*>? {
event.root.eventId ?: return null
@ -65,7 +65,7 @@ class EncryptedItemFactory @Inject constructor(private val messageInformationDat
// TODO This is not correct format for error, change it
val informationData = messageInformationDataFactory.create(event, nextEvent, hideReadMarker)
val informationData = messageInformationDataFactory.create(event, nextEvent, readMarkerVisible)
val attributes = attributesFactory.create(null, informationData, callback)
return MessageTextItem_()
.leftGuideline(avatarSizeProvider.leftGuideline)

View file

@ -18,15 +18,9 @@ package im.vector.riotx.features.home.room.detail.timeline.factory
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.riotx.core.di.ActiveSessionHolder
import im.vector.riotx.core.extensions.displayReadMarker
import im.vector.riotx.features.home.AvatarRenderer
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider
import im.vector.riotx.features.home.room.detail.timeline.helper.MergedTimelineEventVisibilityStateChangedListener
import im.vector.riotx.features.home.room.detail.timeline.helper.canBeMerged
import im.vector.riotx.features.home.room.detail.timeline.helper.prevSameTypeEvents
import im.vector.riotx.features.home.room.detail.timeline.helper.senderAvatar
import im.vector.riotx.features.home.room.detail.timeline.helper.senderName
import im.vector.riotx.features.home.room.detail.timeline.helper.*
import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem
import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem_
import javax.inject.Inject
@ -42,6 +36,7 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act
nextEvent: TimelineEvent?,
items: List<TimelineEvent>,
addDaySeparator: Boolean,
readMarkerVisible: Boolean,
currentPosition: Int,
eventIdToHighlight: String?,
callback: TimelineEventController.Callback?,
@ -67,7 +62,7 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act
if (readMarkerId == null && mergedEvent.hasReadMarker) {
readMarkerId = mergedEvent.root.eventId
}
if (!showReadMarker && mergedEvent.displayReadMarker(sessionHolder.getActiveSession().myUserId)) {
if (!showReadMarker && mergedEvent.hasReadMarker && readMarkerVisible) {
showReadMarker = true
}
val senderAvatar = mergedEvent.senderAvatar()

View file

@ -76,12 +76,12 @@ class MessageItemFactory @Inject constructor(
fun create(event: TimelineEvent,
nextEvent: TimelineEvent?,
highlight: Boolean,
hideReadMarker: Boolean,
readMarkerVisible: Boolean,
callback: TimelineEventController.Callback?
): VectorEpoxyModel<*>? {
event.root.eventId ?: return null
val informationData = messageInformationDataFactory.create(event, nextEvent, hideReadMarker)
val informationData = messageInformationDataFactory.create(event, nextEvent, readMarkerVisible)
if (event.root.isRedacted()) {
//message is redacted
@ -98,7 +98,7 @@ class MessageItemFactory @Inject constructor(
|| event.isEncrypted() && event.root.content.toModel<EncryptedEventContent>()?.relatesTo?.type == RelationType.REPLACE
) {
// This is an edit event, we should it when debugging as a notice event
return noticeItemFactory.create(event, highlight, hideReadMarker, callback)
return noticeItemFactory.create(event, highlight, readMarkerVisible, callback)
}
val attributes = messageItemAttributesFactory.create(messageContent, informationData, callback)

View file

@ -34,11 +34,11 @@ class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEv
fun create(event: TimelineEvent,
highlight: Boolean,
hideReadMarker: Boolean,
readMarkerVisible: Boolean,
callback: TimelineEventController.Callback?): NoticeItem? {
val formattedText = eventFormatter.format(event) ?: return null
val informationData = informationDataFactory.create(event, null, hideReadMarker)
val informationData = informationDataFactory.create(event, null, readMarkerVisible)
val attributes = NoticeItem.Attributes(
avatarRenderer = avatarRenderer,
informationData = informationData,

View file

@ -33,14 +33,14 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
fun create(event: TimelineEvent,
nextEvent: TimelineEvent?,
eventIdToHighlight: String?,
hideReadMarker: Boolean,
readMarkerVisible: Boolean,
callback: TimelineEventController.Callback?): VectorEpoxyModel<*> {
val highlight = event.root.eventId == eventIdToHighlight
val computedModel = try {
when (event.root.getClearType()) {
EventType.MESSAGE -> messageItemFactory.create(event, nextEvent, highlight, hideReadMarker, callback)
EventType.MESSAGE -> messageItemFactory.create(event, nextEvent, highlight, readMarkerVisible, callback)
// State and call
EventType.STATE_ROOM_TOMBSTONE,
EventType.STATE_ROOM_NAME,
@ -52,22 +52,22 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
EventType.CALL_ANSWER,
EventType.REACTION,
EventType.REDACTION,
EventType.ENCRYPTION -> noticeItemFactory.create(event, highlight, hideReadMarker, callback)
EventType.ENCRYPTION -> noticeItemFactory.create(event, highlight, readMarkerVisible, callback)
// State room create
EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(event, callback)
// Crypto
EventType.ENCRYPTED -> {
if (event.root.isRedacted()) {
// Redacted event, let the MessageItemFactory handle it
messageItemFactory.create(event, nextEvent, highlight, hideReadMarker, callback)
messageItemFactory.create(event, nextEvent, highlight, readMarkerVisible, callback)
} else {
encryptedItemFactory.create(event, nextEvent, highlight, hideReadMarker, callback)
encryptedItemFactory.create(event, nextEvent, highlight, readMarkerVisible, callback)
}
}
// Unhandled event types (yet)
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
EventType.STICKER -> defaultItemFactory.create(event, highlight, hideReadMarker, callback)
EventType.STICKER -> defaultItemFactory.create(event, highlight, readMarkerVisible, callback)
else -> {
Timber.v("Type ${event.root.getClearType()} not handled")
null
@ -75,7 +75,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
}
} catch (e: Exception) {
Timber.e(e, "failed to create message item")
defaultItemFactory.create(event, highlight, hideReadMarker, callback, e)
defaultItemFactory.create(event, highlight, readMarkerVisible, callback, e)
}
return (computedModel ?: EmptyItem_())
}

View file

@ -24,10 +24,8 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.api.session.room.timeline.hasBeenEdited
import im.vector.riotx.core.extensions.localDateTime
import im.vector.riotx.core.resources.ColorProvider
import im.vector.riotx.core.utils.isSingleEmoji
import im.vector.riotx.features.home.getColorFromUserId
import im.vector.riotx.core.date.VectorDateFormatter
import im.vector.riotx.core.extensions.displayReadMarker
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
import im.vector.riotx.features.home.room.detail.timeline.item.ReactionInfoData
import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData
@ -41,7 +39,7 @@ class MessageInformationDataFactory @Inject constructor(private val session: Ses
private val dateFormatter: VectorDateFormatter,
private val colorProvider: ColorProvider) {
fun create(event: TimelineEvent, nextEvent: TimelineEvent?, hideReadMarker: Boolean): MessageInformationData {
fun create(event: TimelineEvent, nextEvent: TimelineEvent?, readMarkerVisible: Boolean): MessageInformationData {
// Non nullability has been tested before
val eventId = event.root.eventId!!
@ -65,7 +63,7 @@ class MessageInformationDataFactory @Inject constructor(private val session: Ses
textColor = colorProvider.getColor(getColorFromUserId(event.root.senderId ?: ""))
}
val displayReadMarker = !hideReadMarker && event.displayReadMarker(session.myUserId)
val displayReadMarker = readMarkerVisible && event.hasReadMarker
return MessageInformationData(
eventId = eventId,

View file

@ -57,8 +57,8 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
private val _readMarkerCallback = object : ReadMarkerView.Callback {
override fun onReadMarkerLongBound() {
attributes.readReceiptsCallback?.onReadMarkerLongDisplayed()
override fun onReadMarkerLongBound(isDisplayed: Boolean) {
attributes.readReceiptsCallback?.onReadMarkerLongBound(isDisplayed)
}
}

View file

@ -41,8 +41,8 @@ abstract class MergedHeaderItem : BaseEventItem<MergedHeaderItem.Holder>() {
private val _readMarkerCallback = object : ReadMarkerView.Callback {
override fun onReadMarkerLongBound() {
attributes.readReceiptsCallback?.onReadMarkerLongDisplayed()
override fun onReadMarkerLongBound(isDisplayed: Boolean) {
attributes.readReceiptsCallback?.onReadMarkerLongBound(isDisplayed)
}
}

View file

@ -38,8 +38,9 @@ abstract class NoticeItem : BaseEventItem<NoticeItem.Holder>() {
})
private val _readMarkerCallback = object : ReadMarkerView.Callback {
override fun onReadMarkerLongBound() {
attributes.readReceiptsCallback?.onReadMarkerLongDisplayed()
override fun onReadMarkerLongBound(isDisplayed: Boolean) {
attributes.readReceiptsCallback?.onReadMarkerLongBound(isDisplayed)
}
}