mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 21:48:50 +03:00
Read marker: final refact [WIP]
This commit is contained in:
parent
c6d01fbcf4
commit
63b43de4b8
17 changed files with 152 additions and 115 deletions
|
@ -37,7 +37,7 @@ class ReadMarkerView @JvmOverloads constructor(
|
||||||
) : View(context, attrs, defStyleAttr) {
|
) : View(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun onReadMarkerLongBound()
|
fun onReadMarkerLongBound(isDisplayed: Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var eventId: String? = null
|
private var eventId: String? = null
|
||||||
|
@ -57,7 +57,7 @@ class ReadMarkerView @JvmOverloads constructor(
|
||||||
if (hasReadMarker) {
|
if (hasReadMarker) {
|
||||||
callbackDispatcherJob = GlobalScope.launch(Dispatchers.Main) {
|
callbackDispatcherJob = GlobalScope.launch(Dispatchers.Main) {
|
||||||
delay(DELAY_IN_MS)
|
delay(DELAY_IN_MS)
|
||||||
callback?.onReadMarkerLongBound()
|
callback?.onReadMarkerLongBound(displayReadMarker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,25 @@ class ReadMarkerHelper @Inject constructor() {
|
||||||
lateinit var layoutManager: LinearLayoutManager
|
lateinit var layoutManager: LinearLayoutManager
|
||||||
var callback: Callback? = null
|
var callback: Callback? = null
|
||||||
|
|
||||||
|
private var onReadMarkerLongDisplayed = false
|
||||||
|
private var readMarkerVisible: Boolean = true
|
||||||
private var state: RoomDetailViewState? = null
|
private var state: RoomDetailViewState? = null
|
||||||
|
|
||||||
fun updateState(state: RoomDetailViewState) {
|
fun readMarkerVisible(): Boolean {
|
||||||
this.state = state
|
return readMarkerVisible
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onResume() {
|
||||||
|
onReadMarkerLongDisplayed = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onReadMarkerLongDisplayed() {
|
||||||
|
onReadMarkerLongDisplayed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateWith(newState: RoomDetailViewState) {
|
||||||
|
state = newState
|
||||||
|
checkReadMarkerVisibility()
|
||||||
checkJumpToReadMarkerVisibility()
|
checkJumpToReadMarkerVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,34 +56,47 @@ class ReadMarkerHelper @Inject constructor() {
|
||||||
checkJumpToReadMarkerVisibility()
|
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() {
|
private fun checkJumpToReadMarkerVisibility() {
|
||||||
val nonNullState = this.state ?: return
|
val nonNullState = this.state ?: return
|
||||||
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
|
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
|
||||||
val readMarkerId = nonNullState.asyncRoomSummary()?.readMarkerId
|
val readMarkerId = nonNullState.asyncRoomSummary()?.readMarkerId
|
||||||
if (readMarkerId == null) {
|
if (readMarkerId == null) {
|
||||||
callback?.onVisibilityUpdated(false, null)
|
callback?.onJumpToReadMarkerVisibilityUpdate(false, null)
|
||||||
}
|
}
|
||||||
val positionOfReadMarker = timelineEventController.searchPositionOfEvent(readMarkerId)
|
val positionOfReadMarker = timelineEventController.searchPositionOfEvent(readMarkerId)
|
||||||
Timber.v("Position of readMarker: $positionOfReadMarker")
|
|
||||||
Timber.v("Position of lastVisibleItem: $lastVisibleItem")
|
|
||||||
if (positionOfReadMarker == null) {
|
if (positionOfReadMarker == null) {
|
||||||
if (nonNullState.timeline?.isLive == true && lastVisibleItem > 0) {
|
if (nonNullState.timeline?.isLive == true && lastVisibleItem > 0) {
|
||||||
callback?.onVisibilityUpdated(true, readMarkerId)
|
callback?.onJumpToReadMarkerVisibilityUpdate(true, readMarkerId)
|
||||||
} else {
|
} else {
|
||||||
callback?.onVisibilityUpdated(false, readMarkerId)
|
callback?.onJumpToReadMarkerVisibilityUpdate(false, readMarkerId)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (positionOfReadMarker > lastVisibleItem) {
|
if (positionOfReadMarker > lastVisibleItem) {
|
||||||
callback?.onVisibilityUpdated(true, readMarkerId)
|
callback?.onJumpToReadMarkerVisibilityUpdate(true, readMarkerId)
|
||||||
} else {
|
} else {
|
||||||
callback?.onVisibilityUpdated(false, readMarkerId)
|
callback?.onJumpToReadMarkerVisibilityUpdate(false, readMarkerId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun onVisibilityUpdated(show: Boolean, readMarkerId: String?)
|
fun onJumpToReadMarkerVisibilityUpdate(show: Boolean, readMarkerId: String?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,7 @@ import android.os.Parcelable
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.HapticFeedbackConstants
|
import android.view.*
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.View
|
|
||||||
import android.view.Window
|
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
@ -51,13 +46,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import com.airbnb.epoxy.EpoxyModel
|
import com.airbnb.epoxy.EpoxyModel
|
||||||
import com.airbnb.epoxy.EpoxyVisibilityTracker
|
import com.airbnb.epoxy.EpoxyVisibilityTracker
|
||||||
import com.airbnb.mvrx.Async
|
import com.airbnb.mvrx.*
|
||||||
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.github.piasy.biv.BigImageViewer
|
import com.github.piasy.biv.BigImageViewer
|
||||||
import com.github.piasy.biv.loader.ImageLoader
|
import com.github.piasy.biv.loader.ImageLoader
|
||||||
import com.google.android.material.snackbar.Snackbar
|
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.Session
|
||||||
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.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.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.send.SendState
|
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.Timeline
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
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.composer.TextComposerViewState
|
||||||
import im.vector.riotx.features.home.room.detail.readreceipts.DisplayReadReceiptsBottomSheet
|
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.TimelineEventController
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.action.ActionsHandler
|
import im.vector.riotx.features.home.room.detail.timeline.action.*
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.action.MessageActionsBottomSheet
|
import im.vector.riotx.features.home.room.detail.timeline.item.*
|
||||||
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.html.EventHtmlRenderer
|
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||||
import im.vector.riotx.features.html.PillImageSpan
|
import im.vector.riotx.features.html.PillImageSpan
|
||||||
import im.vector.riotx.features.invite.VectorInviteView
|
import im.vector.riotx.features.invite.VectorInviteView
|
||||||
|
@ -432,8 +406,8 @@ class RoomDetailFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
readMarkerHelper.onResume()
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
notificationDrawerManager.setCurrentRoom(roomDetailArgs.roomId)
|
notificationDrawerManager.setCurrentRoom(roomDetailArgs.roomId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +457,7 @@ class RoomDetailFragment :
|
||||||
readMarkerHelper.timelineEventController = timelineEventController
|
readMarkerHelper.timelineEventController = timelineEventController
|
||||||
readMarkerHelper.layoutManager = layoutManager
|
readMarkerHelper.layoutManager = layoutManager
|
||||||
readMarkerHelper.callback = object : ReadMarkerHelper.Callback {
|
readMarkerHelper.callback = object : ReadMarkerHelper.Callback {
|
||||||
override fun onVisibilityUpdated(show: Boolean, readMarkerId: String?) {
|
override fun onJumpToReadMarkerVisibilityUpdate(show: Boolean, readMarkerId: String?) {
|
||||||
jumpToReadMarkerView.render(show, readMarkerId)
|
jumpToReadMarkerView.render(show, readMarkerId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -707,13 +681,13 @@ class RoomDetailFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderState(state: RoomDetailViewState) {
|
private fun renderState(state: RoomDetailViewState) {
|
||||||
readMarkerHelper.updateState(state)
|
readMarkerHelper.updateWith(state)
|
||||||
renderRoomSummary(state)
|
renderRoomSummary(state)
|
||||||
val summary = state.asyncRoomSummary()
|
val summary = state.asyncRoomSummary()
|
||||||
val inviter = state.asyncInviter()
|
val inviter = state.asyncInviter()
|
||||||
if (summary?.membership == Membership.JOIN) {
|
if (summary?.membership == Membership.JOIN) {
|
||||||
scrollOnHighlightedEventCallback.timeline = state.timeline
|
scrollOnHighlightedEventCallback.timeline = state.timeline
|
||||||
timelineEventController.update(state)
|
timelineEventController.update(state, readMarkerHelper.readMarkerVisible())
|
||||||
inviteView.visibility = View.GONE
|
inviteView.visibility = View.GONE
|
||||||
val uid = session.myUserId
|
val uid = session.myUserId
|
||||||
val meMember = session.getRoom(state.roomId)?.getRoomMember(uid)
|
val meMember = session.getRoom(state.roomId)?.getRoomMember(uid)
|
||||||
|
@ -974,7 +948,10 @@ class RoomDetailFragment :
|
||||||
.show(requireActivity().supportFragmentManager, "DISPLAY_READ_RECEIPTS")
|
.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 firstVisibleItem = layoutManager.findFirstVisibleItemPosition()
|
||||||
val nextReadMarkerId = timelineEventController.searchEventIdAtPosition(firstVisibleItem)
|
val nextReadMarkerId = timelineEventController.searchEventIdAtPosition(firstVisibleItem)
|
||||||
if (nextReadMarkerId != null) {
|
if (nextReadMarkerId != null) {
|
||||||
|
@ -982,6 +959,7 @@ class RoomDetailFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// AutocompleteUserPresenter.Callback
|
// AutocompleteUserPresenter.Callback
|
||||||
|
|
||||||
override fun onQueryUsers(query: CharSequence?) {
|
override fun onQueryUsers(query: CharSequence?) {
|
||||||
|
|
|
@ -21,8 +21,6 @@ import android.text.TextUtils
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import arrow.core.Option
|
|
||||||
import arrow.core.getOrElse
|
|
||||||
import com.airbnb.mvrx.FragmentViewModelContext
|
import com.airbnb.mvrx.FragmentViewModelContext
|
||||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
import com.airbnb.mvrx.Success
|
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.MessageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
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.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.model.tombstone.RoomTombstoneContent
|
||||||
import im.vector.matrix.android.api.session.room.send.UserDraft
|
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.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.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.attachments.toElementToDecrypt
|
||||||
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
|
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
|
||||||
import im.vector.matrix.rx.rx
|
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.core.utils.subscribeLogError
|
||||||
import im.vector.riotx.features.command.CommandParser
|
import im.vector.riotx.features.command.CommandParser
|
||||||
import im.vector.riotx.features.command.ParsedCommand
|
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.home.room.detail.timeline.helper.TimelineDisplayableEvents
|
||||||
import im.vector.riotx.features.settings.VectorPreferences
|
import im.vector.riotx.features.settings.VectorPreferences
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.functions.BiFunction
|
import io.reactivex.functions.BiFunction
|
||||||
import io.reactivex.functions.Function3
|
|
||||||
import io.reactivex.rxkotlin.subscribeBy
|
import io.reactivex.rxkotlin.subscribeBy
|
||||||
import org.commonmark.parser.Parser
|
import org.commonmark.parser.Parser
|
||||||
import org.commonmark.renderer.html.HtmlRenderer
|
import org.commonmark.renderer.html.HtmlRenderer
|
||||||
|
@ -76,6 +72,7 @@ import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
||||||
class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState,
|
class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: RoomDetailViewState,
|
||||||
|
private val timelineLayoutManagerHolder: TimelineLayoutManagerHolder,
|
||||||
private val userPreferencesProvider: UserPreferencesProvider,
|
private val userPreferencesProvider: UserPreferencesProvider,
|
||||||
private val vectorPreferences: VectorPreferences,
|
private val vectorPreferences: VectorPreferences,
|
||||||
private val session: Session
|
private val session: Session
|
||||||
|
@ -119,8 +116,9 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
observeRoomSummary()
|
observeRoomSummary()
|
||||||
observeEventDisplayedActions()
|
observeEventDisplayedActions()
|
||||||
observeSummaryState()
|
observeSummaryState()
|
||||||
observeReadMarkerVisibility()
|
|
||||||
observeDrafts()
|
observeDrafts()
|
||||||
|
observeReadMarkerVisibility()
|
||||||
|
observeOwnState()
|
||||||
room.rx().loadRoomMembersIfNeeded().subscribeLogError().disposeOnClear()
|
room.rx().loadRoomMembersIfNeeded().subscribeLogError().disposeOnClear()
|
||||||
timeline.start()
|
timeline.start()
|
||||||
setState { copy(timeline = this@RoomDetailViewModel.timeline) }
|
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() {
|
private fun observeSummaryState() {
|
||||||
asyncSubscribe(RoomDetailViewState::asyncRoomSummary) { summary ->
|
asyncSubscribe(RoomDetailViewState::asyncRoomSummary) { summary ->
|
||||||
if (summary.membership == Membership.INVITE) {
|
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() {
|
override fun onCleared() {
|
||||||
timeline.dispose()
|
timeline.dispose()
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
|
|
|
@ -53,7 +53,7 @@ data class RoomDetailViewState(
|
||||||
val tombstoneEventHandling: Async<String> = Uninitialized,
|
val tombstoneEventHandling: Async<String> = Uninitialized,
|
||||||
val syncState: SyncState = SyncState.IDLE,
|
val syncState: SyncState = SyncState.IDLE,
|
||||||
val highlightedEventId: String? = null,
|
val highlightedEventId: String? = null,
|
||||||
val hideReadMarker: Boolean = false
|
val readMarkerVisible: Boolean = false
|
||||||
) : MvRxState {
|
) : MvRxState {
|
||||||
|
|
||||||
constructor(args: RoomDetailArgs) : this(roomId = args.roomId, eventId = args.eventId)
|
constructor(args: RoomDetailArgs) : this(roomId = args.roomId, eventId = args.eventId)
|
||||||
|
|
|
@ -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.RoomDetailViewState
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.factory.MergedHeaderItemFactory
|
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.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.home.room.detail.timeline.item.*
|
||||||
import im.vector.riotx.features.media.ImageContentRenderer
|
import im.vector.riotx.features.media.ImageContentRenderer
|
||||||
import im.vector.riotx.features.media.VideoContentRenderer
|
import im.vector.riotx.features.media.VideoContentRenderer
|
||||||
|
@ -79,7 +82,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
||||||
|
|
||||||
interface ReadReceiptsCallback {
|
interface ReadReceiptsCallback {
|
||||||
fun onReadReceiptsClicked(readReceipts: List<ReadReceiptData>)
|
fun onReadReceiptsClicked(readReceipts: List<ReadReceiptData>)
|
||||||
fun onReadMarkerLongDisplayed()
|
fun onReadMarkerLongBound(isDisplayed: Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UrlClickCallback {
|
interface UrlClickCallback {
|
||||||
|
@ -141,7 +144,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
||||||
requestModelBuild()
|
requestModelBuild()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(viewState: RoomDetailViewState) {
|
fun update(viewState: RoomDetailViewState, readMarkerVisible: Boolean) {
|
||||||
if (timeline != viewState.timeline) {
|
if (timeline != viewState.timeline) {
|
||||||
timeline = viewState.timeline
|
timeline = viewState.timeline
|
||||||
timeline?.listener = this
|
timeline?.listener = this
|
||||||
|
@ -166,8 +169,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
||||||
eventIdToHighlight = viewState.highlightedEventId
|
eventIdToHighlight = viewState.highlightedEventId
|
||||||
requestModelBuild = true
|
requestModelBuild = true
|
||||||
}
|
}
|
||||||
if (hideReadMarker != viewState.hideReadMarker) {
|
if (this.readMarkerVisible != readMarkerVisible) {
|
||||||
hideReadMarker = viewState.hideReadMarker
|
this.readMarkerVisible = readMarkerVisible
|
||||||
requestModelBuild = true
|
requestModelBuild = true
|
||||||
}
|
}
|
||||||
if (requestModelBuild) {
|
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
|
private var eventIdToHighlight: String? = null
|
||||||
|
|
||||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||||
|
@ -255,11 +258,19 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
||||||
val date = event.root.localDateTime()
|
val date = event.root.localDateTime()
|
||||||
val nextDate = nextEvent?.root?.localDateTime()
|
val nextDate = nextEvent?.root?.localDateTime()
|
||||||
val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
|
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.id(event.localId)
|
||||||
it.setOnVisibilityStateChanged(TimelineEventVisibilityStateChangedListener(callback, event))
|
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()
|
requestModelBuild()
|
||||||
}
|
}
|
||||||
val daySeparatorItem = buildDaySeparatorItem(addDaySeparator, date)
|
val daySeparatorItem = buildDaySeparatorItem(addDaySeparator, date)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ class DefaultItemFactory @Inject constructor(private val avatarSizeProvider: Ava
|
||||||
|
|
||||||
fun create(event: TimelineEvent,
|
fun create(event: TimelineEvent,
|
||||||
highlight: Boolean,
|
highlight: Boolean,
|
||||||
hideReadMarker: Boolean,
|
readMarkerVisible: Boolean,
|
||||||
callback: TimelineEventController.Callback?,
|
callback: TimelineEventController.Callback?,
|
||||||
exception: Exception? = null): DefaultItem? {
|
exception: Exception? = null): DefaultItem? {
|
||||||
val text = if (exception == null) {
|
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}"
|
"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_()
|
return DefaultItem_()
|
||||||
.leftGuideline(avatarSizeProvider.leftGuideline)
|
.leftGuideline(avatarSizeProvider.leftGuideline)
|
||||||
|
|
|
@ -41,7 +41,7 @@ class EncryptedItemFactory @Inject constructor(private val messageInformationDat
|
||||||
fun create(event: TimelineEvent,
|
fun create(event: TimelineEvent,
|
||||||
nextEvent: TimelineEvent?,
|
nextEvent: TimelineEvent?,
|
||||||
highlight: Boolean,
|
highlight: Boolean,
|
||||||
hideReadMarker: Boolean,
|
readMarkerVisible: Boolean,
|
||||||
callback: TimelineEventController.Callback?): VectorEpoxyModel<*>? {
|
callback: TimelineEventController.Callback?): VectorEpoxyModel<*>? {
|
||||||
event.root.eventId ?: return null
|
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
|
// 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)
|
val attributes = attributesFactory.create(null, informationData, callback)
|
||||||
return MessageTextItem_()
|
return MessageTextItem_()
|
||||||
.leftGuideline(avatarSizeProvider.leftGuideline)
|
.leftGuideline(avatarSizeProvider.leftGuideline)
|
||||||
|
|
|
@ -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.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
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.AvatarRenderer
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
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.*
|
||||||
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.item.MergedHeaderItem
|
import im.vector.riotx.features.home.room.detail.timeline.item.MergedHeaderItem
|
||||||
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
|
import javax.inject.Inject
|
||||||
|
@ -42,6 +36,7 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act
|
||||||
nextEvent: TimelineEvent?,
|
nextEvent: TimelineEvent?,
|
||||||
items: List<TimelineEvent>,
|
items: List<TimelineEvent>,
|
||||||
addDaySeparator: Boolean,
|
addDaySeparator: Boolean,
|
||||||
|
readMarkerVisible: Boolean,
|
||||||
currentPosition: Int,
|
currentPosition: Int,
|
||||||
eventIdToHighlight: String?,
|
eventIdToHighlight: String?,
|
||||||
callback: TimelineEventController.Callback?,
|
callback: TimelineEventController.Callback?,
|
||||||
|
@ -67,7 +62,7 @@ class MergedHeaderItemFactory @Inject constructor(private val sessionHolder: Act
|
||||||
if (readMarkerId == null && mergedEvent.hasReadMarker) {
|
if (readMarkerId == null && mergedEvent.hasReadMarker) {
|
||||||
readMarkerId = mergedEvent.root.eventId
|
readMarkerId = mergedEvent.root.eventId
|
||||||
}
|
}
|
||||||
if (!showReadMarker && mergedEvent.displayReadMarker(sessionHolder.getActiveSession().myUserId)) {
|
if (!showReadMarker && mergedEvent.hasReadMarker && readMarkerVisible) {
|
||||||
showReadMarker = true
|
showReadMarker = true
|
||||||
}
|
}
|
||||||
val senderAvatar = mergedEvent.senderAvatar()
|
val senderAvatar = mergedEvent.senderAvatar()
|
||||||
|
|
|
@ -76,12 +76,12 @@ class MessageItemFactory @Inject constructor(
|
||||||
fun create(event: TimelineEvent,
|
fun create(event: TimelineEvent,
|
||||||
nextEvent: TimelineEvent?,
|
nextEvent: TimelineEvent?,
|
||||||
highlight: Boolean,
|
highlight: Boolean,
|
||||||
hideReadMarker: Boolean,
|
readMarkerVisible: Boolean,
|
||||||
callback: TimelineEventController.Callback?
|
callback: TimelineEventController.Callback?
|
||||||
): VectorEpoxyModel<*>? {
|
): VectorEpoxyModel<*>? {
|
||||||
event.root.eventId ?: return null
|
event.root.eventId ?: return null
|
||||||
|
|
||||||
val informationData = messageInformationDataFactory.create(event, nextEvent, hideReadMarker)
|
val informationData = messageInformationDataFactory.create(event, nextEvent, readMarkerVisible)
|
||||||
|
|
||||||
if (event.root.isRedacted()) {
|
if (event.root.isRedacted()) {
|
||||||
//message is redacted
|
//message is redacted
|
||||||
|
@ -98,7 +98,7 @@ class MessageItemFactory @Inject constructor(
|
||||||
|| event.isEncrypted() && event.root.content.toModel<EncryptedEventContent>()?.relatesTo?.type == RelationType.REPLACE
|
|| 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
|
// 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)
|
val attributes = messageItemAttributesFactory.create(messageContent, informationData, callback)
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,11 @@ class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEv
|
||||||
|
|
||||||
fun create(event: TimelineEvent,
|
fun create(event: TimelineEvent,
|
||||||
highlight: Boolean,
|
highlight: Boolean,
|
||||||
hideReadMarker: Boolean,
|
readMarkerVisible: Boolean,
|
||||||
callback: TimelineEventController.Callback?): NoticeItem? {
|
callback: TimelineEventController.Callback?): NoticeItem? {
|
||||||
|
|
||||||
val formattedText = eventFormatter.format(event) ?: return null
|
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(
|
val attributes = NoticeItem.Attributes(
|
||||||
avatarRenderer = avatarRenderer,
|
avatarRenderer = avatarRenderer,
|
||||||
informationData = informationData,
|
informationData = informationData,
|
||||||
|
|
|
@ -33,14 +33,14 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
||||||
fun create(event: TimelineEvent,
|
fun create(event: TimelineEvent,
|
||||||
nextEvent: TimelineEvent?,
|
nextEvent: TimelineEvent?,
|
||||||
eventIdToHighlight: String?,
|
eventIdToHighlight: String?,
|
||||||
hideReadMarker: Boolean,
|
readMarkerVisible: Boolean,
|
||||||
callback: TimelineEventController.Callback?): VectorEpoxyModel<*> {
|
callback: TimelineEventController.Callback?): VectorEpoxyModel<*> {
|
||||||
|
|
||||||
val highlight = event.root.eventId == eventIdToHighlight
|
val highlight = event.root.eventId == eventIdToHighlight
|
||||||
|
|
||||||
val computedModel = try {
|
val computedModel = try {
|
||||||
when (event.root.getClearType()) {
|
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
|
// State and call
|
||||||
EventType.STATE_ROOM_TOMBSTONE,
|
EventType.STATE_ROOM_TOMBSTONE,
|
||||||
EventType.STATE_ROOM_NAME,
|
EventType.STATE_ROOM_NAME,
|
||||||
|
@ -52,22 +52,22 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
||||||
EventType.CALL_ANSWER,
|
EventType.CALL_ANSWER,
|
||||||
EventType.REACTION,
|
EventType.REACTION,
|
||||||
EventType.REDACTION,
|
EventType.REDACTION,
|
||||||
EventType.ENCRYPTION -> noticeItemFactory.create(event, highlight, hideReadMarker, callback)
|
EventType.ENCRYPTION -> noticeItemFactory.create(event, highlight, readMarkerVisible, callback)
|
||||||
// State room create
|
// State room create
|
||||||
EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(event, callback)
|
EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(event, callback)
|
||||||
// Crypto
|
// Crypto
|
||||||
EventType.ENCRYPTED -> {
|
EventType.ENCRYPTED -> {
|
||||||
if (event.root.isRedacted()) {
|
if (event.root.isRedacted()) {
|
||||||
// Redacted event, let the MessageItemFactory handle it
|
// Redacted event, let the MessageItemFactory handle it
|
||||||
messageItemFactory.create(event, nextEvent, highlight, hideReadMarker, callback)
|
messageItemFactory.create(event, nextEvent, highlight, readMarkerVisible, callback)
|
||||||
} else {
|
} else {
|
||||||
encryptedItemFactory.create(event, nextEvent, highlight, hideReadMarker, callback)
|
encryptedItemFactory.create(event, nextEvent, highlight, readMarkerVisible, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unhandled event types (yet)
|
// Unhandled event types (yet)
|
||||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||||
EventType.STICKER -> defaultItemFactory.create(event, highlight, hideReadMarker, callback)
|
EventType.STICKER -> defaultItemFactory.create(event, highlight, readMarkerVisible, callback)
|
||||||
else -> {
|
else -> {
|
||||||
Timber.v("Type ${event.root.getClearType()} not handled")
|
Timber.v("Type ${event.root.getClearType()} not handled")
|
||||||
null
|
null
|
||||||
|
@ -75,7 +75,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "failed to create message item")
|
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_())
|
return (computedModel ?: EmptyItem_())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.matrix.android.api.session.room.timeline.hasBeenEdited
|
||||||
import im.vector.riotx.core.extensions.localDateTime
|
import im.vector.riotx.core.extensions.localDateTime
|
||||||
import im.vector.riotx.core.resources.ColorProvider
|
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.features.home.getColorFromUserId
|
||||||
import im.vector.riotx.core.date.VectorDateFormatter
|
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.MessageInformationData
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.ReactionInfoData
|
import im.vector.riotx.features.home.room.detail.timeline.item.ReactionInfoData
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData
|
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 dateFormatter: VectorDateFormatter,
|
||||||
private val colorProvider: ColorProvider) {
|
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
|
// Non nullability has been tested before
|
||||||
val eventId = event.root.eventId!!
|
val eventId = event.root.eventId!!
|
||||||
|
|
||||||
|
@ -65,7 +63,7 @@ class MessageInformationDataFactory @Inject constructor(private val session: Ses
|
||||||
textColor = colorProvider.getColor(getColorFromUserId(event.root.senderId ?: ""))
|
textColor = colorProvider.getColor(getColorFromUserId(event.root.senderId ?: ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
val displayReadMarker = !hideReadMarker && event.displayReadMarker(session.myUserId)
|
val displayReadMarker = readMarkerVisible && event.hasReadMarker
|
||||||
|
|
||||||
return MessageInformationData(
|
return MessageInformationData(
|
||||||
eventId = eventId,
|
eventId = eventId,
|
||||||
|
|
|
@ -57,8 +57,8 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : BaseEventItem<H>() {
|
||||||
|
|
||||||
private val _readMarkerCallback = object : ReadMarkerView.Callback {
|
private val _readMarkerCallback = object : ReadMarkerView.Callback {
|
||||||
|
|
||||||
override fun onReadMarkerLongBound() {
|
override fun onReadMarkerLongBound(isDisplayed: Boolean) {
|
||||||
attributes.readReceiptsCallback?.onReadMarkerLongDisplayed()
|
attributes.readReceiptsCallback?.onReadMarkerLongBound(isDisplayed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,8 @@ abstract class MergedHeaderItem : BaseEventItem<MergedHeaderItem.Holder>() {
|
||||||
|
|
||||||
private val _readMarkerCallback = object : ReadMarkerView.Callback {
|
private val _readMarkerCallback = object : ReadMarkerView.Callback {
|
||||||
|
|
||||||
override fun onReadMarkerLongBound() {
|
override fun onReadMarkerLongBound(isDisplayed: Boolean) {
|
||||||
attributes.readReceiptsCallback?.onReadMarkerLongDisplayed()
|
attributes.readReceiptsCallback?.onReadMarkerLongBound(isDisplayed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,9 @@ abstract class NoticeItem : BaseEventItem<NoticeItem.Holder>() {
|
||||||
})
|
})
|
||||||
|
|
||||||
private val _readMarkerCallback = object : ReadMarkerView.Callback {
|
private val _readMarkerCallback = object : ReadMarkerView.Callback {
|
||||||
override fun onReadMarkerLongBound() {
|
|
||||||
attributes.readReceiptsCallback?.onReadMarkerLongDisplayed()
|
override fun onReadMarkerLongBound(isDisplayed: Boolean) {
|
||||||
|
attributes.readReceiptsCallback?.onReadMarkerLongBound(isDisplayed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue