Merge pull request #4274 from element-hq/feature/bma/mediaTimelineImprovment
Update Matrix Room API and allow media swipe on pinned event only.
This commit is contained in:
commit
86afffb4bc
31 changed files with 296 additions and 185 deletions
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.room
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
|
||||
sealed interface CreateTimelineParams {
|
||||
data class Focused(val focusedEventId: EventId) : CreateTimelineParams
|
||||
data object MediaOnly : CreateTimelineParams
|
||||
data class MediaOnlyFocused(val focusedEventId: EventId) : CreateTimelineParams
|
||||
data object PinnedOnly : CreateTimelineParams
|
||||
}
|
||||
|
|
@ -109,21 +109,12 @@ interface MatrixRoom : Closeable {
|
|||
val liveTimeline: Timeline
|
||||
|
||||
/**
|
||||
* Create a new timeline, focused on the provided Event.
|
||||
* Should not be used directly, see `TimelineController` to manage the various timelines.
|
||||
* Create a new timeline.
|
||||
* @param createTimelineParams contains parameters about how to filter the timeline. Will also configure the date separators.
|
||||
*/
|
||||
suspend fun timelineFocusedOnEvent(eventId: EventId): Result<Timeline>
|
||||
|
||||
/**
|
||||
* Create a new timeline for the pinned events of the room.
|
||||
*/
|
||||
suspend fun pinnedEventsTimeline(): Result<Timeline>
|
||||
|
||||
/**
|
||||
* Create a new timeline for the media events of the room.
|
||||
* @param eventId The event to focus on, if any.
|
||||
*/
|
||||
suspend fun mediaTimeline(eventId: EventId?): Result<Timeline>
|
||||
suspend fun createTimeline(
|
||||
createTimelineParams: CreateTimelineParams,
|
||||
): Result<Timeline>
|
||||
|
||||
fun destroy()
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import io.element.android.libraries.matrix.api.media.MediaUploadHandler
|
|||
import io.element.android.libraries.matrix.api.media.VideoInfo
|
||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
||||
import io.element.android.libraries.matrix.api.poll.PollKind
|
||||
import io.element.android.libraries.matrix.api.room.CreateTimelineParams
|
||||
import io.element.android.libraries.matrix.api.room.IntentionalMention
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
|
||||
|
|
@ -214,80 +215,81 @@ class RustMatrixRoom(
|
|||
|
||||
override suspend fun subscribeToSync() = roomSyncSubscriber.subscribe(roomId)
|
||||
|
||||
override suspend fun timelineFocusedOnEvent(eventId: EventId): Result<Timeline> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
innerRoom.timelineWithConfiguration(
|
||||
configuration = TimelineConfiguration(
|
||||
focus = TimelineFocus.Event(
|
||||
eventId = eventId.value,
|
||||
numContextEvents = 50u,
|
||||
),
|
||||
allowedMessageTypes = AllowedMessageTypes.All,
|
||||
internalIdPrefix = "focus_$eventId",
|
||||
dateDividerMode = DateDividerMode.DAILY,
|
||||
)
|
||||
).let { inner ->
|
||||
createTimeline(inner, mode = Timeline.Mode.FOCUSED_ON_EVENT)
|
||||
}
|
||||
}.mapFailure {
|
||||
it.toFocusEventException()
|
||||
}.onFailure {
|
||||
if (it is CancellationException) {
|
||||
throw it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun pinnedEventsTimeline(): Result<Timeline> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
innerRoom.timelineWithConfiguration(
|
||||
configuration = TimelineConfiguration(
|
||||
focus = TimelineFocus.PinnedEvents(
|
||||
maxEventsToLoad = 100u,
|
||||
maxConcurrentRequests = 10u,
|
||||
),
|
||||
allowedMessageTypes = AllowedMessageTypes.All,
|
||||
internalIdPrefix = "pinned_events",
|
||||
dateDividerMode = DateDividerMode.DAILY,
|
||||
)
|
||||
).let { inner ->
|
||||
createTimeline(inner, mode = Timeline.Mode.PINNED_EVENTS)
|
||||
}
|
||||
}.onFailure {
|
||||
if (it is CancellationException) {
|
||||
throw it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun mediaTimeline(
|
||||
eventId: EventId?,
|
||||
override suspend fun createTimeline(
|
||||
createTimelineParams: CreateTimelineParams,
|
||||
): Result<Timeline> = withContext(roomDispatcher) {
|
||||
val focus = if (eventId != null) {
|
||||
TimelineFocus.Event(
|
||||
eventId = eventId.value,
|
||||
val focus = when (createTimelineParams) {
|
||||
is CreateTimelineParams.PinnedOnly -> TimelineFocus.PinnedEvents(
|
||||
maxEventsToLoad = 100u,
|
||||
maxConcurrentRequests = 10u,
|
||||
)
|
||||
is CreateTimelineParams.MediaOnly -> TimelineFocus.Live
|
||||
is CreateTimelineParams.Focused -> TimelineFocus.Event(
|
||||
eventId = createTimelineParams.focusedEventId.value,
|
||||
numContextEvents = 50u,
|
||||
)
|
||||
is CreateTimelineParams.MediaOnlyFocused -> TimelineFocus.Event(
|
||||
eventId = createTimelineParams.focusedEventId.value,
|
||||
numContextEvents = 50u,
|
||||
)
|
||||
} else {
|
||||
TimelineFocus.Live
|
||||
}
|
||||
|
||||
val allowedMessageTypes = when (createTimelineParams) {
|
||||
is CreateTimelineParams.MediaOnly,
|
||||
is CreateTimelineParams.MediaOnlyFocused -> AllowedMessageTypes.Only(
|
||||
types = listOf(
|
||||
RoomMessageEventMessageType.FILE,
|
||||
RoomMessageEventMessageType.IMAGE,
|
||||
RoomMessageEventMessageType.VIDEO,
|
||||
RoomMessageEventMessageType.AUDIO,
|
||||
)
|
||||
)
|
||||
is CreateTimelineParams.Focused,
|
||||
CreateTimelineParams.PinnedOnly -> AllowedMessageTypes.All
|
||||
}
|
||||
|
||||
val internalIdPrefix = when (createTimelineParams) {
|
||||
is CreateTimelineParams.PinnedOnly -> "pinned_events"
|
||||
is CreateTimelineParams.Focused -> "focus_${createTimelineParams.focusedEventId}"
|
||||
is CreateTimelineParams.MediaOnly -> "MediaGallery_"
|
||||
is CreateTimelineParams.MediaOnlyFocused -> "MediaGallery_${createTimelineParams.focusedEventId}"
|
||||
}
|
||||
|
||||
// Note that for TimelineFilter.MediaOnlyFocused, the date separator will be filtered out,
|
||||
// but there is no way to exclude data separator at the moment.
|
||||
val dateDividerMode = when (createTimelineParams) {
|
||||
is CreateTimelineParams.MediaOnly,
|
||||
is CreateTimelineParams.MediaOnlyFocused -> DateDividerMode.MONTHLY
|
||||
is CreateTimelineParams.Focused,
|
||||
CreateTimelineParams.PinnedOnly -> DateDividerMode.DAILY
|
||||
}
|
||||
|
||||
runCatching {
|
||||
innerRoom.timelineWithConfiguration(
|
||||
configuration = TimelineConfiguration(
|
||||
focus = focus,
|
||||
allowedMessageTypes = AllowedMessageTypes.Only(
|
||||
types = listOf(
|
||||
RoomMessageEventMessageType.FILE,
|
||||
RoomMessageEventMessageType.IMAGE,
|
||||
RoomMessageEventMessageType.VIDEO,
|
||||
RoomMessageEventMessageType.AUDIO,
|
||||
)
|
||||
),
|
||||
internalIdPrefix = "MediaGallery_",
|
||||
dateDividerMode = DateDividerMode.MONTHLY,
|
||||
allowedMessageTypes = allowedMessageTypes,
|
||||
internalIdPrefix = internalIdPrefix,
|
||||
dateDividerMode = dateDividerMode,
|
||||
)
|
||||
).let { inner ->
|
||||
createTimeline(inner, mode = if (eventId != null) Timeline.Mode.FOCUSED_ON_EVENT else Timeline.Mode.MEDIA)
|
||||
val mode = when (createTimelineParams) {
|
||||
is CreateTimelineParams.Focused -> Timeline.Mode.FOCUSED_ON_EVENT
|
||||
is CreateTimelineParams.MediaOnly -> Timeline.Mode.MEDIA
|
||||
is CreateTimelineParams.MediaOnlyFocused -> Timeline.Mode.FOCUSED_ON_EVENT
|
||||
CreateTimelineParams.PinnedOnly -> Timeline.Mode.PINNED_EVENTS
|
||||
}
|
||||
createTimeline(
|
||||
timeline = inner,
|
||||
mode = mode,
|
||||
)
|
||||
}
|
||||
}.mapFailure {
|
||||
when (createTimelineParams) {
|
||||
is CreateTimelineParams.Focused,
|
||||
is CreateTimelineParams.MediaOnlyFocused -> it.toFocusEventException()
|
||||
CreateTimelineParams.MediaOnly,
|
||||
CreateTimelineParams.PinnedOnly -> it
|
||||
}
|
||||
}.onFailure {
|
||||
if (it is CancellationException) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.api.media.MediaUploadHandler
|
|||
import io.element.android.libraries.matrix.api.media.VideoInfo
|
||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
||||
import io.element.android.libraries.matrix.api.poll.PollKind
|
||||
import io.element.android.libraries.matrix.api.room.CreateTimelineParams
|
||||
import io.element.android.libraries.matrix.api.room.IntentionalMention
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
|
||||
|
|
@ -138,9 +139,7 @@ class FakeMatrixRoom(
|
|||
private val leaveRoomLambda: () -> Result<Unit> = { lambdaError() },
|
||||
private val updateMembersResult: () -> Unit = { lambdaError() },
|
||||
private val getMembersResult: (Int) -> Result<List<RoomMember>> = { lambdaError() },
|
||||
private val timelineFocusedOnEventResult: (EventId) -> Result<Timeline> = { lambdaError() },
|
||||
private val pinnedEventsTimelineResult: () -> Result<Timeline> = { lambdaError() },
|
||||
private val mediaTimelineResult: (EventId?) -> Result<Timeline> = { lambdaError() },
|
||||
private val createTimelineResult: (CreateTimelineParams) -> Result<Timeline> = { lambdaError() },
|
||||
private val setSendQueueEnabledLambda: (Boolean) -> Unit = { _: Boolean -> },
|
||||
private val saveComposerDraftLambda: (ComposerDraft) -> Result<Unit> = { _: ComposerDraft -> Result.success(Unit) },
|
||||
private val loadComposerDraftLambda: () -> Result<ComposerDraft?> = { Result.success<ComposerDraft?>(null) },
|
||||
|
|
@ -220,16 +219,10 @@ class FakeMatrixRoom(
|
|||
_syncUpdateFlow.tryEmit(_syncUpdateFlow.value + 1)
|
||||
}
|
||||
|
||||
override suspend fun timelineFocusedOnEvent(eventId: EventId): Result<Timeline> = simulateLongTask {
|
||||
timelineFocusedOnEventResult(eventId)
|
||||
}
|
||||
|
||||
override suspend fun pinnedEventsTimeline(): Result<Timeline> = simulateLongTask {
|
||||
pinnedEventsTimelineResult()
|
||||
}
|
||||
|
||||
override suspend fun mediaTimeline(eventId: EventId?): Result<Timeline> = simulateLongTask {
|
||||
mediaTimelineResult(eventId)
|
||||
override suspend fun createTimeline(
|
||||
createTimelineParams: CreateTimelineParams,
|
||||
): Result<Timeline> = simulateLongTask {
|
||||
createTimelineResult(createTimelineParams)
|
||||
}
|
||||
|
||||
override suspend fun subscribeToSync() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue