change(members): make sure state is not lost when navigating
This commit is contained in:
parent
80d799c4db
commit
dcaac703fc
6 changed files with 153 additions and 125 deletions
|
|
@ -11,6 +11,7 @@ package io.element.android.features.roomdetails.impl.members
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||||
|
|
||||||
sealed interface RoomMemberListEvents {
|
sealed interface RoomMemberListEvents {
|
||||||
|
data class ChangeSelectedSection(val section: SelectedSection): RoomMemberListEvents
|
||||||
data class UpdateSearchQuery(val query: String) : RoomMemberListEvents
|
data class UpdateSearchQuery(val query: String) : RoomMemberListEvents
|
||||||
data class OnSearchActiveChanged(val active: Boolean) : RoomMemberListEvents
|
data class OnSearchActiveChanged(val active: Boolean) : RoomMemberListEvents
|
||||||
data class RoomMemberSelected(val roomMember: RoomMember) : RoomMemberListEvents
|
data class RoomMemberSelected(val roomMember: RoomMember) : RoomMemberListEvents
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
package io.element.android.features.roomdetails.impl.members
|
package io.element.android.features.roomdetails.impl.members
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import com.bumble.appyx.core.lifecycle.subscribe
|
import com.bumble.appyx.core.lifecycle.subscribe
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
|
|
@ -21,6 +23,7 @@ import io.element.android.annotations.ContributesNode
|
||||||
import io.element.android.features.roommembermoderation.api.ModerationAction
|
import io.element.android.features.roommembermoderation.api.ModerationAction
|
||||||
import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents
|
import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents
|
||||||
import io.element.android.features.roommembermoderation.api.RoomMemberModerationRenderer
|
import io.element.android.features.roommembermoderation.api.RoomMemberModerationRenderer
|
||||||
|
import io.element.android.libraries.architecture.appyx.launchMolecule
|
||||||
import io.element.android.libraries.architecture.callback
|
import io.element.android.libraries.architecture.callback
|
||||||
import io.element.android.libraries.di.RoomScope
|
import io.element.android.libraries.di.RoomScope
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
|
|
@ -41,6 +44,7 @@ class RoomMemberListNode(
|
||||||
}
|
}
|
||||||
|
|
||||||
private val callback: Callback = callback()
|
private val callback: Callback = callback()
|
||||||
|
private val stateFlow = launchMolecule { presenter.present() }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
lifecycle.subscribe(
|
lifecycle.subscribe(
|
||||||
|
|
@ -64,7 +68,7 @@ class RoomMemberListNode(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
val state = presenter.present()
|
val state by stateFlow.collectAsState()
|
||||||
RoomMemberListView(
|
RoomMemberListView(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ package io.element.android.features.roomdetails.impl.members
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
|
@ -18,7 +19,7 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import dev.zacsweers.metro.Inject
|
import dev.zacsweers.metro.Inject
|
||||||
import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents
|
import io.element.android.features.roommembermoderation.api.RoomMemberModerationEvents.ShowActionsForUser
|
||||||
import io.element.android.features.roommembermoderation.api.RoomMemberModerationState
|
import io.element.android.features.roommembermoderation.api.RoomMemberModerationState
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
|
|
@ -53,7 +54,7 @@ class RoomMemberListPresenter(
|
||||||
private val roomMembersModerationPresenter: Presenter<RoomMemberModerationState>,
|
private val roomMembersModerationPresenter: Presenter<RoomMemberModerationState>,
|
||||||
private val encryptionService: EncryptionService,
|
private val encryptionService: EncryptionService,
|
||||||
) : Presenter<RoomMemberListState> {
|
) : Presenter<RoomMemberListState> {
|
||||||
private var roomMembers: AsyncData<RoomMembers> by mutableStateOf(AsyncData.Loading())
|
|
||||||
private val powerLevelRoomMemberComparator = PowerLevelRoomMemberComparator()
|
private val powerLevelRoomMemberComparator = PowerLevelRoomMemberComparator()
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -77,6 +78,9 @@ class RoomMemberListPresenter(
|
||||||
.launchIn(this)
|
.launchIn(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var roomMembers: AsyncData<RoomMembers> by remember { mutableStateOf(AsyncData.Loading())}
|
||||||
|
var selectedSection by remember { mutableStateOf(SelectedSection.MEMBERS)}
|
||||||
|
|
||||||
// Update the room members when the screen is loaded
|
// Update the room members when the screen is loaded
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
room.updateMembers()
|
room.updateMembers()
|
||||||
|
|
@ -160,7 +164,14 @@ class RoomMemberListPresenter(
|
||||||
is RoomMemberListEvents.OnSearchActiveChanged -> isSearchActive = event.active
|
is RoomMemberListEvents.OnSearchActiveChanged -> isSearchActive = event.active
|
||||||
is RoomMemberListEvents.UpdateSearchQuery -> searchQuery = event.query
|
is RoomMemberListEvents.UpdateSearchQuery -> searchQuery = event.query
|
||||||
is RoomMemberListEvents.RoomMemberSelected ->
|
is RoomMemberListEvents.RoomMemberSelected ->
|
||||||
roomModerationState.eventSink(RoomMemberModerationEvents.ShowActionsForUser(event.roomMember.toMatrixUser()))
|
roomModerationState.eventSink(ShowActionsForUser(event.roomMember.toMatrixUser()))
|
||||||
|
is RoomMemberListEvents.ChangeSelectedSection -> selectedSection = event.section
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!roomModerationState.canBan && selectedSection == SelectedSection.BANNED) {
|
||||||
|
SideEffect {
|
||||||
|
selectedSection = SelectedSection.MEMBERS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,6 +182,7 @@ class RoomMemberListPresenter(
|
||||||
isSearchActive = isSearchActive,
|
isSearchActive = isSearchActive,
|
||||||
canInvite = canInvite,
|
canInvite = canInvite,
|
||||||
moderationState = roomModerationState,
|
moderationState = roomModerationState,
|
||||||
|
selectedSection = selectedSection,
|
||||||
eventSink = ::handleEvent,
|
eventSink = ::handleEvent,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,16 @@ data class RoomMemberListState(
|
||||||
val searchResults: SearchBarResultState<AsyncData<RoomMembers>>,
|
val searchResults: SearchBarResultState<AsyncData<RoomMembers>>,
|
||||||
val isSearchActive: Boolean,
|
val isSearchActive: Boolean,
|
||||||
val canInvite: Boolean,
|
val canInvite: Boolean,
|
||||||
|
val selectedSection: SelectedSection,
|
||||||
val moderationState: RoomMemberModerationState,
|
val moderationState: RoomMemberModerationState,
|
||||||
val eventSink: (RoomMemberListEvents) -> Unit,
|
val eventSink: (RoomMemberListEvents) -> Unit,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
enum class SelectedSection {
|
||||||
|
MEMBERS,
|
||||||
|
BANNED
|
||||||
|
}
|
||||||
|
|
||||||
data class RoomMembers(
|
data class RoomMembers(
|
||||||
val invited: ImmutableList<RoomMemberWithIdentityState>,
|
val invited: ImmutableList<RoomMemberWithIdentityState>,
|
||||||
val joined: ImmutableList<RoomMemberWithIdentityState>,
|
val joined: ImmutableList<RoomMemberWithIdentityState>,
|
||||||
|
|
|
||||||
|
|
@ -21,107 +21,131 @@ import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
internal class RoomMemberListStateProvider : PreviewParameterProvider<RoomMemberListState> {
|
internal class RoomMemberListStateProvider : PreviewParameterProvider<RoomMemberListState> {
|
||||||
override val values: Sequence<RoomMemberListState>
|
override val values: Sequence<RoomMemberListState>
|
||||||
get() = sequenceOf(
|
get() = roomMemberListStates() + bannedRoomMemberListStates()
|
||||||
aRoomMemberListState(
|
|
||||||
roomMembers = AsyncData.Success(
|
|
||||||
RoomMembers(
|
|
||||||
invited = persistentListOf(aVictor().withIdentity(), aWalter().withIdentity()),
|
|
||||||
joined = persistentListOf(anAlice().withIdentity(), aBob().withIdentity(), aWalter().withIdentity()),
|
|
||||||
banned = persistentListOf(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
aRoomMemberListState(
|
|
||||||
roomMembers = AsyncData.Success(
|
|
||||||
RoomMembers(
|
|
||||||
invited = persistentListOf(aVictor().withIdentity(), aWalter().withIdentity()),
|
|
||||||
joined = persistentListOf(
|
|
||||||
anAlice().withIdentity(identityState = IdentityState.Verified),
|
|
||||||
aBob().withIdentity(identityState = IdentityState.PinViolation),
|
|
||||||
aWalter().withIdentity(identityState = IdentityState.VerificationViolation)
|
|
||||||
),
|
|
||||||
banned = persistentListOf(),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
moderationState = aRoomMemberModerationState(canBan = true)
|
|
||||||
),
|
|
||||||
aRoomMemberListState(roomMembers = AsyncData.Loading()),
|
|
||||||
aRoomMemberListState().copy(canInvite = true),
|
|
||||||
aRoomMemberListState().copy(isSearchActive = false),
|
|
||||||
aRoomMemberListState().copy(isSearchActive = true),
|
|
||||||
aRoomMemberListState().copy(isSearchActive = true, searchQuery = "someone"),
|
|
||||||
aRoomMemberListState().copy(
|
|
||||||
isSearchActive = true,
|
|
||||||
searchQuery = "@someone:matrix.org",
|
|
||||||
searchResults = SearchBarResultState.Results(
|
|
||||||
AsyncData.Success(
|
|
||||||
RoomMembers(
|
|
||||||
invited = persistentListOf(aVictor().withIdentity()),
|
|
||||||
joined = persistentListOf(anAlice().withIdentity()),
|
|
||||||
banned = persistentListOf(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
aRoomMemberListState().copy(
|
|
||||||
isSearchActive = true,
|
|
||||||
searchQuery = "something-with-no-results",
|
|
||||||
searchResults = SearchBarResultState.NoResultsFound()
|
|
||||||
),
|
|
||||||
aRoomMemberListState(
|
|
||||||
roomMembers = AsyncData.Failure(Exception("Error details")),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class RoomMemberListStateBannedProvider : PreviewParameterProvider<RoomMemberListState> {
|
private fun roomMemberListStates(): Sequence<RoomMemberListState> = sequenceOf(
|
||||||
override val values: Sequence<RoomMemberListState>
|
aRoomMemberListState(
|
||||||
get() = sequenceOf(
|
roomMembers = AsyncData.Success(
|
||||||
aRoomMemberListState(
|
RoomMembers(
|
||||||
roomMembers = AsyncData.Success(
|
invited = persistentListOf(aVictor().withIdentity(), aWalter().withIdentity()),
|
||||||
RoomMembers(
|
joined = persistentListOf(anAlice().withIdentity(), aBob().withIdentity(), aWalter().withIdentity()),
|
||||||
invited = persistentListOf(),
|
banned = persistentListOf(),
|
||||||
joined = persistentListOf(),
|
|
||||||
banned = persistentListOf(
|
|
||||||
aRoomMember(userId = UserId("@alice:example.com"), displayName = "Alice").withIdentity(),
|
|
||||||
aRoomMember(userId = UserId("@bob:example.com"), displayName = "Bob").withIdentity(),
|
|
||||||
aRoomMember(userId = UserId("@charlie:example.com"), displayName = "Charlie").withIdentity(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
moderationState = aRoomMemberModerationState(),
|
|
||||||
),
|
),
|
||||||
aRoomMemberListState(
|
),
|
||||||
roomMembers = AsyncData.Loading(
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
RoomMembers(
|
),
|
||||||
invited = persistentListOf(),
|
aRoomMemberListState(
|
||||||
joined = persistentListOf(),
|
roomMembers = AsyncData.Success(
|
||||||
banned = persistentListOf(
|
RoomMembers(
|
||||||
aRoomMember(userId = UserId("@alice:example.com"), displayName = "Alice").withIdentity(),
|
invited = persistentListOf(aVictor().withIdentity(), aWalter().withIdentity()),
|
||||||
aRoomMember(userId = UserId("@bob:example.com"), displayName = "Bob").withIdentity(),
|
joined = persistentListOf(
|
||||||
aRoomMember(userId = UserId("@charlie:example.com"), displayName = "Charlie").withIdentity(),
|
anAlice().withIdentity(identityState = IdentityState.Verified),
|
||||||
),
|
aBob().withIdentity(identityState = IdentityState.PinViolation),
|
||||||
)
|
aWalter().withIdentity(identityState = IdentityState.VerificationViolation)
|
||||||
),
|
),
|
||||||
moderationState = aRoomMemberModerationState(),
|
banned = persistentListOf(),
|
||||||
),
|
|
||||||
aRoomMemberListState(
|
|
||||||
roomMembers = AsyncData.Success(
|
|
||||||
RoomMembers(
|
|
||||||
invited = persistentListOf(),
|
|
||||||
joined = persistentListOf(),
|
|
||||||
banned = persistentListOf(),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
moderationState = aRoomMemberModerationState(),
|
|
||||||
)
|
)
|
||||||
)
|
),
|
||||||
}
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
|
moderationState = aRoomMemberModerationState(canBan = true)
|
||||||
|
),
|
||||||
|
aRoomMemberListState(
|
||||||
|
roomMembers = AsyncData.Loading(),
|
||||||
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
|
),
|
||||||
|
aRoomMemberListState().copy(
|
||||||
|
canInvite = true,
|
||||||
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
|
),
|
||||||
|
aRoomMemberListState().copy(
|
||||||
|
isSearchActive = false,
|
||||||
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
|
),
|
||||||
|
aRoomMemberListState().copy(
|
||||||
|
isSearchActive = true,
|
||||||
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
|
),
|
||||||
|
aRoomMemberListState().copy(
|
||||||
|
isSearchActive = true,
|
||||||
|
searchQuery = "someone",
|
||||||
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
|
),
|
||||||
|
aRoomMemberListState().copy(
|
||||||
|
isSearchActive = true,
|
||||||
|
searchQuery = "@someone:matrix.org",
|
||||||
|
searchResults = SearchBarResultState.Results(
|
||||||
|
AsyncData.Success(
|
||||||
|
RoomMembers(
|
||||||
|
invited = persistentListOf(aVictor().withIdentity()),
|
||||||
|
joined = persistentListOf(anAlice().withIdentity()),
|
||||||
|
banned = persistentListOf(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
|
),
|
||||||
|
aRoomMemberListState().copy(
|
||||||
|
isSearchActive = true,
|
||||||
|
searchQuery = "something-with-no-results",
|
||||||
|
searchResults = SearchBarResultState.NoResultsFound(),
|
||||||
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
|
),
|
||||||
|
aRoomMemberListState(
|
||||||
|
roomMembers = AsyncData.Failure(Exception("Error details")),
|
||||||
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun bannedRoomMemberListStates(): Sequence<RoomMemberListState> = sequenceOf(
|
||||||
|
aRoomMemberListState(
|
||||||
|
roomMembers = AsyncData.Success(
|
||||||
|
RoomMembers(
|
||||||
|
invited = persistentListOf(),
|
||||||
|
joined = persistentListOf(),
|
||||||
|
banned = persistentListOf(
|
||||||
|
aRoomMember(userId = UserId("@alice:example.com"), displayName = "Alice").withIdentity(),
|
||||||
|
aRoomMember(userId = UserId("@bob:example.com"), displayName = "Bob").withIdentity(),
|
||||||
|
aRoomMember(userId = UserId("@charlie:example.com"), displayName = "Charlie").withIdentity(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
moderationState = aRoomMemberModerationState(),
|
||||||
|
selectedSection = SelectedSection.BANNED,
|
||||||
|
),
|
||||||
|
aRoomMemberListState(
|
||||||
|
roomMembers = AsyncData.Loading(
|
||||||
|
RoomMembers(
|
||||||
|
invited = persistentListOf(),
|
||||||
|
joined = persistentListOf(),
|
||||||
|
banned = persistentListOf(
|
||||||
|
aRoomMember(userId = UserId("@alice:example.com"), displayName = "Alice").withIdentity(),
|
||||||
|
aRoomMember(userId = UserId("@bob:example.com"), displayName = "Bob").withIdentity(),
|
||||||
|
aRoomMember(userId = UserId("@charlie:example.com"), displayName = "Charlie").withIdentity(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
moderationState = aRoomMemberModerationState(),
|
||||||
|
selectedSection = SelectedSection.BANNED,
|
||||||
|
),
|
||||||
|
aRoomMemberListState(
|
||||||
|
roomMembers = AsyncData.Success(
|
||||||
|
RoomMembers(
|
||||||
|
invited = persistentListOf(),
|
||||||
|
joined = persistentListOf(),
|
||||||
|
banned = persistentListOf(),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
moderationState = aRoomMemberModerationState(),
|
||||||
|
selectedSection = SelectedSection.BANNED,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
internal fun aRoomMemberListState(
|
internal fun aRoomMemberListState(
|
||||||
roomMembers: AsyncData<RoomMembers> = AsyncData.Loading(),
|
roomMembers: AsyncData<RoomMembers> = AsyncData.Loading(),
|
||||||
searchResults: SearchBarResultState<AsyncData<RoomMembers>> = SearchBarResultState.Initial(),
|
searchResults: SearchBarResultState<AsyncData<RoomMembers>> = SearchBarResultState.Initial(),
|
||||||
moderationState: RoomMemberModerationState = aRoomMemberModerationState(),
|
moderationState: RoomMemberModerationState = aRoomMemberModerationState(),
|
||||||
|
selectedSection: SelectedSection = SelectedSection.MEMBERS,
|
||||||
) = RoomMemberListState(
|
) = RoomMemberListState(
|
||||||
roomMembers = roomMembers,
|
roomMembers = roomMembers,
|
||||||
searchQuery = "",
|
searchQuery = "",
|
||||||
|
|
@ -129,6 +153,7 @@ internal fun aRoomMemberListState(
|
||||||
isSearchActive = false,
|
isSearchActive = false,
|
||||||
canInvite = false,
|
canInvite = false,
|
||||||
moderationState = moderationState,
|
moderationState = moderationState,
|
||||||
|
selectedSection = SelectedSection.MEMBERS,
|
||||||
eventSink = {}
|
eventSink = {}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.SideEffect
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -48,6 +45,7 @@ import io.element.android.features.roomdetails.impl.R
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
|
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||||
|
|
@ -68,17 +66,11 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
private enum class SelectedSection {
|
|
||||||
MEMBERS,
|
|
||||||
BANNED
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RoomMemberListView(
|
fun RoomMemberListView(
|
||||||
state: RoomMemberListState,
|
state: RoomMemberListState,
|
||||||
navigator: RoomMemberListNavigator,
|
navigator: RoomMemberListNavigator,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
initialSelectedSectionIndex: Int = 0,
|
|
||||||
) {
|
) {
|
||||||
fun onSelectUser(roomMember: RoomMember) {
|
fun onSelectUser(roomMember: RoomMember) {
|
||||||
state.eventSink(RoomMemberListEvents.RoomMemberSelected(roomMember))
|
state.eventSink(RoomMemberListEvents.RoomMemberSelected(roomMember))
|
||||||
|
|
@ -96,12 +88,6 @@ fun RoomMemberListView(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
var selectedSection by remember { mutableStateOf(SelectedSection.entries[initialSelectedSectionIndex]) }
|
|
||||||
if (!state.moderationState.canBan && selectedSection == SelectedSection.BANNED) {
|
|
||||||
SideEffect {
|
|
||||||
selectedSection = SelectedSection.MEMBERS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|
@ -117,7 +103,7 @@ fun RoomMemberListView(
|
||||||
onActiveChange = { state.eventSink(RoomMemberListEvents.OnSearchActiveChanged(it)) },
|
onActiveChange = { state.eventSink(RoomMemberListEvents.OnSearchActiveChanged(it)) },
|
||||||
onTextChange = { state.eventSink(RoomMemberListEvents.UpdateSearchQuery(it)) },
|
onTextChange = { state.eventSink(RoomMemberListEvents.UpdateSearchQuery(it)) },
|
||||||
onSelectUser = ::onSelectUser,
|
onSelectUser = ::onSelectUser,
|
||||||
selectedSection = selectedSection,
|
selectedSection = state.selectedSection,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -126,8 +112,8 @@ fun RoomMemberListView(
|
||||||
roomMembers = state.roomMembers,
|
roomMembers = state.roomMembers,
|
||||||
showMembersCount = true,
|
showMembersCount = true,
|
||||||
canDisplayBannedUsersControls = state.moderationState.canBan,
|
canDisplayBannedUsersControls = state.moderationState.canBan,
|
||||||
selectedSection = selectedSection,
|
selectedSection = state.selectedSection,
|
||||||
onSelectedSectionChange = { selectedSection = it },
|
onSelectedSectionChange = { state.eventSink(RoomMemberListEvents.ChangeSelectedSection(it)) },
|
||||||
onSelectUser = ::onSelectUser,
|
onSelectUser = ::onSelectUser,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -380,9 +366,13 @@ private fun RoomMemberSearchBar(
|
||||||
selectedSection: SelectedSection,
|
selectedSection: SelectedSection,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
var queryFieldState by textFieldState(query)
|
||||||
SearchBar(
|
SearchBar(
|
||||||
query = query,
|
query = queryFieldState,
|
||||||
onQueryChange = onTextChange,
|
onQueryChange = { newQuery ->
|
||||||
|
queryFieldState = newQuery
|
||||||
|
onTextChange(newQuery)
|
||||||
|
},
|
||||||
active = active,
|
active = active,
|
||||||
onActiveChange = onActiveChange,
|
onActiveChange = onActiveChange,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
|
@ -409,13 +399,3 @@ internal fun RoomMemberListViewPreview(@PreviewParameter(RoomMemberListStateProv
|
||||||
navigator = object : RoomMemberListNavigator {},
|
navigator = object : RoomMemberListNavigator {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreviewsDayNight
|
|
||||||
@Composable
|
|
||||||
internal fun RoomMemberListViewBannedPreview(@PreviewParameter(RoomMemberListStateBannedProvider::class) state: RoomMemberListState) = ElementPreview {
|
|
||||||
RoomMemberListView(
|
|
||||||
initialSelectedSectionIndex = 1,
|
|
||||||
state = state,
|
|
||||||
navigator = object : RoomMemberListNavigator {},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue