diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt index ebe96b6382..133c309ad9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/Room.kt @@ -101,4 +101,8 @@ interface Room : * Use this room as a Space, if the type is correct. */ fun asSpace(): Space? + + suspend fun setJoinRulePublic() + suspend fun setJoinRuleInviteOnly() + suspend fun setJoinRuleRestricted(allowList: List) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt index e614ea91d6..d44753770e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt @@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.Optional @@ -53,7 +54,7 @@ interface StateService { /** * Update the join rule and/or the guest access */ - suspend fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?) + suspend fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?, allowList: List? = null) /** * Update the avatar of the room diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt index 82565d8118..21f55bbc42 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/permalinks/ViaParameterFinder.kt @@ -17,17 +17,24 @@ package org.matrix.android.sdk.internal.session.permalinks import org.matrix.android.sdk.api.MatrixPatterns.getDomain +import org.matrix.android.sdk.api.query.QueryStringValue +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams import org.matrix.android.sdk.api.session.room.model.Membership +import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent +import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.session.room.RoomGetter +import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource import java.net.URLEncoder import javax.inject.Inject import javax.inject.Provider internal class ViaParameterFinder @Inject constructor( @UserId private val userId: String, - private val roomGetterProvider: Provider + private val roomGetterProvider: Provider, + private val stateEventDataSource: StateEventDataSource ) { fun computeViaParams(roomId: String, max: Int): List { @@ -70,4 +77,28 @@ internal class ViaParameterFinder @Inject constructor( .orEmpty() .toSet() } + + fun computeViaParamsForRestricted(roomId: String, max: Int): List { + val userThatCanInvite = roomGetterProvider.get().getRoom(roomId) + ?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) }) + ?.map { it.userId } + ?.filter { userCanInvite(userId, roomId) } + .orEmpty() + .toSet() + + return userThatCanInvite.map { it.getDomain() } + .groupBy { it } + .mapValues { it.value.size } + .toMutableMap() + .let { map -> map.keys.sortedByDescending { map[it] } } + .take(max) + } + + fun userCanInvite(userId: String, roomId: String): Boolean { + val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) + ?.content?.toModel() + ?.let { PowerLevelsHelper(it) } + + return powerLevelsHelper?.isUserAbleToInvite(userId) ?: false + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt index 8afd690f64..ecdfe5e235 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt @@ -24,6 +24,8 @@ import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataServic import org.matrix.android.sdk.api.session.room.alias.AliasService import org.matrix.android.sdk.api.session.room.call.RoomCallService import org.matrix.android.sdk.api.session.room.members.MembershipService +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomType import org.matrix.android.sdk.api.session.room.model.relation.RelationService @@ -164,4 +166,20 @@ internal class DefaultRoom(override val roomId: String, if (roomSummary()?.roomType != RoomType.SPACE) return null return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder) } + + override suspend fun setJoinRulePublic() { + stateService.updateJoinRule(RoomJoinRules.PUBLIC, null) + } + + override suspend fun setJoinRuleInviteOnly() { + stateService.updateJoinRule(RoomJoinRules.INVITE, null) + } + + override suspend fun setJoinRuleRestricted(allowList: List) { + // we need to compute correct via parameters and check if PL are correct + val allowEntries = allowList.map { spaceId -> + RoomJoinRulesAllowEntry(spaceId, viaParameterFinder.computeViaParamsForRestricted(spaceId, 3)) + } + stateService.updateJoinRule(RoomJoinRules.RESTRICTED, null, allowEntries) + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt index ff2afb5d61..2f5ba6997e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt @@ -19,8 +19,8 @@ package org.matrix.android.sdk.internal.session.room.state import android.net.Uri import androidx.lifecycle.LiveData import dagger.assisted.Assisted -import dagger.assisted.AssistedInject import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType @@ -29,12 +29,13 @@ import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry +import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent import org.matrix.android.sdk.api.session.room.state.StateService import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.MimeTypes import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.internal.session.content.FileUploader -import java.lang.UnsupportedOperationException internal class DefaultStateService @AssistedInject constructor(@Assisted private val roomId: String, private val stateEventDataSource: StateEventDataSource, @@ -126,12 +127,19 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private ) } - override suspend fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?) { + override suspend fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?, allowList: List?) { if (joinRules != null) { - if (joinRules == RoomJoinRules.RESTRICTED) throw UnsupportedOperationException("No yet supported") + val body = if (joinRules == RoomJoinRules.RESTRICTED) { + RoomJoinRulesContent( + _joinRules = RoomJoinRules.RESTRICTED.value, + allowList = allowList + ).toContent() + } else { + mapOf("join_rule" to joinRules) + } sendStateEvent( eventType = EventType.STATE_ROOM_JOIN_RULES, - body = mapOf("join_rule" to joinRules), + body = body, stateKey = null ) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleActivity.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleActivity.kt index 6fb7381349..ac73a8efda 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleActivity.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleActivity.kt @@ -18,11 +18,20 @@ package im.vector.app.features.roomprofile.settings.joinrule import android.content.Context import android.content.Intent +import android.os.Bundle +import androidx.core.view.isVisible +import com.airbnb.mvrx.Fail +import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRx +import com.airbnb.mvrx.Success +import com.airbnb.mvrx.Uninitialized +import com.airbnb.mvrx.viewModel import im.vector.app.R import im.vector.app.core.di.ScreenComponent +import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.extensions.addFragment import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.core.utils.toast import im.vector.app.databinding.ActivitySimpleBinding import im.vector.app.features.roomprofile.RoomProfileArgs import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedState @@ -39,6 +48,11 @@ class RoomJoinRuleActivity : VectorBaseActivity(), @Inject lateinit var allowListViewModelFactory: RoomJoinRuleChooseRestrictedViewModel.Factory + @Inject + lateinit var errorFormatter: ErrorFormatter + + val viewModel: RoomJoinRuleChooseRestrictedViewModel by viewModel() + override fun create(initialState: RoomJoinRuleChooseRestrictedState) = allowListViewModelFactory.create(initialState) override fun injectWith(injector: ScreenComponent) { @@ -56,6 +70,27 @@ class RoomJoinRuleActivity : VectorBaseActivity(), } } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + viewModel.selectSubscribe(this, RoomJoinRuleChooseRestrictedState::updatingStatus) { + when (it) { + Uninitialized -> { + // nop + } + is Loading -> { + views.simpleActivityWaitingView.isVisible = true + } + is Success -> { + finish() + } + is Fail -> { + views.simpleActivityWaitingView.isVisible = false + toast(errorFormatter.toHumanReadable(it.error)) + } + } + } + } + companion object { fun newIntent(context: Context, roomId: String): Intent { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt index 7962023dd5..7adfc594b7 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleAdvancedController.kt @@ -26,6 +26,7 @@ import im.vector.app.core.ui.list.genericFooterItem import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedState import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import timber.log.Timber import javax.inject.Inject class RoomJoinRuleAdvancedController @Inject constructor( @@ -76,12 +77,13 @@ class RoomJoinRuleAdvancedController @Inject constructor( if (choices.firstOrNull { it.rule == RoomJoinRules.RESTRICTED } != null) { val restrictedRule = choices.first { it.rule == RoomJoinRules.RESTRICTED } + Timber.w("##@@ ${state.updatedAllowList}") spaceJoinRuleItem { id("restricted") avatarRenderer(host.avatarRenderer) needUpgrade(restrictedRule.needUpgrade) selected(state.currentRoomJoinRules == RoomJoinRules.RESTRICTED) - restrictedList(state.updatedAllowList.orEmpty()) + restrictedList(state.updatedAllowList) listener { host.interactionListener?.didSelectRule(RoomJoinRules.RESTRICTED) } } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt index 3e00c3f564..41c15ad4b9 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/RoomJoinRuleFragment.kt @@ -21,8 +21,10 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible +import com.airbnb.mvrx.Loading import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.withState +import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.commitTransaction @@ -48,10 +50,20 @@ class RoomJoinRuleFragment @Inject constructor( FragmentJoinRulesRecyclerBinding.inflate(inflater, container, false) override fun onBackPressed(toolbarButton: Boolean): Boolean { - // TODO val hasUnsavedChanges = withState(viewModel) { it.hasUnsavedChanges } - if (!hasUnsavedChanges) { + val isLoading = withState(viewModel) { it.updatingStatus is Loading } + if (!hasUnsavedChanges || isLoading) { requireActivity().finish() + } else { + MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.dialog_title_warning) + .setMessage(R.string.warning_unsaved_change) + .setPositiveButton(R.string.warning_unsaved_change_discard) { _, _ -> + requireActivity().finish() + } + .setNegativeButton(R.string.cancel, null) + .show() + return true } return true } @@ -65,6 +77,9 @@ class RoomJoinRuleFragment @Inject constructor( views.positiveButton.text = getString(R.string.warning_unsaved_change_discard) views.positiveButton.isVisible = true views.positiveButton.text = getString(R.string.save) + views.positiveButton.debouncedClicks { + viewModel.handle(RoomJoinRuleChooseRestrictedActions.DoUpdateJoinRules) + } } else { views.cancelButton.isVisible = false views.positiveButton.isVisible = true @@ -86,6 +101,9 @@ class RoomJoinRuleFragment @Inject constructor( } override fun didSelectRule(rules: RoomJoinRules) { + val isLoading = withState(viewModel) { it.updatingStatus is Loading } + if (isLoading) return + val oldRule = withState(viewModel) { it.currentRoomJoinRules } viewModel.handle(RoomJoinRuleChooseRestrictedActions.SelectJoinRules(rules)) if (rules == RoomJoinRules.RESTRICTED && oldRule == RoomJoinRules.RESTRICTED) { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt index 261796c612..4f3f1e3a5b 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/SpaceJoinRuleItem.kt @@ -74,6 +74,7 @@ abstract class SpaceJoinRuleItem : VectorEpoxyModel() holder.listTitle.isVisible = true restrictedList.forEachIndexed { index, matrixItem -> if (index < items.size) { + items[index].isVisible = true avatarRenderer.render(matrixItem, items[index]) } else if (index == items.size) { holder.spaceMore.isVisible = true diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChangeJoinRuleViewModelTask.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChangeJoinRuleViewModelTask.kt new file mode 100644 index 0000000000..36dd3ed0d3 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/ChangeJoinRuleViewModelTask.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 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 im.vector.app.features.roomprofile.settings.joinrule.advanced + +import im.vector.app.core.platform.ViewModelTask +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.room.model.RoomJoinRules +import javax.inject.Inject + +sealed class ChangeJoinRuleTaskResult { + + object Success : ChangeJoinRuleTaskResult() + + data class Failure(val error: Throwable) : ChangeJoinRuleTaskResult() +} + +data class ChangeJoinRuleParams( + val roomId: String, + val newJoinRule: RoomJoinRules, + val newAllowIfRestricted: List? = null +) + +class ChangeJoinRuleViewModelTask @Inject constructor( + private val session: Session +) : ViewModelTask { + + override suspend fun execute(params: ChangeJoinRuleParams): ChangeJoinRuleTaskResult { + val room = session.getRoom(params.roomId) ?: return ChangeJoinRuleTaskResult.Failure(IllegalArgumentException("Unknown room")) + + try { + when (params.newJoinRule) { + RoomJoinRules.PUBLIC, + RoomJoinRules.INVITE -> { + room.updateJoinRule(params.newJoinRule, null) + } + RoomJoinRules.RESTRICTED -> updateRestrictedJoinRule(params.roomId, params.newAllowIfRestricted.orEmpty()) + RoomJoinRules.KNOCK, + RoomJoinRules.PRIVATE -> { + return ChangeJoinRuleTaskResult.Failure(UnsupportedOperationException()) + } + } + } catch (failure: Throwable) { + return ChangeJoinRuleTaskResult.Failure(failure) + } + + return ChangeJoinRuleTaskResult.Success + } + + fun updateRestrictedJoinRule(roomId: String, allowList: List) { + // let's compute correct via list + allowList.map { + session.getRoomSummary(it) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedActions.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedActions.kt index 909be4654d..dd445ee484 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedActions.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedActions.kt @@ -24,4 +24,5 @@ sealed class RoomJoinRuleChooseRestrictedActions : VectorViewModelAction { data class FilterWith(val filter: String) : RoomJoinRuleChooseRestrictedActions() data class ToggleSelection(val matrixItem: MatrixItem) : RoomJoinRuleChooseRestrictedActions() data class SelectJoinRules(val rules: RoomJoinRules) : RoomJoinRuleChooseRestrictedActions() + object DoUpdateJoinRules : RoomJoinRuleChooseRestrictedActions() } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedState.kt index 0d0b8eeef7..cc7b8a5a7e 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedState.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedState.kt @@ -39,7 +39,8 @@ data class RoomJoinRuleChooseRestrictedState( val unknownRestricted: List = emptyList(), val filter: String = "", val filteredResults: Async> = Uninitialized, - val hasUnsavedChanges: Boolean = false + val hasUnsavedChanges: Boolean = false, + val updatingStatus: Async = Uninitialized ) : MvRxState { constructor(args: RoomProfileArgs) : this(roomId = args.roomId) } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt index c82bc75fba..6dd9bbdec1 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/joinrule/advanced/RoomJoinRuleChooseRestrictedViewModel.kt @@ -18,6 +18,7 @@ package im.vector.app.features.roomprofile.settings.joinrule.advanced import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.ActivityViewModelContext +import com.airbnb.mvrx.Fail import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MvRxViewModelFactory @@ -61,10 +62,6 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor( ?.toModel() val initialAllowList = joinRulesContent?.allowList -// val others = session.spaceService().getSpaceSummaries(spaceSummaryQueryParams { -// memberships = listOf(Membership.JOIN) -// }).map { it.toMatrixItem() } - val knownParentSpacesAllowed = mutableListOf() val unknownAllowedOrRooms = mutableListOf() initialAllowList.orEmpty().forEach { entry -> @@ -130,7 +127,6 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor( updatedAllowList = initialAllowList.orEmpty().map { session.getRoomSummary(it.spaceID)?.toMatrixItem() ?: MatrixItem.RoomItem(it.spaceID, null, null) }, -// selectedRoomList = initialAllowList.orEmpty().map { it.spaceID }, possibleSpaceCandidate = possibleSpaceCandidate, unknownRestricted = unknownAllowedOrRooms ) @@ -170,11 +166,50 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor( is RoomJoinRuleChooseRestrictedActions.FilterWith -> handleFilter(action) is RoomJoinRuleChooseRestrictedActions.ToggleSelection -> handleToggleSelection(action) is RoomJoinRuleChooseRestrictedActions.SelectJoinRules -> handleSelectRule(action) + RoomJoinRuleChooseRestrictedActions.DoUpdateJoinRules -> handleSubmit() }.exhaustive checkForChanges() } + fun handleSubmit() = withState { state -> + setState { copy(updatingStatus = Loading()) } + viewModelScope.launch { + try { + when (state.currentRoomJoinRules) { + RoomJoinRules.PUBLIC -> room.setJoinRulePublic() + RoomJoinRules.INVITE -> room.setJoinRuleInviteOnly() + RoomJoinRules.RESTRICTED -> room.setJoinRuleRestricted(state.updatedAllowList.map { it.id }) + RoomJoinRules.KNOCK, + RoomJoinRules.PRIVATE, + null -> { + throw UnsupportedOperationException() + } + } + setState { copy(updatingStatus = Success(Unit)) } + } catch (failure: Throwable) { + setState { copy(updatingStatus = Fail(failure)) } + } + } + } + fun handleSelectRule(action: RoomJoinRuleChooseRestrictedActions.SelectJoinRules) = withState { state -> + if (action.rules == RoomJoinRules.RESTRICTED && state.currentRoomJoinRules != RoomJoinRules.RESTRICTED) { + // switching to restricted + // if allow list is empty, then default to current space parents + if (state.updatedAllowList.isEmpty()) { + val candidates = session.getRoomSummary(initialState.roomId) + ?.flattenParentIds + ?.filter { + session.getRoomSummary(it)?.spaceChildren?.firstOrNull { it.childRoomId == initialState.roomId } != null + }?.mapNotNull { + session.getRoomSummary(it)?.toMatrixItem() + }.orEmpty() + setState { + copy(updatedAllowList = candidates) + } + } + } + setState { copy( currentRoomJoinRules = action.rules