Feature: add room threads list (#6575)

Add threads list screen for rooms:

- Add `ThreadsListService` to subscribe to thread changes in the room.
- Create `ThreadsListView` and its associated node a presenters (the UI may change).
- Add a menu icon in the room screen to open it.

This is still pending info about unread threads, so several UI components related to it will be hidden.

* Add feature flag and use it to hide the access to this new screen

---------

Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Jorge Martin Espinosa 2026-04-15 14:14:22 +02:00 committed by GitHub
parent be775d686e
commit 80470b3792
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 1357 additions and 45 deletions

View file

@ -35,6 +35,7 @@ import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.threads.FakeThreadsListService
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.simulateLongTask
@ -56,6 +57,7 @@ class FakeJoinedRoom(
override val roomNotificationSettingsStateFlow: StateFlow<RoomNotificationSettingsState> =
MutableStateFlow(RoomNotificationSettingsState.Unknown),
override val knockRequestsFlow: Flow<List<KnockRequest>> = MutableStateFlow(emptyList()),
override val threadsListService: FakeThreadsListService = FakeThreadsListService(),
private val roomNotificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
private var createTimelineResult: (CreateTimelineParams) -> Result<Timeline> = { lambdaError() },
private val editMessageLambda: (EventId, String, String?, List<IntentionalMention>) -> Result<Unit> = { _, _, _, _ -> lambdaError() },

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2026 Element Creations 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.test.room.threads
import io.element.android.libraries.matrix.api.room.threads.ThreadListItem
import io.element.android.libraries.matrix.api.room.threads.ThreadListPaginationStatus
import io.element.android.libraries.matrix.api.room.threads.ThreadsListService
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
class FakeThreadsListService(
private val items: MutableStateFlow<List<ThreadListItem>> = MutableStateFlow(emptyList()),
private val paginationStatus: MutableStateFlow<ThreadListPaginationStatus> = MutableStateFlow(ThreadListPaginationStatus.Idle(hasMoreToLoad = true)),
private val subscribeToItemUpdates: () -> Flow<List<ThreadListItem>> = { items },
private val subscribeToPaginationUpdates: () -> Flow<ThreadListPaginationStatus> = { paginationStatus },
private val paginate: suspend () -> Result<Unit> = { Result.success(Unit) },
private val reset: suspend () -> Result<Unit> = { Result.success(Unit) },
private val destroy: () -> Unit = {},
) : ThreadsListService {
override fun subscribeToItemUpdates(): Flow<List<ThreadListItem>> {
return subscribeToItemUpdates.invoke()
}
override fun subscribeToPaginationUpdates(): Flow<ThreadListPaginationStatus> {
return subscribeToPaginationUpdates.invoke()
}
override suspend fun paginate(): Result<Unit> {
return paginate.invoke()
}
override suspend fun reset(): Result<Unit> {
return reset.invoke()
}
override fun destroy() {
return destroy.invoke()
}
suspend fun emit(items: List<ThreadListItem>) {
this.items.emit(items)
}
}