1
0
mirror of https://github.com/vector-im/riotX-android synced 2025-10-06 00:02:48 +02:00

Compare commits

...

2 Commits

Author SHA1 Message Date
ganfra
dc7b424324 Timeline: try playing with EmptyItem to fix some scroll issues 2021-03-01 12:22:13 +01:00
ganfra
5dec4797dd Timeline: fix background of day separator and read marker 2021-02-22 17:40:50 +01:00
12 changed files with 57 additions and 62 deletions

View File

@@ -16,6 +16,7 @@
package im.vector.app.core.epoxy
import androidx.core.view.updateLayoutParams
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
@@ -25,6 +26,14 @@ import im.vector.app.features.home.room.detail.timeline.item.ItemWithEvents
abstract class TimelineEmptyItem : VectorEpoxyModel<TimelineEmptyItem.Holder>(), ItemWithEvents {
@EpoxyAttribute lateinit var eventId: String
@EpoxyAttribute var hidden: Boolean = true
override fun bind(holder: Holder) {
super.bind(holder)
holder.view.updateLayoutParams {
this.height = if (hidden) 0 else 1
}
}
override fun getEventIds(): List<String> {
return listOf(eventId)

View File

@@ -66,7 +66,7 @@ class JumpToBottomViewVisibilityManager(
}
private fun maybeShowJumpToBottomViewVisibility() {
if (layoutManager.findFirstVisibleItemPosition() != 0) {
if (layoutManager.findFirstVisibleItemPosition() > 1) {
jumpToBottomView.show()
} else {
jumpToBottomView.hide()

View File

@@ -24,7 +24,6 @@ import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent
import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
import org.matrix.android.sdk.api.session.room.timeline.Timeline
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.widgets.model.Widget
import org.matrix.android.sdk.api.util.MatrixItem
@@ -34,8 +33,8 @@ sealed class RoomDetailAction : VectorViewModelAction {
data class SendSticker(val stickerContent: MessageStickerContent) : RoomDetailAction()
data class SendMessage(val text: CharSequence, val autoMarkdown: Boolean) : RoomDetailAction()
data class SendMedia(val attachments: List<ContentAttachmentData>, val compressBeforeSending: Boolean) : RoomDetailAction()
data class TimelineEventTurnsVisible(val event: TimelineEvent) : RoomDetailAction()
data class TimelineEventTurnsInvisible(val event: TimelineEvent) : RoomDetailAction()
data class TimelineEventTurnsVisible(val eventId: String) : RoomDetailAction()
data class TimelineEventTurnsInvisible(val eventId: String) : RoomDetailAction()
data class LoadMoreTimelineEvents(val direction: Timeline.Direction) : RoomDetailAction()
data class SendReaction(val targetEventId: String, val reaction: String) : RoomDetailAction()
data class UndoReaction(val targetEventId: String, val reaction: String, val reason: String? = "") : RoomDetailAction()

View File

@@ -1454,12 +1454,12 @@ class RoomDetailFragment @Inject constructor(
return true
}
override fun onEventVisible(event: TimelineEvent) {
roomDetailViewModel.handle(RoomDetailAction.TimelineEventTurnsVisible(event))
override fun onEventVisible(eventId: String) {
roomDetailViewModel.handle(RoomDetailAction.TimelineEventTurnsVisible(eventId))
}
override fun onEventInvisible(event: TimelineEvent) {
roomDetailViewModel.handle(RoomDetailAction.TimelineEventTurnsInvisible(event))
override fun onEventInvisible(eventId: String) {
roomDetailViewModel.handle(RoomDetailAction.TimelineEventTurnsInvisible(eventId))
}
override fun onEncryptedMessageClicked(informationData: MessageInformationData, view: View) {

View File

@@ -1022,19 +1022,19 @@ class RoomDetailViewModel @AssistedInject constructor(
private fun handleEventVisible(action: RoomDetailAction.TimelineEventTurnsVisible) {
viewModelScope.launch(Dispatchers.Default) {
if (action.event.root.sendState.isSent()) { // ignore pending/local events
val event = timeline.getTimelineEventWithId(action.eventId) ?: return@launch
if (event.root.sendState.isSent()) { // ignore pending/local events
visibleEventsObservable.accept(action)
}
// We need to update this with the related m.replace also (to move read receipt)
action.event.annotations?.editSummary?.sourceEvents?.forEach {
event.annotations?.editSummary?.sourceEvents?.forEach {
room.getTimeLineEvent(it)?.let { event ->
visibleEventsObservable.accept(RoomDetailAction.TimelineEventTurnsVisible(event))
visibleEventsObservable.accept(RoomDetailAction.TimelineEventTurnsVisible(event.eventId))
}
}
// handle chat effects here
if (vectorPreferences.chatEffectsEnabled()) {
chatEffectManager.checkForEffect(action.event)
chatEffectManager.checkForEffect(event)
}
}
}
@@ -1194,7 +1194,9 @@ class RoomDetailViewModel @AssistedInject constructor(
.buffer(1, TimeUnit.SECONDS)
.filter { it.isNotEmpty() }
.subscribeBy(onNext = { actions ->
val bufferedMostRecentDisplayedEvent = actions.maxByOrNull { it.event.displayIndex }?.event ?: return@subscribeBy
val bufferedMostRecentDisplayedEvent = actions
.mapNotNull { timeline.getTimelineEventWithId(it.eventId) }
.maxByOrNull { it.displayIndex } ?: return@subscribeBy
val globalMostRecentDisplayedEvent = mostRecentDisplayedEvent
if (trackUnreadMessages.get()) {
if (globalMostRecentDisplayedEvent == null) {

View File

@@ -43,7 +43,6 @@ class ScrollOnNewMessageCallback(private val layoutManager: LinearLayoutManager,
layoutManager.scrollToPosition(position)
return
}
Timber.v("On inserted $count count at position: $position")
if (layoutManager.findFirstVisibleItemPosition() != position) {
return
}
@@ -51,11 +50,10 @@ class ScrollOnNewMessageCallback(private val layoutManager: LinearLayoutManager,
val firstNewItemIds = firstNewItem.getEventIds().firstOrNull() ?: return
val indexOfFirstNewItem = newTimelineEventIds.indexOf(firstNewItemIds)
if (indexOfFirstNewItem != -1) {
Timber.v("Should scroll to position: $position")
repeat(newTimelineEventIds.size - indexOfFirstNewItem) {
newTimelineEventIds.removeAt(indexOfFirstNewItem)
}
layoutManager.scrollToPosition(position)
layoutManager.scrollToPosition(0)
}
}
}

View File

@@ -85,8 +85,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
ReadReceiptsCallback,
PreviewUrlCallback {
fun onLoadMore(direction: Timeline.Direction)
fun onEventInvisible(event: TimelineEvent)
fun onEventVisible(event: TimelineEvent)
fun onEventInvisible(eventId: String)
fun onEventVisible(eventId: String)
fun onRoomCreateLinkClicked(url: String)
fun onEncryptedMessageClicked(informationData: MessageInformationData, view: View)
fun onImageMessageClicked(messageImageContent: MessageImageInfoContent, mediaData: ImageContentRenderer.Data, view: View)
@@ -144,7 +144,6 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
private var unreadState: UnreadState = UnreadState.Unknown
private var positionOfReadMarker: Int? = null
private var eventIdToHighlight: String? = null
private var previousModelsSize = 0
var callback: Callback? = null
var timeline: Timeline? = null
@@ -341,7 +340,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
updateUTDStates(event, nextEvent)
val eventModel = timelineItemFactory.create(event, nextEvent, eventIdToHighlight, callback).also {
it.id(event.localId)
it.setOnVisibilityStateChanged(TimelineEventVisibilityStateChangedListener(callback, event))
it.setOnVisibilityStateChanged(TimelineEventVisibilityStateChangedListener(callback, event.eventId))
}
val addDaySeparator = if (hasReachedInvite && hasUTD) {
true

View File

@@ -19,6 +19,7 @@ package im.vector.app.features.home.room.detail.timeline.helper
import com.airbnb.epoxy.EpoxyModel
import com.airbnb.epoxy.VisibilityState
import im.vector.app.core.epoxy.LoadingItem_
import im.vector.app.core.epoxy.TimelineEmptyItem
import im.vector.app.core.epoxy.TimelineEmptyItem_
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.home.room.detail.UnreadState
@@ -59,12 +60,27 @@ class TimelineControllerInterceptorHelper(private val positionOfReadMarker: KMut
val showHiddenEvents = vectorPreferences.shouldShowHiddenEvents()
var index = 0
val firstUnreadEventId = (unreadState as? UnreadState.HasUnread)?.firstUnreadEventId
var prevWasHidden = false
var onlyHidden = true
// Then iterate on models so we have the exact positions in the adapter
modelsIterator.forEach { epoxyModel ->
if (epoxyModel is TimelineEmptyItem && !prevWasHidden) {
prevWasHidden = true
modelsIterator.remove()
val emptyItem = TimelineEmptyItem_()
.id("not_hidden_${epoxyModel.id()}")
.eventId(epoxyModel.eventId)
.hidden(false)
.setOnVisibilityStateChanged(TimelineEventVisibilityStateChangedListener(callback, epoxyModel.eventId))
modelsIterator.add(emptyItem)
} else if (epoxyModel !is TimelineEmptyItem) {
onlyHidden = false
prevWasHidden = false
}
if (epoxyModel is ItemWithEvents) {
epoxyModel.getEventIds().forEach { eventId ->
adapterPositionMapping[eventId] = index
if (eventId == firstUnreadEventId) {
if (eventId == firstUnreadEventId && !onlyHidden) {
modelsIterator.addReadMarkerItem(callback)
index++
positionOfReadMarker.set(index)
@@ -88,6 +104,7 @@ class TimelineControllerInterceptorHelper(private val positionOfReadMarker: KMut
add(readMarker)
// Use next as we still have some process to do before the next iterator loop
next()
previous()
}
private fun MutableListIterator<EpoxyModel<*>>.removeCallItemIfNeeded(
@@ -105,6 +122,7 @@ class TimelineControllerInterceptorHelper(private val positionOfReadMarker: KMut
val emptyItem = TimelineEmptyItem_()
.id(epoxyModel.id())
.eventId(epoxyModel.attributes.informationData.eventId)
.hidden(false)
add(emptyItem)
}
callIds.add(callId)

View File

@@ -32,14 +32,14 @@ class ReadMarkerVisibilityStateChangedListener(private val callback: TimelineEve
}
class TimelineEventVisibilityStateChangedListener(private val callback: TimelineEventController.Callback?,
private val event: TimelineEvent)
private val eventId: String)
: VectorEpoxyModel.OnVisibilityStateChangedListener {
override fun onVisibilityStateChanged(visibilityState: Int) {
if (visibilityState == VisibilityState.VISIBLE) {
callback?.onEventVisible(event)
callback?.onEventVisible(eventId)
} else if (visibilityState == VisibilityState.INVISIBLE) {
callback?.onEventInvisible(event)
callback?.onEventInvisible(eventId)
}
}
}
@@ -50,9 +50,9 @@ class MergedTimelineEventVisibilityStateChangedListener(private val callback: Ti
override fun onVisibilityStateChanged(visibilityState: Int) {
if (visibilityState == VisibilityState.VISIBLE) {
events.forEach { callback?.onEventVisible(it) }
events.forEach { callback?.onEventVisible(it.eventId) }
} else if (visibilityState == VisibilityState.INVISIBLE) {
events.forEach { callback?.onEventInvisible(it) }
events.forEach { callback?.onEventInvisible(it.eventId) }
}
}
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.home.room.detail.timeline.item
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
@EpoxyModelClass(layout = R.layout.item_timeline_event_blank_stub)
abstract class BlankItem : VectorEpoxyModel<BlankItem.BlankHolder>() {
class BlankHolder : VectorEpoxyHolder()
}

View File

@@ -3,7 +3,6 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?riotx_background"
android:padding="8dp">
<View
@@ -12,16 +11,15 @@
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:background="?riotx_header_panel_background" />
android:background="?riotx_list_bottom_sheet_divider_color" />
<TextView
android:id="@+id/itemDayTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="?riotx_background"
android:paddingStart="32dp"
android:paddingEnd="32dp"
android:background="?android:attr/windowBackground"
android:paddingHorizontal="24dp"
android:textColor="?riotx_header_panel_text_secondary"
android:textSize="15sp"
tools:text="@tools:sample/date/day_of_week" />

View File

@@ -2,7 +2,6 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?riotx_background"
android:padding="8dp">
<View
@@ -17,10 +16,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="?riotx_background"
android:background="?android:attr/windowBackground"
android:fontFamily="sans-serif-medium"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingHorizontal="16dp"
android:text="@string/timeline_unread_messages"
android:textColor="@color/notification_accent_color"
android:textSize="15sp" />