[Room member list] Display room member list (#276)
* Implement room member list * Move timeline initialization back to `TimelinePresenter`. * Fix crash when the `innerRoom` inside a `RustMatrixRoom` is destroyed but `syncUpdateFlow` is still running. * Address review comments
This commit is contained in:
committed by
GitHub
parent
f0b95d30be
commit
d7a6779343
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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 io.element.android.features.createroom.impl
|
||||
|
||||
import io.element.android.features.userlist.api.MatrixUserDataSource
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO this is empty as we currently don't have an endpoint to perform user search
|
||||
class AllMatrixUsersDataSource @Inject constructor() : MatrixUserDataSource {
|
||||
override suspend fun search(query: String): List<MatrixUser> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override suspend fun getProfile(userId: UserId): MatrixUser? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -17,31 +17,38 @@
|
||||
package io.element.android.features.createroom.impl.addpeople
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.element.android.features.selectusers.api.SelectUsersPresenter
|
||||
import io.element.android.features.selectusers.api.SelectUsersPresenterArgs
|
||||
import io.element.android.features.selectusers.api.SelectionMode
|
||||
import io.element.android.features.userlist.api.SelectionMode
|
||||
import io.element.android.features.userlist.api.MatrixUserDataSource
|
||||
import io.element.android.features.userlist.api.UserListPresenter
|
||||
import io.element.android.features.userlist.api.UserListPresenterArgs
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class AddPeoplePresenter @Inject constructor(
|
||||
private val selectUsersPresenterFactory: SelectUsersPresenter.Factory,
|
||||
private val userListPresenterFactory: UserListPresenter.Factory,
|
||||
@Named("AllUsers") private val matrixUserDataSource: MatrixUserDataSource,
|
||||
) : Presenter<AddPeopleState> {
|
||||
|
||||
private val selectUsersPresenter by lazy {
|
||||
selectUsersPresenterFactory.create(SelectUsersPresenterArgs(SelectionMode.Multiple))
|
||||
private val userListPresenter by lazy {
|
||||
userListPresenterFactory.create(
|
||||
UserListPresenterArgs(selectionMode = SelectionMode.Multiple),
|
||||
matrixUserDataSource,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun present(): AddPeopleState {
|
||||
val selectUsersState = selectUsersPresenter.present()
|
||||
val userListState = userListPresenter.present()
|
||||
|
||||
fun handleEvents(event: AddPeopleEvents) {
|
||||
// do nothing for now
|
||||
}
|
||||
|
||||
return AddPeopleState(
|
||||
selectUsersState = selectUsersState,
|
||||
userListState = userListState,
|
||||
eventSink = ::handleEvents,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package io.element.android.features.createroom.impl.addpeople
|
||||
|
||||
import io.element.android.features.selectusers.api.SelectUsersState
|
||||
import io.element.android.features.userlist.api.UserListState
|
||||
|
||||
data class AddPeopleState(
|
||||
val selectUsersState: SelectUsersState,
|
||||
val userListState: UserListState,
|
||||
val eventSink: (AddPeopleEvents) -> Unit,
|
||||
)
|
||||
|
||||
@@ -17,22 +17,22 @@
|
||||
package io.element.android.features.createroom.impl.addpeople
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.features.selectusers.api.SelectionMode
|
||||
import io.element.android.features.selectusers.api.aListOfSelectedUsers
|
||||
import io.element.android.features.selectusers.api.aSelectUsersState
|
||||
import io.element.android.features.userlist.api.SelectionMode
|
||||
import io.element.android.features.userlist.api.aListOfSelectedUsers
|
||||
import io.element.android.features.userlist.api.aUserListState
|
||||
|
||||
open class AddPeopleStateProvider : PreviewParameterProvider<AddPeopleState> {
|
||||
override val values: Sequence<AddPeopleState>
|
||||
get() = sequenceOf(
|
||||
aAddPeopleState(),
|
||||
aAddPeopleState().copy(
|
||||
selectUsersState = aSelectUsersState().copy(
|
||||
userListState = aUserListState().copy(
|
||||
selectedUsers = aListOfSelectedUsers(),
|
||||
selectionMode = SelectionMode.Multiple,
|
||||
)
|
||||
),
|
||||
aAddPeopleState().copy(
|
||||
selectUsersState = aSelectUsersState().copy(
|
||||
userListState = aUserListState().copy(
|
||||
selectedUsers = aListOfSelectedUsers(),
|
||||
isSearchActive = true,
|
||||
selectionMode = SelectionMode.Multiple,
|
||||
@@ -42,6 +42,6 @@ open class AddPeopleStateProvider : PreviewParameterProvider<AddPeopleState> {
|
||||
}
|
||||
|
||||
fun aAddPeopleState() = AddPeopleState(
|
||||
selectUsersState = aSelectUsersState(),
|
||||
userListState = aUserListState(),
|
||||
eventSink = {}
|
||||
)
|
||||
|
||||
@@ -29,8 +29,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.features.userlist.api.UserListView
|
||||
import io.element.android.features.createroom.impl.R
|
||||
import io.element.android.features.selectusers.api.SelectUsersView
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
@@ -52,9 +52,9 @@ fun AddPeopleView(
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
if (!state.selectUsersState.isSearchActive) {
|
||||
if (!state.userListState.isSearchActive) {
|
||||
AddPeopleViewTopBar(
|
||||
hasSelectedUsers = state.selectUsersState.selectedUsers.isNotEmpty(),
|
||||
hasSelectedUsers = state.userListState.selectedUsers.isNotEmpty(),
|
||||
onBackPressed = onBackPressed,
|
||||
onNextPressed = onNextPressed,
|
||||
)
|
||||
@@ -66,9 +66,9 @@ fun AddPeopleView(
|
||||
.fillMaxSize()
|
||||
.padding(padding),
|
||||
) {
|
||||
SelectUsersView(
|
||||
UserListView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state = state.selectUsersState,
|
||||
state = state.userListState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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 io.element.android.features.createroom.impl.di
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesTo
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import io.element.android.features.createroom.impl.AllMatrixUsersDataSource
|
||||
import io.element.android.features.userlist.api.MatrixUserDataSource
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import javax.inject.Named
|
||||
|
||||
@Module
|
||||
@ContributesTo(AppScope::class)
|
||||
interface CreateRoomModule {
|
||||
|
||||
@Binds
|
||||
@Named("AllUsers")
|
||||
fun bindAllUserListDataSource(dataSource: AllMatrixUsersDataSource): MatrixUserDataSource
|
||||
|
||||
}
|
||||
@@ -17,25 +17,31 @@
|
||||
package io.element.android.features.createroom.impl.root
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.element.android.features.selectusers.api.SelectUsersPresenter
|
||||
import io.element.android.features.selectusers.api.SelectUsersPresenterArgs
|
||||
import io.element.android.features.selectusers.api.SelectionMode
|
||||
import io.element.android.features.userlist.api.SelectionMode
|
||||
import io.element.android.features.userlist.api.MatrixUserDataSource
|
||||
import io.element.android.features.userlist.api.UserListPresenter
|
||||
import io.element.android.features.userlist.api.UserListPresenterArgs
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
||||
class CreateRoomRootPresenter @Inject constructor(
|
||||
private val presenterFactory: SelectUsersPresenter.Factory,
|
||||
private val presenterFactory: UserListPresenter.Factory,
|
||||
@Named("AllUsers") private val matrixUserDataSource: MatrixUserDataSource,
|
||||
) : Presenter<CreateRoomRootState> {
|
||||
|
||||
private val presenter by lazy {
|
||||
presenterFactory.create(SelectUsersPresenterArgs(SelectionMode.Single))
|
||||
presenterFactory.create(
|
||||
UserListPresenterArgs(selectionMode = SelectionMode.Single),
|
||||
matrixUserDataSource,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun present(): CreateRoomRootState {
|
||||
val selectUsersState = presenter.present()
|
||||
val userListState = presenter.present()
|
||||
|
||||
fun handleEvents(event: CreateRoomRootEvents) {
|
||||
when (event) {
|
||||
@@ -45,7 +51,7 @@ class CreateRoomRootPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
return CreateRoomRootState(
|
||||
selectUsersState = selectUsersState,
|
||||
userListState = userListState,
|
||||
eventSink = ::handleEvents,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package io.element.android.features.createroom.impl.root
|
||||
|
||||
import io.element.android.features.selectusers.api.SelectUsersState
|
||||
import io.element.android.features.userlist.api.UserListState
|
||||
|
||||
data class CreateRoomRootState(
|
||||
val selectUsersState: SelectUsersState,
|
||||
val userListState: UserListState,
|
||||
val eventSink: (CreateRoomRootEvents) -> Unit,
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package io.element.android.features.createroom.impl.root
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.features.selectusers.api.aSelectUsersState
|
||||
import io.element.android.features.userlist.api.aUserListState
|
||||
|
||||
open class CreateRoomRootStateProvider : PreviewParameterProvider<CreateRoomRootState> {
|
||||
override val values: Sequence<CreateRoomRootState>
|
||||
@@ -28,5 +28,5 @@ open class CreateRoomRootStateProvider : PreviewParameterProvider<CreateRoomRoot
|
||||
|
||||
fun aCreateRoomRootState() = CreateRoomRootState(
|
||||
eventSink = {},
|
||||
selectUsersState = aSelectUsersState(),
|
||||
userListState = aUserListState(),
|
||||
)
|
||||
|
||||
@@ -37,8 +37,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.features.userlist.api.UserListView
|
||||
import io.element.android.features.createroom.impl.R
|
||||
import io.element.android.features.selectusers.api.SelectUsersView
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.CenterAlignedTopAppBar
|
||||
@@ -60,7 +60,7 @@ fun CreateRoomRootView(
|
||||
Scaffold(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
topBar = {
|
||||
if (!state.selectUsersState.isSearchActive) {
|
||||
if (!state.userListState.isSearchActive) {
|
||||
CreateRoomRootViewTopBar(onClosePressed = onClosePressed)
|
||||
}
|
||||
}
|
||||
@@ -69,13 +69,13 @@ fun CreateRoomRootView(
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
SelectUsersView(
|
||||
UserListView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state = state.selectUsersState,
|
||||
state = state.userListState,
|
||||
onUserSelected = { state.eventSink.invoke(CreateRoomRootEvents.StartDM(it)) },
|
||||
)
|
||||
|
||||
if (!state.selectUsersState.isSearchActive) {
|
||||
if (!state.userListState.isSearchActive) {
|
||||
CreateRoomActionButtonsList(
|
||||
onNewRoomClicked = onNewRoomClicked,
|
||||
onInvitePeopleClicked = { state.eventSink(CreateRoomRootEvents.InvitePeople) },
|
||||
|
||||
@@ -22,8 +22,10 @@ import app.cash.molecule.RecompositionClock
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.selectusers.api.SelectUsersPresenterArgs
|
||||
import io.element.android.features.selectusers.impl.DefaultSelectUsersPresenter
|
||||
import io.element.android.features.userlist.api.MatrixUserDataSource
|
||||
import io.element.android.features.userlist.api.UserListPresenterArgs
|
||||
import io.element.android.features.userlist.impl.DefaultUserListPresenter
|
||||
import io.element.android.features.userlist.test.FakeMatrixUserDataSource
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
@@ -35,10 +37,11 @@ class AddPeoplePresenterTests {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val selectUsersFactory = object : DefaultSelectUsersPresenter.DefaultSelectUsersFactory {
|
||||
override fun create(args: SelectUsersPresenterArgs) = DefaultSelectUsersPresenter(args)
|
||||
val userListFactory = object : DefaultUserListPresenter.DefaultUserListFactory {
|
||||
override fun create(args: UserListPresenterArgs, dataSource: MatrixUserDataSource) = DefaultUserListPresenter(args, dataSource)
|
||||
}
|
||||
presenter = AddPeoplePresenter(selectUsersFactory)
|
||||
val dataSource = FakeMatrixUserDataSource()
|
||||
presenter = AddPeoplePresenter(userListFactory, dataSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -51,3 +54,4 @@ class AddPeoplePresenterTests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,10 @@ import app.cash.molecule.RecompositionClock
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.selectusers.api.SelectUsersPresenterArgs
|
||||
import io.element.android.features.selectusers.impl.DefaultSelectUsersPresenter
|
||||
import io.element.android.features.userlist.api.MatrixUserDataSource
|
||||
import io.element.android.features.userlist.api.UserListPresenterArgs
|
||||
import io.element.android.features.userlist.impl.DefaultUserListPresenter
|
||||
import io.element.android.features.userlist.test.FakeMatrixUserDataSource
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@@ -33,14 +35,16 @@ import org.junit.Test
|
||||
|
||||
class CreateRoomRootPresenterTests {
|
||||
|
||||
private lateinit var userListDataSource: FakeMatrixUserDataSource
|
||||
private lateinit var presenter: CreateRoomRootPresenter
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val selectUsersPresenter = object : DefaultSelectUsersPresenter.DefaultSelectUsersFactory {
|
||||
override fun create(args: SelectUsersPresenterArgs) = DefaultSelectUsersPresenter(args)
|
||||
val userListPresenter = object : DefaultUserListPresenter.DefaultUserListFactory {
|
||||
override fun create(args: UserListPresenterArgs, dataSource: MatrixUserDataSource) = DefaultUserListPresenter(args, dataSource)
|
||||
}
|
||||
presenter = CreateRoomRootPresenter(selectUsersPresenter)
|
||||
userListDataSource = FakeMatrixUserDataSource()
|
||||
presenter = CreateRoomRootPresenter(userListPresenter, userListDataSource)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user