Lab setting to load rooms at first unread message
Change-Id: I781e5a32d8557939c51387eadf1387cba0d3b149
This commit is contained in:
parent
401424ff96
commit
2db315219a
@ -66,6 +66,16 @@ interface Timeline {
|
||||
*/
|
||||
fun setInitialEventId(eventId: String?)
|
||||
|
||||
/**
|
||||
* Offset for the initial event, e.g. if we want to load the event just below said id
|
||||
*/
|
||||
fun getInitialEventIdOffset(): Int
|
||||
|
||||
/**
|
||||
* Set the offset for the initial event, e.g. if we want to load the event just below said id
|
||||
*/
|
||||
fun setInitialEventIdOffset(offset: Int)
|
||||
|
||||
/**
|
||||
* Check if the timeline can be enriched by paginating.
|
||||
* @param direction the direction to check in
|
||||
|
@ -61,6 +61,7 @@ private const val MIN_FETCHING_COUNT = 30
|
||||
internal class DefaultTimeline(
|
||||
private val roomId: String,
|
||||
private var initialEventId: String? = null,
|
||||
private var initialEventIdOffset: Int = 0,
|
||||
private val realmConfiguration: RealmConfiguration,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val contextOfEventTask: GetContextOfEventTask,
|
||||
@ -145,7 +146,7 @@ internal class DefaultTimeline(
|
||||
|
||||
override fun start() {
|
||||
if (isStarted.compareAndSet(false, true)) {
|
||||
Timber.v("Start timeline for roomId: $roomId and eventId: $initialEventId")
|
||||
Timber.v("Start timeline for roomId: $roomId and eventId: $initialEventId (offset $initialEventIdOffset)")
|
||||
timelineInput.listeners.add(this)
|
||||
BACKGROUND_HANDLER.post {
|
||||
eventDecryptor.start()
|
||||
@ -195,7 +196,7 @@ internal class DefaultTimeline(
|
||||
if (isStarted.compareAndSet(true, false)) {
|
||||
isReady.set(false)
|
||||
timelineInput.listeners.remove(this)
|
||||
Timber.v("Dispose timeline for roomId: $roomId and eventId: $initialEventId")
|
||||
Timber.v("Dispose timeline for roomId: $roomId and eventId: $initialEventId (offset $initialEventIdOffset)")
|
||||
cancelableBag.cancel()
|
||||
BACKGROUND_HANDLER.removeCallbacksAndMessages(null)
|
||||
BACKGROUND_HANDLER.post {
|
||||
@ -217,6 +218,7 @@ internal class DefaultTimeline(
|
||||
override fun restartWithEventId(eventId: String?) {
|
||||
dispose()
|
||||
initialEventId = eventId
|
||||
initialEventIdOffset = 0
|
||||
start()
|
||||
postSnapshot()
|
||||
}
|
||||
@ -229,6 +231,14 @@ internal class DefaultTimeline(
|
||||
initialEventId = eventId
|
||||
}
|
||||
|
||||
override fun getInitialEventIdOffset(): Int {
|
||||
return initialEventIdOffset
|
||||
}
|
||||
|
||||
override fun setInitialEventIdOffset(offset: Int) {
|
||||
initialEventIdOffset = offset
|
||||
}
|
||||
|
||||
override fun getTimelineEventAtIndex(index: Int): TimelineEvent? {
|
||||
return builtEvents.getOrNull(index)
|
||||
}
|
||||
|
@ -131,11 +131,16 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
Timeline.Listener, ChatEffectManager.Delegate, CallProtocolsChecker.Listener {
|
||||
|
||||
private val room = session.getRoom(initialState.roomId)!!
|
||||
private val eventId = initialState.eventId
|
||||
private val eventId = initialState.eventId ?: if (vectorPreferences.loadRoomAtFirstUnread()) room.roomSummary()?.readMarkerId else null
|
||||
private val invisibleEventsObservable = BehaviorRelay.create<RoomDetailAction.TimelineEventTurnsInvisible>()
|
||||
private val visibleEventsObservable = BehaviorRelay.create<RoomDetailAction.TimelineEventTurnsVisible>()
|
||||
private var timelineEvents = PublishRelay.create<List<TimelineEvent>>()
|
||||
val timeline = timelineFactory.createTimeline(viewModelScope, room, eventId)
|
||||
val timeline = timelineFactory.createTimeline(viewModelScope, room, eventId).apply {
|
||||
// Target the event just below $eventId in case that it is the readMarkerId
|
||||
if (initialState.eventId == null && eventId != null) {
|
||||
setInitialEventIdOffset(-1)
|
||||
}
|
||||
}
|
||||
|
||||
// Same lifecycle than the ViewModel (survive to screen rotation)
|
||||
val previewUrlRetriever = PreviewUrlRetriever(session, viewModelScope)
|
||||
@ -184,8 +189,10 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
observeActiveRoomWidgets()
|
||||
observePowerLevel()
|
||||
room.getRoomSummaryLive()
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
tryOrNull { room.markAsRead(ReadService.MarkAsReadParams.READ_RECEIPT) }
|
||||
if (!vectorPreferences.loadRoomAtFirstUnread()) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
tryOrNull { room.markAsRead(ReadService.MarkAsReadParams.READ_RECEIPT) }
|
||||
}
|
||||
}
|
||||
// Inform the SDK that the room is displayed
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
@ -507,6 +514,9 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
mostRecentDisplayedEvent?.root?.eventId?.also {
|
||||
session.coroutineScope.launch(NonCancellable) {
|
||||
tryOrNull { room.setReadMarker(it) }
|
||||
if (vectorPreferences.loadRoomAtFirstUnread()) {
|
||||
tryOrNull { room.setReadReceipt(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
mostRecentDisplayedEvent = null
|
||||
@ -1312,10 +1322,10 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun observeEventDisplayedActions() {
|
||||
// We are buffering scroll events for one second
|
||||
// We are buffering scroll events for half a second
|
||||
// and keep the most recent one to set the read receipt on.
|
||||
visibleEventsObservable
|
||||
.buffer(1, TimeUnit.SECONDS)
|
||||
.buffer(500, TimeUnit.MILLISECONDS)
|
||||
.filter { it.isNotEmpty() }
|
||||
.subscribeBy(onNext = { actions ->
|
||||
val bufferedMostRecentDisplayedEvent = actions.maxByOrNull { it.event.displayIndex }?.event ?: return@subscribeBy
|
||||
|
@ -23,6 +23,7 @@ import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||
import im.vector.app.features.home.room.detail.timeline.item.ItemWithEvents
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import kotlin.math.max
|
||||
|
||||
class ScrollOnNewMessageCallback(private val layoutManager: LinearLayoutManager,
|
||||
private val timelineEventController: TimelineEventController,
|
||||
@ -32,7 +33,6 @@ class ScrollOnNewMessageCallback(private val layoutManager: LinearLayoutManager,
|
||||
private var forceScroll = false
|
||||
var initialForceScroll = false
|
||||
var initialForceScrollEventId: String? = null
|
||||
get() = field ?: timelineEventController.timeline?.getInitialEventId()
|
||||
|
||||
fun addNewTimelineEventIds(eventIds: List<String>) {
|
||||
// Disable initial force scroll
|
||||
@ -57,8 +57,10 @@ class ScrollOnNewMessageCallback(private val layoutManager: LinearLayoutManager,
|
||||
override fun onInserted(position: Int, count: Int) {
|
||||
if (initialForceScroll) {
|
||||
var scrollToEvent = initialForceScrollEventId
|
||||
var scrollOffset = 0
|
||||
if (initialForceScrollEventId == null) {
|
||||
scrollToEvent = timelineEventController.timeline?.getInitialEventId()
|
||||
scrollOffset = timelineEventController.timeline?.getInitialEventIdOffset() ?: 0
|
||||
}
|
||||
if (scrollToEvent == null) {
|
||||
layoutManager.scrollToPositionWithOffset(0, 0)
|
||||
@ -67,7 +69,8 @@ class ScrollOnNewMessageCallback(private val layoutManager: LinearLayoutManager,
|
||||
// Scroll such that the scrolled-to event is moved down 1/3 of the screen.
|
||||
// To do that, we actually scroll the view above out by 2/3 (since we can only control the distance
|
||||
// from the bottom of the view, not the top).
|
||||
layoutManager.scrollToPositionWithOffset(it + 1, parentView.measuredHeight * 2 / 3)
|
||||
val scrollToPosition = max(it + scrollOffset + 1, 0)
|
||||
layoutManager.scrollToPositionWithOffset(scrollToPosition, parentView.measuredHeight * 2 / 3)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -203,6 +203,7 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
||||
private const val SETTINGS_USER_COLOR_MODE_DM = "SETTINGS_USER_COLOR_MODE_DM"
|
||||
private const val SETTINGS_USER_COLOR_MODE_DEFAULT = "SETTINGS_USER_COLOR_MODE_DEFAULT"
|
||||
private const val SETTINGS_USER_COLOR_MODE_PUBLIC_ROOM = "SETTINGS_USER_COLOR_MODE_PUBLIC_ROOM"
|
||||
private const val SETTINGS_OPEN_CHATS_AT_FIRST_UNREAD = "SETTINGS_OPEN_CHATS_AT_FIRST_UNREAD"
|
||||
|
||||
private const val DID_ASK_TO_ENABLE_SESSION_PUSH = "DID_ASK_TO_ENABLE_SESSION_PUSH"
|
||||
|
||||
@ -997,6 +998,11 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
||||
}, MatrixItemColorProvider.USER_COLORING_DEFAULT) ?: MatrixItemColorProvider.USER_COLORING_DEFAULT
|
||||
}
|
||||
|
||||
// SC addition
|
||||
fun loadRoomAtFirstUnread(): Boolean {
|
||||
return defaultPrefs.getBoolean(SETTINGS_OPEN_CHATS_AT_FIRST_UNREAD, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* The user enable protecting app access with pin code.
|
||||
* Currently we use the pin code store to know if the pin is enabled, so this is not used
|
||||
|
@ -84,6 +84,9 @@
|
||||
<string name="setting_sc_accent_color_dark">Accent color for dark themes</string>
|
||||
<string name="settings_sc_accent_disclaimer">Note that these color settings only apply to SC themes, and not Element themes.</string>
|
||||
|
||||
<string name="settings_open_chats_at_first_unread">Open at first unread</string>
|
||||
<string name="settings_open_chats_at_first_unread_summary">Open chats at the first unread message instead of at the bottom.</string>
|
||||
|
||||
<!-- Accent colors -->
|
||||
<string name="sc_accent_greenlight">Light green</string>
|
||||
<string name="sc_accent_greendark">Dark green</string>
|
||||
|
@ -34,6 +34,12 @@
|
||||
<!--android:summary="@string/settings_labs_enable_send_voice_summary"-->
|
||||
<!--android:title="@string/settings_labs_enable_send_voice" />-->
|
||||
|
||||
<im.vector.app.core.preference.VectorSwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="SETTINGS_OPEN_CHATS_AT_FIRST_UNREAD"
|
||||
android:title="@string/settings_open_chats_at_first_unread"
|
||||
android:summary="@string/settings_open_chats_at_first_unread_summary" />
|
||||
|
||||
<im.vector.app.core.preference.VectorSwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="SYSTEM_DARK_THEME_PRE_TEN"
|
||||
|
Loading…
x
Reference in New Issue
Block a user