Iterate on space "Add existing rooms" logic and ui
This commit is contained in:
parent
9fe7c50972
commit
ca1d98928d
6 changed files with 106 additions and 91 deletions
|
|
@ -10,11 +10,11 @@ package io.element.android.features.space.impl.addroom
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
|
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
|
||||||
|
|
||||||
sealed interface AddRoomToSpaceEvents {
|
sealed interface AddRoomToSpaceEvent {
|
||||||
data class ToggleRoom(val room: SelectRoomInfo) : AddRoomToSpaceEvents
|
data class ToggleRoom(val room: SelectRoomInfo) : AddRoomToSpaceEvent
|
||||||
data class UpdateSearchQuery(val query: String) : AddRoomToSpaceEvents
|
data class UpdateSearchQuery(val query: String) : AddRoomToSpaceEvent
|
||||||
data class OnSearchActiveChanged(val active: Boolean) : AddRoomToSpaceEvents
|
data class OnSearchActiveChanged(val active: Boolean) : AddRoomToSpaceEvent
|
||||||
data object Save : AddRoomToSpaceEvents
|
data object Save : AddRoomToSpaceEvent
|
||||||
data object CloseSearch : AddRoomToSpaceEvents
|
data object CloseSearch : AddRoomToSpaceEvent
|
||||||
data object ClearError : AddRoomToSpaceEvents
|
data object ResetSaveAction : AddRoomToSpaceEvent
|
||||||
}
|
}
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
package io.element.android.features.space.impl.addroom
|
package io.element.android.features.space.impl.addroom
|
||||||
|
|
||||||
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.modality.BuildContext
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
import com.bumble.appyx.core.node.Node
|
import com.bumble.appyx.core.node.Node
|
||||||
|
|
@ -17,6 +19,7 @@ import dev.zacsweers.metro.Assisted
|
||||||
import dev.zacsweers.metro.AssistedInject
|
import dev.zacsweers.metro.AssistedInject
|
||||||
import io.element.android.annotations.ContributesNode
|
import io.element.android.annotations.ContributesNode
|
||||||
import io.element.android.features.space.impl.di.SpaceFlowScope
|
import io.element.android.features.space.impl.di.SpaceFlowScope
|
||||||
|
import io.element.android.libraries.architecture.appyx.launchMolecule
|
||||||
import io.element.android.libraries.architecture.callback
|
import io.element.android.libraries.architecture.callback
|
||||||
|
|
||||||
@ContributesNode(SpaceFlowScope::class)
|
@ContributesNode(SpaceFlowScope::class)
|
||||||
|
|
@ -31,10 +34,11 @@ class AddRoomToSpaceNode(
|
||||||
}
|
}
|
||||||
|
|
||||||
private val callback: Callback = callback()
|
private val callback: Callback = callback()
|
||||||
|
private val stateFlow = launchMolecule { presenter.present() }
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
val state = presenter.present()
|
val state by stateFlow.collectAsState()
|
||||||
AddRoomToSpaceView(
|
AddRoomToSpaceView(
|
||||||
state = state,
|
state = state,
|
||||||
onBackClick = ::navigateUp,
|
onBackClick = ::navigateUp,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.produceState
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import dev.zacsweers.metro.Inject
|
import dev.zacsweers.metro.Inject
|
||||||
|
|
@ -25,34 +24,22 @@ import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.architecture.runUpdatingState
|
import io.element.android.libraries.architecture.runUpdatingState
|
||||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
|
||||||
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
|
||||||
import io.element.android.libraries.matrix.api.room.isDm
|
|
||||||
import io.element.android.libraries.matrix.api.room.recent.getRecentRooms
|
|
||||||
import io.element.android.libraries.matrix.api.spaces.SpaceRoomList
|
import io.element.android.libraries.matrix.api.spaces.SpaceRoomList
|
||||||
import io.element.android.libraries.matrix.api.spaces.SpaceService
|
import io.element.android.libraries.matrix.api.spaces.SpaceService
|
||||||
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
|
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
|
||||||
import io.element.android.libraries.matrix.ui.model.toSelectRoomInfo
|
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlinx.collections.immutable.toPersistentList
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import kotlinx.coroutines.flow.take
|
|
||||||
import kotlinx.coroutines.flow.toList
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
private const val MAX_SUGGESTIONS_COUNT = 5
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
class AddRoomToSpacePresenter(
|
class AddRoomToSpacePresenter(
|
||||||
private val spaceRoomList: SpaceRoomList,
|
private val spaceRoomList: SpaceRoomList,
|
||||||
private val dataSource: AddRoomToSpaceSearchDataSource,
|
private val dataSource: AddRoomToSpaceSearchDataSource,
|
||||||
private val spaceService: SpaceService,
|
private val spaceService: SpaceService,
|
||||||
private val matrixClient: MatrixClient,
|
|
||||||
@SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope,
|
@SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope,
|
||||||
) : Presenter<AddRoomToSpaceState> {
|
) : Presenter<AddRoomToSpaceState> {
|
||||||
|
|
||||||
|
|
@ -63,74 +50,56 @@ class AddRoomToSpacePresenter(
|
||||||
var isSearchActive by remember { mutableStateOf(false) }
|
var isSearchActive by remember { mutableStateOf(false) }
|
||||||
val saveAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
val saveAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
||||||
|
|
||||||
// Load data source
|
|
||||||
LaunchedEffect(Unit) { dataSource.load() }
|
|
||||||
|
|
||||||
// Update search query in data source
|
// Update search query in data source
|
||||||
LaunchedEffect(searchQuery) {
|
LaunchedEffect(searchQuery) {
|
||||||
dataSource.setSearchQuery(searchQuery)
|
dataSource.setSearchQuery(searchQuery)
|
||||||
}
|
}
|
||||||
|
LaunchedEffect(isSearchActive) {
|
||||||
// Get rooms already in space
|
dataSource.setIsActive(isSearchActive)
|
||||||
val spaceChildrenIds by remember {
|
|
||||||
spaceRoomList.spaceRoomsFlow.map { spaceChildren ->
|
|
||||||
spaceChildren.map { it.roomId }
|
|
||||||
}
|
|
||||||
}.collectAsState(initial = emptyList())
|
|
||||||
|
|
||||||
// Suggestions from recently visited rooms (excluding DMs, spaces, and rooms already in space)
|
|
||||||
val suggestions by produceState(persistentListOf(), spaceChildrenIds) {
|
|
||||||
value = matrixClient
|
|
||||||
.getRecentRooms { info ->
|
|
||||||
!info.isSpace && !info.isDm && info.currentUserMembership == CurrentUserMembership.JOINED
|
|
||||||
}
|
|
||||||
.take(MAX_SUGGESTIONS_COUNT)
|
|
||||||
.map { info -> info.toSelectRoomInfo() }
|
|
||||||
.toList()
|
|
||||||
.toImmutableList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val allRooms by dataSource.roomInfoList.collectAsState(initial = persistentListOf())
|
val suggestions by dataSource.suggestions.collectAsState(initial = persistentListOf())
|
||||||
|
|
||||||
|
val filteredRooms by dataSource.roomInfoList.collectAsState(initial = persistentListOf())
|
||||||
val searchResults by remember<State<SearchBarResultState<ImmutableList<SelectRoomInfo>>>> {
|
val searchResults by remember<State<SearchBarResultState<ImmutableList<SelectRoomInfo>>>> {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
val filtered = allRooms.filterNot { it.roomId in spaceChildrenIds }
|
|
||||||
when {
|
when {
|
||||||
filtered.isNotEmpty() -> SearchBarResultState.Results(filtered.toImmutableList())
|
filteredRooms.isNotEmpty() -> SearchBarResultState.Results(filteredRooms)
|
||||||
isSearchActive && searchQuery.isNotEmpty() -> SearchBarResultState.NoResultsFound()
|
isSearchActive && searchQuery.isNotEmpty() -> SearchBarResultState.NoResultsFound()
|
||||||
else -> SearchBarResultState.Initial()
|
else -> SearchBarResultState.Initial()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleEvent(event: AddRoomToSpaceEvents) {
|
fun handleEvent(event: AddRoomToSpaceEvent) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is AddRoomToSpaceEvents.ToggleRoom -> {
|
is AddRoomToSpaceEvent.ToggleRoom -> {
|
||||||
selectedRooms = if (selectedRooms.any { it.roomId == event.room.roomId }) {
|
selectedRooms = if (selectedRooms.any { it.roomId == event.room.roomId }) {
|
||||||
selectedRooms.filterNot { it.roomId == event.room.roomId }.toPersistentList()
|
selectedRooms.filterNot { it.roomId == event.room.roomId }.toPersistentList()
|
||||||
} else {
|
} else {
|
||||||
(selectedRooms + event.room).toPersistentList()
|
(selectedRooms + event.room).toPersistentList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is AddRoomToSpaceEvents.UpdateSearchQuery -> {
|
is AddRoomToSpaceEvent.UpdateSearchQuery -> {
|
||||||
searchQuery = event.query
|
searchQuery = event.query
|
||||||
}
|
}
|
||||||
is AddRoomToSpaceEvents.OnSearchActiveChanged -> {
|
is AddRoomToSpaceEvent.OnSearchActiveChanged -> {
|
||||||
isSearchActive = event.active
|
isSearchActive = event.active
|
||||||
if (!event.active) {
|
if (!event.active) {
|
||||||
searchQuery = ""
|
searchQuery = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddRoomToSpaceEvents.CloseSearch -> {
|
AddRoomToSpaceEvent.CloseSearch -> {
|
||||||
isSearchActive = false
|
isSearchActive = false
|
||||||
searchQuery = ""
|
searchQuery = ""
|
||||||
}
|
}
|
||||||
AddRoomToSpaceEvents.Save -> {
|
AddRoomToSpaceEvent.Save -> {
|
||||||
sessionCoroutineScope.addRoomsToSpace(
|
sessionCoroutineScope.addRoomsToSpace(
|
||||||
selectedRooms = selectedRooms,
|
selectedRooms = selectedRooms,
|
||||||
addAction = saveAction,
|
addAction = saveAction,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
AddRoomToSpaceEvents.ClearError -> {
|
AddRoomToSpaceEvent.ResetSaveAction -> {
|
||||||
saveAction.value = AsyncAction.Uninitialized
|
saveAction.value = AsyncAction.Uninitialized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,31 +10,42 @@ package io.element.android.features.space.impl.addroom
|
||||||
|
|
||||||
import dev.zacsweers.metro.Inject
|
import dev.zacsweers.metro.Inject
|
||||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
||||||
|
import io.element.android.libraries.matrix.api.room.RoomInfo
|
||||||
import io.element.android.libraries.matrix.api.room.isDm
|
import io.element.android.libraries.matrix.api.room.isDm
|
||||||
|
import io.element.android.libraries.matrix.api.room.recent.getRecentRooms
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomList
|
import io.element.android.libraries.matrix.api.roomlist.RoomList
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
|
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||||
import io.element.android.libraries.matrix.api.roomlist.loadAllIncrementally
|
import io.element.android.libraries.matrix.api.roomlist.loadAllIncrementally
|
||||||
|
import io.element.android.libraries.matrix.api.spaces.SpaceRoomList
|
||||||
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
|
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
|
||||||
import io.element.android.libraries.matrix.ui.model.toSelectRoomInfo
|
import io.element.android.libraries.matrix.ui.model.toSelectRoomInfo
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.take
|
||||||
|
import kotlinx.coroutines.flow.toList
|
||||||
|
|
||||||
private const val PAGE_SIZE = 30
|
private const val PAGE_SIZE = 30
|
||||||
|
private const val MAX_SUGGESTIONS_COUNT = 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DataSource for rooms that can be added to a space.
|
* DataSource for rooms that can be added to a space.
|
||||||
* Filters out DMs, spaces, and only includes rooms the user has joined.
|
* Filters out DMs, spaces, rooms already in the space, and only includes rooms the user has joined.
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
class AddRoomToSpaceSearchDataSource(
|
class AddRoomToSpaceSearchDataSource(
|
||||||
roomListService: RoomListService,
|
roomListService: RoomListService,
|
||||||
coroutineDispatchers: CoroutineDispatchers,
|
spaceRoomList: SpaceRoomList,
|
||||||
|
private val matrixClient: MatrixClient,
|
||||||
|
private val coroutineDispatchers: CoroutineDispatchers,
|
||||||
) {
|
) {
|
||||||
private val roomList = roomListService.createRoomList(
|
private val roomList = roomListService.createRoomList(
|
||||||
pageSize = PAGE_SIZE,
|
pageSize = PAGE_SIZE,
|
||||||
|
|
@ -42,22 +53,42 @@ class AddRoomToSpaceSearchDataSource(
|
||||||
source = RoomList.Source.All,
|
source = RoomList.Source.All,
|
||||||
)
|
)
|
||||||
|
|
||||||
val roomInfoList: Flow<ImmutableList<SelectRoomInfo>> = roomList.filteredSummaries
|
private val spaceChildrenFlow = spaceRoomList.spaceRoomsFlow.map { spaceChildren ->
|
||||||
.map { roomSummaries ->
|
spaceChildren.map { it.roomId }.toSet()
|
||||||
roomSummaries
|
}
|
||||||
.filter {
|
|
||||||
it.info.currentUserMembership == CurrentUserMembership.JOINED &&
|
|
||||||
!it.info.isDm &&
|
|
||||||
!it.info.isSpace
|
|
||||||
}
|
|
||||||
.distinctBy { it.roomId }
|
|
||||||
.map { roomSummary -> roomSummary.toSelectRoomInfo() }
|
|
||||||
.toImmutableList()
|
|
||||||
}
|
|
||||||
.flowOn(coroutineDispatchers.computation)
|
|
||||||
|
|
||||||
suspend fun load() = coroutineScope {
|
private val filterRoomPredicate: (RoomInfo, Set<RoomId>) -> Boolean = { info, childIds ->
|
||||||
roomList.loadAllIncrementally(this)
|
!info.isSpace &&
|
||||||
|
!info.isDm &&
|
||||||
|
info.currentUserMembership == CurrentUserMembership.JOINED &&
|
||||||
|
info.id !in childIds
|
||||||
|
}
|
||||||
|
|
||||||
|
val roomInfoList: Flow<ImmutableList<SelectRoomInfo>> = combine(
|
||||||
|
roomList.filteredSummaries,
|
||||||
|
spaceChildrenFlow,
|
||||||
|
) { roomSummaries, childIds ->
|
||||||
|
roomSummaries
|
||||||
|
.filter { filterRoomPredicate(it.info, childIds) }
|
||||||
|
.map { it.toSelectRoomInfo() }
|
||||||
|
.toImmutableList()
|
||||||
|
}.flowOn(coroutineDispatchers.computation)
|
||||||
|
|
||||||
|
val suggestions: Flow<ImmutableList<SelectRoomInfo>> = spaceChildrenFlow.map { childIds ->
|
||||||
|
matrixClient
|
||||||
|
.getRecentRooms { filterRoomPredicate(it, childIds) }
|
||||||
|
.take(MAX_SUGGESTIONS_COUNT)
|
||||||
|
.map { it.toSelectRoomInfo() }
|
||||||
|
.toList()
|
||||||
|
.toImmutableList()
|
||||||
|
}.flowOn(coroutineDispatchers.computation)
|
||||||
|
|
||||||
|
suspend fun setIsActive(isActive: Boolean) = coroutineScope {
|
||||||
|
if (isActive) {
|
||||||
|
roomList.loadAllIncrementally(this)
|
||||||
|
} else {
|
||||||
|
roomList.reset()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setSearchQuery(searchQuery: String) {
|
suspend fun setSearchQuery(searchQuery: String) {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ data class AddRoomToSpaceState(
|
||||||
val selectedRooms: ImmutableList<SelectRoomInfo>,
|
val selectedRooms: ImmutableList<SelectRoomInfo>,
|
||||||
val suggestions: ImmutableList<SelectRoomInfo>,
|
val suggestions: ImmutableList<SelectRoomInfo>,
|
||||||
val saveAction: AsyncAction<Unit>,
|
val saveAction: AsyncAction<Unit>,
|
||||||
val eventSink: (AddRoomToSpaceEvents) -> Unit,
|
val eventSink: (AddRoomToSpaceEvent) -> Unit,
|
||||||
) {
|
) {
|
||||||
val canSave: Boolean = selectedRooms.isNotEmpty() && !saveAction.isLoading()
|
val canSave: Boolean = selectedRooms.isNotEmpty() && !saveAction.isLoading()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,10 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.designsystem.components.ProgressDialog
|
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
||||||
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.avatar.AvatarType
|
import io.element.android.libraries.designsystem.components.avatar.AvatarType
|
||||||
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.dialogs.ErrorDialog
|
|
||||||
import io.element.android.libraries.designsystem.components.list.AvatarListItem
|
import io.element.android.libraries.designsystem.components.list.AvatarListItem
|
||||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
|
|
@ -58,12 +57,12 @@ fun AddRoomToSpaceView(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
fun onRoomRemoved(roomInfo: SelectRoomInfo) {
|
fun onRoomRemoved(roomInfo: SelectRoomInfo) {
|
||||||
state.eventSink(AddRoomToSpaceEvents.ToggleRoom(roomInfo))
|
state.eventSink(AddRoomToSpaceEvent.ToggleRoom(roomInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onBack() {
|
fun onBack() {
|
||||||
if (state.isSearchActive) {
|
if (state.isSearchActive) {
|
||||||
state.eventSink(AddRoomToSpaceEvents.CloseSearch)
|
state.eventSink(AddRoomToSpaceEvent.CloseSearch)
|
||||||
} else {
|
} else {
|
||||||
onBackClick()
|
onBackClick()
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +89,7 @@ fun AddRoomToSpaceView(
|
||||||
TextButton(
|
TextButton(
|
||||||
text = stringResource(CommonStrings.action_save),
|
text = stringResource(CommonStrings.action_save),
|
||||||
enabled = state.canSave,
|
enabled = state.canSave,
|
||||||
onClick = { state.eventSink(AddRoomToSpaceEvents.Save) }
|
onClick = { state.eventSink(AddRoomToSpaceEvent.Save) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -105,9 +104,9 @@ fun AddRoomToSpaceView(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
placeHolderTitle = stringResource(CommonStrings.action_search),
|
placeHolderTitle = stringResource(CommonStrings.action_search),
|
||||||
query = state.searchQuery,
|
query = state.searchQuery,
|
||||||
onQueryChange = { state.eventSink(AddRoomToSpaceEvents.UpdateSearchQuery(it)) },
|
onQueryChange = { state.eventSink(AddRoomToSpaceEvent.UpdateSearchQuery(it)) },
|
||||||
active = state.isSearchActive,
|
active = state.isSearchActive,
|
||||||
onActiveChange = { state.eventSink(AddRoomToSpaceEvents.OnSearchActiveChanged(it)) },
|
onActiveChange = { state.eventSink(AddRoomToSpaceEvent.OnSearchActiveChanged(it)) },
|
||||||
resultState = state.searchResults,
|
resultState = state.searchResults,
|
||||||
showBackButton = false,
|
showBackButton = false,
|
||||||
contentPrefix = {
|
contentPrefix = {
|
||||||
|
|
@ -125,7 +124,7 @@ fun AddRoomToSpaceView(
|
||||||
RoomListItem(
|
RoomListItem(
|
||||||
roomInfo = roomInfo,
|
roomInfo = roomInfo,
|
||||||
isSelected = state.selectedRooms.any { it.roomId == roomInfo.roomId },
|
isSelected = state.selectedRooms.any { it.roomId == roomInfo.roomId },
|
||||||
onToggle = { state.eventSink(AddRoomToSpaceEvents.ToggleRoom(it)) }
|
onToggle = { state.eventSink(AddRoomToSpaceEvent.ToggleRoom(it)) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +153,7 @@ fun AddRoomToSpaceView(
|
||||||
RoomListItem(
|
RoomListItem(
|
||||||
roomInfo = roomInfo,
|
roomInfo = roomInfo,
|
||||||
isSelected = state.selectedRooms.any { it.roomId == roomInfo.roomId },
|
isSelected = state.selectedRooms.any { it.roomId == roomInfo.roomId },
|
||||||
onToggle = { state.eventSink(AddRoomToSpaceEvents.ToggleRoom(it)) }
|
onToggle = { state.eventSink(AddRoomToSpaceEvent.ToggleRoom(it)) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -162,19 +161,31 @@ fun AddRoomToSpaceView(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SaveActionView(
|
||||||
|
saveAction = state.saveAction,
|
||||||
|
onRetry = { state.eventSink(AddRoomToSpaceEvent.Save)},
|
||||||
|
onDismiss = {state.eventSink(AddRoomToSpaceEvent.ResetSaveAction)}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Loading dialog
|
@Composable
|
||||||
if (state.saveAction.isLoading()) {
|
private fun SaveActionView(
|
||||||
ProgressDialog()
|
saveAction: AsyncAction<Unit>,
|
||||||
}
|
onRetry: () -> Unit,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
// Error dialog
|
) {
|
||||||
if (state.saveAction.isFailure()) {
|
AsyncActionView(
|
||||||
ErrorDialog(
|
async = saveAction,
|
||||||
content = stringResource(CommonStrings.error_unknown),
|
onRetry = onRetry,
|
||||||
onSubmit = { state.eventSink(AddRoomToSpaceEvents.ClearError) },
|
errorTitle = {
|
||||||
)
|
stringResource(CommonStrings.common_something_went_wrong)
|
||||||
}
|
},
|
||||||
|
errorMessage = {
|
||||||
|
stringResource(CommonStrings.error_network_or_server_issue)
|
||||||
|
},
|
||||||
|
onSuccess = { onDismiss() },
|
||||||
|
onErrorDismiss = onDismiss,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue