mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 05:31:21 +03:00
Make TimelineSettings aware of rootThreadEventId and welcome a new Thread mode for the timeline creation
This commit is contained in:
parent
50e51cbe29
commit
e541636802
8 changed files with 79 additions and 21 deletions
|
@ -27,5 +27,14 @@ data class TimelineSettings(
|
|||
/**
|
||||
* If true, will build read receipts for each event.
|
||||
*/
|
||||
val buildReadReceipts: Boolean = true
|
||||
)
|
||||
val buildReadReceipts: Boolean = true,
|
||||
/**
|
||||
* The root thread eventId if this is a thread timeline, or null if this is NOT a thread timeline
|
||||
*/
|
||||
val rootThreadEventId: String? = null) {
|
||||
|
||||
/**
|
||||
* Returns true if this is a thread timeline or false otherwise
|
||||
*/
|
||||
fun isThreadTimeline() = rootThreadEventId != null
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ internal class DefaultTimeline(private val roomId: String,
|
|||
ensureReadReceiptAreLoaded(realm)
|
||||
backgroundRealm.set(realm)
|
||||
listenToPostSnapshotSignals()
|
||||
openAround(initialEventId)
|
||||
openAround(initialEventId, rootThreadEventId)
|
||||
postSnapshot()
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ internal class DefaultTimeline(private val roomId: String,
|
|||
|
||||
override fun restartWithEventId(eventId: String?) {
|
||||
timelineScope.launch {
|
||||
openAround(eventId)
|
||||
openAround(eventId,rootThreadEventId)
|
||||
postSnapshot()
|
||||
}
|
||||
}
|
||||
|
@ -226,18 +226,20 @@ internal class DefaultTimeline(private val roomId: String,
|
|||
return true
|
||||
}
|
||||
|
||||
private suspend fun openAround(eventId: String?) = withContext(timelineDispatcher) {
|
||||
private suspend fun openAround(eventId: String?, rootThreadEventId: String?) = withContext(timelineDispatcher) {
|
||||
val baseLogMessage = "openAround(eventId: $eventId)"
|
||||
Timber.v("$baseLogMessage started")
|
||||
if (!isStarted.get()) {
|
||||
throw IllegalStateException("You should call start before using timeline")
|
||||
}
|
||||
strategy.onStop()
|
||||
strategy = if (eventId == null) {
|
||||
buildStrategy(LoadTimelineStrategy.Mode.Live)
|
||||
} else {
|
||||
buildStrategy(LoadTimelineStrategy.Mode.Permalink(eventId))
|
||||
|
||||
strategy = when {
|
||||
rootThreadEventId != null -> buildStrategy(LoadTimelineStrategy.Mode.Thread(rootThreadEventId))
|
||||
eventId == null -> buildStrategy(LoadTimelineStrategy.Mode.Live)
|
||||
else -> buildStrategy(LoadTimelineStrategy.Mode.Permalink(eventId))
|
||||
}
|
||||
|
||||
initPaginationStates(eventId)
|
||||
strategy.onStart()
|
||||
loadMore(
|
||||
|
|
|
@ -20,4 +20,5 @@ internal enum class LoadMoreResult {
|
|||
REACHED_END,
|
||||
SUCCESS,
|
||||
FAILURE
|
||||
// evenIDS
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ internal class LoadTimelineStrategy(
|
|||
sealed interface Mode {
|
||||
object Live : Mode
|
||||
data class Permalink(val originEventId: String) : Mode
|
||||
data class Thread(val rootThreadEventId: String) : Mode
|
||||
|
||||
fun originEventId(): String? {
|
||||
return if (this is Permalink) {
|
||||
|
@ -59,6 +60,14 @@ internal class LoadTimelineStrategy(
|
|||
null
|
||||
}
|
||||
}
|
||||
|
||||
// fun getRootThreadEventId(): String? {
|
||||
// return if (this is Thread) {
|
||||
// rootThreadEventId
|
||||
// } else {
|
||||
// null
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
data class Dependencies(
|
||||
|
@ -162,6 +171,7 @@ internal class LoadTimelineStrategy(
|
|||
}
|
||||
|
||||
suspend fun loadMore(count: Int, direction: Timeline.Direction, fetchOnServerIfNeeded: Boolean = true): LoadMoreResult {
|
||||
///
|
||||
if (mode is Mode.Permalink && timelineChunk == null) {
|
||||
val params = GetContextOfEventTask.Params(roomId, mode.originEventId)
|
||||
try {
|
||||
|
@ -198,13 +208,22 @@ internal class LoadTimelineStrategy(
|
|||
}
|
||||
|
||||
private fun getChunkEntity(realm: Realm): RealmResults<ChunkEntity> {
|
||||
return if (mode is Mode.Permalink) {
|
||||
ChunkEntity.findAllIncludingEvents(realm, listOf(mode.originEventId))
|
||||
} else {
|
||||
|
||||
return when (mode) {
|
||||
is Mode.Live -> {
|
||||
ChunkEntity.where(realm, roomId)
|
||||
.equalTo(ChunkEntityFields.IS_LAST_FORWARD, true)
|
||||
.findAll()
|
||||
}
|
||||
is Mode.Permalink -> {
|
||||
ChunkEntity.findAllIncludingEvents(realm, listOf(mode.originEventId))
|
||||
}
|
||||
is Mode.Thread -> {
|
||||
ChunkEntity.where(realm, roomId)
|
||||
.equalTo(ChunkEntityFields.IS_LAST_FORWARD, true)
|
||||
.findAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasReachedLastForward(): Boolean {
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.realm.RealmQuery
|
|||
import io.realm.RealmResults
|
||||
import io.realm.Sort
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import org.matrix.android.sdk.BuildConfig
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
|
@ -271,7 +272,24 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
|
|||
private suspend fun loadFromStorage(count: Int, direction: Timeline.Direction): Int {
|
||||
val displayIndex = getNextDisplayIndex(direction) ?: return 0
|
||||
val baseQuery = timelineEventEntities.where()
|
||||
val timelineEvents = baseQuery.offsets(direction, count, displayIndex).findAll().orEmpty()
|
||||
|
||||
val timelineEvents = if (timelineSettings.rootThreadEventId != null) {
|
||||
baseQuery
|
||||
.beginGroup()
|
||||
.equalTo(TimelineEventEntityFields.ROOT.ROOT_THREAD_EVENT_ID, timelineSettings.rootThreadEventId)
|
||||
.or()
|
||||
.equalTo(TimelineEventEntityFields.ROOT.EVENT_ID, timelineSettings.rootThreadEventId)
|
||||
.endGroup()
|
||||
.offsets(direction, count, displayIndex)
|
||||
.findAll()
|
||||
.orEmpty()
|
||||
} else {
|
||||
baseQuery
|
||||
.offsets(direction, count, displayIndex)
|
||||
.findAll()
|
||||
.orEmpty()
|
||||
}
|
||||
|
||||
if (timelineEvents.isEmpty()) return 0
|
||||
fetchRootThreadEventsIfNeeded(timelineEvents)
|
||||
if (direction == Timeline.Direction.FORWARDS) {
|
||||
|
@ -299,6 +317,7 @@ internal class TimelineChunk(private val chunkEntity: ChunkEntity,
|
|||
* in order to be able to display the event to the user appropriately
|
||||
*/
|
||||
private suspend fun fetchRootThreadEventsIfNeeded(offsetResults: List<TimelineEventEntity>) {
|
||||
if (BuildConfig.THREADING_ENABLED) return
|
||||
val eventEntityList = offsetResults
|
||||
.mapNotNull {
|
||||
it.root
|
||||
|
|
|
@ -127,7 +127,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||
private val invisibleEventsSource = BehaviorDataSource<RoomDetailAction.TimelineEventTurnsInvisible>()
|
||||
private val visibleEventsSource = BehaviorDataSource<RoomDetailAction.TimelineEventTurnsVisible>()
|
||||
private var timelineEvents = MutableSharedFlow<List<TimelineEvent>>(0)
|
||||
val timeline = timelineFactory.createTimeline(viewModelScope, room, eventId)
|
||||
val timeline = timelineFactory.createTimeline(viewModelScope, room, eventId, initialState.rootThreadEventId)
|
||||
|
||||
// Same lifecycle than the ViewModel (survive to screen rotation)
|
||||
val previewUrlRetriever = PreviewUrlRetriever(session, viewModelScope)
|
||||
|
|
|
@ -35,8 +35,14 @@ private val secondaryTimelineAllowedTypes = listOf(
|
|||
|
||||
class TimelineFactory @Inject constructor(private val session: Session, private val timelineSettingsFactory: TimelineSettingsFactory) {
|
||||
|
||||
fun createTimeline(coroutineScope: CoroutineScope, mainRoom: Room, eventId: String?): Timeline {
|
||||
val settings = timelineSettingsFactory.create()
|
||||
fun createTimeline(
|
||||
coroutineScope: CoroutineScope,
|
||||
mainRoom: Room,
|
||||
eventId: String?,
|
||||
rootThreadEventId: String?
|
||||
): Timeline {
|
||||
val settings = timelineSettingsFactory.create(rootThreadEventId)
|
||||
|
||||
if (!session.vectorCallService.protocolChecker.supportVirtualRooms) {
|
||||
return mainRoom.createTimeline(eventId, settings)
|
||||
}
|
||||
|
|
|
@ -22,9 +22,11 @@ import javax.inject.Inject
|
|||
|
||||
class TimelineSettingsFactory @Inject constructor(private val userPreferencesProvider: UserPreferencesProvider) {
|
||||
|
||||
fun create(): TimelineSettings {
|
||||
fun create(rootThreadEventId: String?): TimelineSettings {
|
||||
return TimelineSettings(
|
||||
initialSize = 30,
|
||||
buildReadReceipts = userPreferencesProvider.shouldShowReadReceipts())
|
||||
buildReadReceipts = userPreferencesProvider.shouldShowReadReceipts(),
|
||||
rootThreadEventId = rootThreadEventId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue