This commit is contained in:
Valere 2021-07-09 14:24:13 +02:00
parent 6c2a917d9f
commit 3da20aea29
9 changed files with 114 additions and 272 deletions

View file

@ -27,6 +27,7 @@ import im.vector.app.databinding.ActivitySimpleBinding
import im.vector.app.features.roomprofile.RoomProfileArgs import im.vector.app.features.roomprofile.RoomProfileArgs
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedState import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedState
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel
import javax.inject.Inject
class RoomJoinRuleActivity : VectorBaseActivity<ActivitySimpleBinding>(), class RoomJoinRuleActivity : VectorBaseActivity<ActivitySimpleBinding>(),
RoomJoinRuleChooseRestrictedViewModel.Factory { RoomJoinRuleChooseRestrictedViewModel.Factory {
@ -35,13 +36,15 @@ class RoomJoinRuleActivity : VectorBaseActivity<ActivitySimpleBinding>(),
private lateinit var roomProfileArgs: RoomProfileArgs private lateinit var roomProfileArgs: RoomProfileArgs
private lateinit var allowListViewModelFactory: RoomJoinRuleChooseRestrictedViewModel.Factory @Inject
lateinit var allowListViewModelFactory: RoomJoinRuleChooseRestrictedViewModel.Factory
override fun create(initialState: RoomJoinRuleChooseRestrictedState) = allowListViewModelFactory.create(initialState) override fun create(initialState: RoomJoinRuleChooseRestrictedState) = allowListViewModelFactory.create(initialState)
override fun injectWith(injector: ScreenComponent) { override fun injectWith(injector: ScreenComponent) {
injector.inject(this) injector.inject(this)
} }
override fun initUiAndData() { override fun initUiAndData() {
roomProfileArgs = intent?.extras?.getParcelable(MvRx.KEY_ARG) ?: return roomProfileArgs = intent?.extras?.getParcelable(MvRx.KEY_ARG) ?: return
if (isFirstCreation()) { if (isFirstCreation()) {
@ -52,10 +55,6 @@ class RoomJoinRuleActivity : VectorBaseActivity<ActivitySimpleBinding>(),
) )
} }
} }
//
// override fun onBackPressed() {
// super.onBackPressed()
// }
companion object { companion object {

View file

@ -1,191 +0,0 @@
/*
* 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
import com.airbnb.mvrx.ActivityViewModelContext
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.ViewModelContext
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.platform.VectorViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.VectorViewModelAction
import im.vector.app.features.roomprofile.RoomProfileArgs
import im.vector.app.features.settings.VectorPreferences
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
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.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.util.MatrixItem
import org.matrix.android.sdk.api.util.toMatrixItem
import org.matrix.android.sdk.rx.mapOptional
import org.matrix.android.sdk.rx.rx
import org.matrix.android.sdk.rx.unwrap
data class RoomJoinRuleAdvancedState(
val roomId: String,
val summary: RoomSummary? = null,
val currentRoomJoinRules: RoomJoinRules? = null,
val initialAllowList: List<MatrixItem>? = null,
val updatedAllowList: List<MatrixItem>? = null,
val choices: Async<List<JoinRulesOptionSupport>> = Uninitialized
) : MvRxState {
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
}
sealed class RoomJoinRuleAdvancedAction : VectorViewModelAction {
data class SelectJoinRules(val rules: RoomJoinRules) : RoomJoinRuleAdvancedAction()
data class UpdateAllowList(val roomIds: List<String>) : RoomJoinRuleAdvancedAction()
}
sealed class RoomJoinRuleAdvancedEvents : VectorViewEvents {
object SelectAllowList : RoomJoinRuleAdvancedEvents()
}
class RoomJoinRuleAdvancedViewModel @AssistedInject constructor(
@Assisted val initialState: RoomJoinRuleAdvancedState,
private val session: Session,
private val vectorPreferences: VectorPreferences
) : VectorViewModel<RoomJoinRuleAdvancedState, RoomJoinRuleAdvancedAction, RoomJoinRuleAdvancedEvents>(initialState) {
private val room = session.getRoom(initialState.roomId)!!
private val homeServerCapabilities = session.getHomeServerCapabilities()
@AssistedFactory
interface Factory {
fun create(initialState: RoomJoinRuleAdvancedState): RoomJoinRuleAdvancedViewModel
}
companion object : MvRxViewModelFactory<RoomJoinRuleAdvancedViewModel, RoomJoinRuleAdvancedState> {
override fun create(viewModelContext: ViewModelContext, state: RoomJoinRuleAdvancedState): RoomJoinRuleAdvancedViewModel? {
val factory = when (viewModelContext) {
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
is ActivityViewModelContext -> viewModelContext.activity as? Factory
}
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
}
}
init {
val initialAllowList = session.getRoom(initialState.roomId)?.getStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.NoCondition)
?.content
?.toModel<RoomJoinRulesContent>()
?.allowList
setState {
val initialAllowItems = initialAllowList.orEmpty().map {
session.getRoomSummary(it.spaceID)?.toMatrixItem()
?: MatrixItem.RoomItem(it.spaceID, null, null)
}
copy(
summary = session.getRoomSummary(initialState.roomId),
initialAllowList = initialAllowItems,
updatedAllowList = initialAllowItems
)
}
// TODO shouldn't be live
room.rx()
.liveStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.NoCondition)
.mapOptional { it.content.toModel<RoomJoinRulesContent>() }
.unwrap()
.subscribe { content ->
content.joinRules?.let {
var safeRule: RoomJoinRules = it
// server is not really checking that, just to be sure let's check
val restrictedSupportedByThisVersion = homeServerCapabilities
.isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED, room.getRoomVersion())
if (it == RoomJoinRules.RESTRICTED
&& !restrictedSupportedByThisVersion) {
safeRule = RoomJoinRules.INVITE
}
val allowList = if (safeRule == RoomJoinRules.RESTRICTED) content.allowList else null
val restrictedSupport = homeServerCapabilities.isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED)
val couldUpgradeToRestricted = when (restrictedSupport) {
HomeServerCapabilities.RoomCapabilitySupport.SUPPORTED -> true
HomeServerCapabilities.RoomCapabilitySupport.SUPPORTED_UNSTABLE -> vectorPreferences.labsUseExperimentalRestricted()
else -> false
}
val choices = if (restrictedSupportedByThisVersion || couldUpgradeToRestricted) {
listOf(
RoomJoinRules.INVITE.toOption(false),
RoomJoinRules.RESTRICTED.toOption(!restrictedSupportedByThisVersion),
RoomJoinRules.PUBLIC.toOption(false)
)
} else {
listOf(
RoomJoinRules.INVITE.toOption(false),
RoomJoinRules.PUBLIC.toOption(false)
)
}
setState {
copy(
currentRoomJoinRules = safeRule,
choices = Success(choices)
)
}
}
}
.disposeOnClear()
}
override fun handle(action: RoomJoinRuleAdvancedAction) {
when (action) {
is RoomJoinRuleAdvancedAction.SelectJoinRules -> handleSelectRule(action)
is RoomJoinRuleAdvancedAction.UpdateAllowList -> handleUpdateAllowList(action)
}
}
fun handleUpdateAllowList(action: RoomJoinRuleAdvancedAction.UpdateAllowList) = withState { state ->
setState {
copy(
updatedAllowList = action.roomIds.map {
session.getRoomSummary(it)?.toMatrixItem() ?: MatrixItem.RoomItem(it, null, null)
}
)
}
}
fun handleSelectRule(action: RoomJoinRuleAdvancedAction.SelectJoinRules) = withState { state ->
if (action.rules == RoomJoinRules.RESTRICTED) {
// open space select?
_viewEvents.post(RoomJoinRuleAdvancedEvents.SelectAllowList)
}
setState {
copy(
currentRoomJoinRules = action.rules
)
}
}
}

View file

@ -20,25 +20,26 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isVisible
import com.airbnb.mvrx.activityViewModel import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.commitTransaction import im.vector.app.core.extensions.commitTransaction
import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.configureWith
import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentJoinRulesRecyclerBinding import im.vector.app.databinding.FragmentJoinRulesRecyclerBinding
import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedActions
import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
import javax.inject.Inject import javax.inject.Inject
class RoomJoinRuleFragment @Inject constructor( class RoomJoinRuleFragment @Inject constructor(
val controller: RoomJoinRuleAdvancedController, val controller: RoomJoinRuleAdvancedController,
// val viewModelFactory: RoomJoinRuleAdvancedViewModel.Factory,
val avatarRenderer: AvatarRenderer val avatarRenderer: AvatarRenderer
) : VectorBaseFragment<FragmentJoinRulesRecyclerBinding>(), ) : VectorBaseFragment<FragmentJoinRulesRecyclerBinding>(),
// RoomJoinRuleAdvancedViewModel.Factory,
OnBackPressed, RoomJoinRuleAdvancedController.InteractionListener { OnBackPressed, RoomJoinRuleAdvancedController.InteractionListener {
private val viewModel: RoomJoinRuleChooseRestrictedViewModel by activityViewModel() private val viewModel: RoomJoinRuleChooseRestrictedViewModel by activityViewModel()
@ -48,54 +49,55 @@ class RoomJoinRuleFragment @Inject constructor(
override fun onBackPressed(toolbarButton: Boolean): Boolean { override fun onBackPressed(toolbarButton: Boolean): Boolean {
// TODO // TODO
requireActivity().finish() val hasUnsavedChanges = withState(viewModel) { it.hasUnsavedChanges }
if (!hasUnsavedChanges) {
requireActivity().finish()
}
return true return true
} }
override fun invalidate() = withState(viewModel) { state -> override fun invalidate() = withState(viewModel) { state ->
super.invalidate() super.invalidate()
controller.setData(state) controller.setData(state)
if (state.hasUnsavedChanges) {
// show discard and save
views.cancelButton.isVisible = true
views.positiveButton.text = getString(R.string.warning_unsaved_change_discard)
views.positiveButton.isVisible = true
views.positiveButton.text = getString(R.string.save)
} else {
views.cancelButton.isVisible = false
views.positiveButton.isVisible = true
views.positiveButton.text = getString(R.string.ok)
views.positiveButton.debouncedClicks { requireActivity().finish() }
}
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
// roomProfileSharedActionViewModel = activityViewModelProvider.get(RoomProfileSharedActionViewModel::class.java)
// setupRoomHistoryVisibilitySharedActionViewModel()
// setupRoomJoinRuleSharedActionViewModel()
// controller.callback = this
views.genericRecyclerView.configureWith(controller, hasFixedSize = true) views.genericRecyclerView.configureWith(controller, hasFixedSize = true)
controller.interactionListener = this controller.interactionListener = this
// views.waitingView.waitingStatusText.setText(R.string.please_wait) views.cancelButton.debouncedClicks { requireActivity().finish() }
// views.waitingView.waitingStatusText.isVisible = true }
// // Use the Kotlin extension in the fragment-ktx artifact override fun onDestroyView() {
// setFragmentResultListener("SelectAllowList") { requestKey, bundle -> views.genericRecyclerView.cleanup()
// // We use a String here, but any type that can be put in a Bundle is supported super.onDestroyView()
// bundle.getStringArrayList("bundleKey")?.toList()?.let { }
// viewModel.handle(RoomJoinRuleAdvancedAction.UpdateAllowList(it))
// }
// }
viewModel.observeViewEvents { override fun didSelectRule(rules: RoomJoinRules) {
when (it) { val oldRule = withState(viewModel) { it.currentRoomJoinRules }
RoomJoinRuleAdvancedEvents.SelectAllowList -> { viewModel.handle(RoomJoinRuleChooseRestrictedActions.SelectJoinRules(rules))
parentFragmentManager.commitTransaction { if (rules == RoomJoinRules.RESTRICTED && oldRule == RoomJoinRules.RESTRICTED) {
setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.fade_in, R.anim.fade_out) parentFragmentManager.commitTransaction {
val tag = RoomJoinRuleChooseRestrictedFragment::class.simpleName setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.fade_in, R.anim.fade_out)
replace(R.id.simpleFragmentContainer, val tag = RoomJoinRuleChooseRestrictedFragment::class.simpleName
RoomJoinRuleChooseRestrictedFragment::class.java, replace(R.id.simpleFragmentContainer,
this@RoomJoinRuleFragment.arguments, RoomJoinRuleChooseRestrictedFragment::class.java,
tag this@RoomJoinRuleFragment.arguments,
).addToBackStack(tag) tag
} ).addToBackStack(tag)
}
} }
} }
} }
override fun create(initialState: RoomJoinRuleAdvancedState) = viewModelFactory.create(initialState)
override fun didSelectRule(rules: RoomJoinRules) {
viewModel.handle(RoomJoinRuleAdvancedAction.SelectJoinRules(rules))
}
} }

View file

@ -53,14 +53,17 @@ class ChooseRestrictedController @Inject constructor(
is Loading -> loadingItem { id("filter_load") } is Loading -> loadingItem { id("filter_load") }
is Success -> { is Success -> {
if (results.invoke().isEmpty()) { if (results.invoke().isEmpty()) {
noResultItem { id("empty") } noResultItem {
id("empty")
text(host.stringProvider.getString(R.string.no_result_placeholder))
}
} else { } else {
results.invoke().forEach { matrixItem -> results.invoke().forEach { matrixItem ->
roomSelectionItem { roomSelectionItem {
id(matrixItem.id) id(matrixItem.id)
matrixItem(matrixItem) matrixItem(matrixItem)
avatarRenderer(host.avatarRenderer) avatarRenderer(host.avatarRenderer)
selected(data.selectedRoomList.firstOrNull { it == matrixItem.id } != null) selected(data.updatedAllowList.firstOrNull { it.id == matrixItem.id } != null)
itemClickListener { host.listener?.onItemSelected(matrixItem) } itemClickListener { host.listener?.onItemSelected(matrixItem) }
} }
} }
@ -77,18 +80,12 @@ class ChooseRestrictedController @Inject constructor(
centered(false) centered(false)
} }
// val testList = mutableListOf<MatrixItem>()
// for(i in 0..20) {
// testList.addAll(data.knownSpaceParents)
// }
// testList
data.possibleSpaceCandidate.forEach { matrixItem -> data.possibleSpaceCandidate.forEach { matrixItem ->
roomSelectionItem { roomSelectionItem {
id(matrixItem.id) id(matrixItem.id)
matrixItem(matrixItem) matrixItem(matrixItem)
avatarRenderer(host.avatarRenderer) avatarRenderer(host.avatarRenderer)
selected(data.selectedRoomList.firstOrNull { it == matrixItem.id } != null) selected(data.updatedAllowList.firstOrNull { it.id == matrixItem.id } != null)
itemClickListener { host.listener?.onItemSelected(matrixItem) } itemClickListener { host.listener?.onItemSelected(matrixItem) }
} }
} }
@ -105,7 +102,7 @@ class ChooseRestrictedController @Inject constructor(
id(matrixItem.id) id(matrixItem.id)
matrixItem(matrixItem) matrixItem(matrixItem)
avatarRenderer(host.avatarRenderer) avatarRenderer(host.avatarRenderer)
selected(data.selectedRoomList.firstOrNull { it == matrixItem.id } != null) selected(data.updatedAllowList.firstOrNull { it.id == matrixItem.id } != null)
itemClickListener { host.listener?.onItemSelected(matrixItem) } itemClickListener { host.listener?.onItemSelected(matrixItem) }
} }
} }

View file

@ -17,9 +17,11 @@
package im.vector.app.features.roomprofile.settings.joinrule.advanced package im.vector.app.features.roomprofile.settings.joinrule.advanced
import im.vector.app.core.platform.VectorViewModelAction import im.vector.app.core.platform.VectorViewModelAction
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.MatrixItem
sealed class RoomJoinRuleChooseRestrictedActions : VectorViewModelAction { sealed class RoomJoinRuleChooseRestrictedActions : VectorViewModelAction {
data class FilterWith(val filter: String): RoomJoinRuleChooseRestrictedActions() data class FilterWith(val filter: String) : RoomJoinRuleChooseRestrictedActions()
data class ToggleSelection(val matrixItem: MatrixItem): RoomJoinRuleChooseRestrictedActions() data class ToggleSelection(val matrixItem: MatrixItem) : RoomJoinRuleChooseRestrictedActions()
data class SelectJoinRules(val rules: RoomJoinRules) : RoomJoinRuleChooseRestrictedActions()
} }

View file

@ -39,15 +39,11 @@ import javax.inject.Inject
class RoomJoinRuleChooseRestrictedFragment @Inject constructor( class RoomJoinRuleChooseRestrictedFragment @Inject constructor(
val controller: ChooseRestrictedController, val controller: ChooseRestrictedController,
// val viewModelFactory: RoomJoinRuleChooseRestrictedViewModel.Factory,
val avatarRenderer: AvatarRenderer val avatarRenderer: AvatarRenderer
) : VectorBaseFragment<FragmentSpaceRestrictedSelectBinding>(), ) : VectorBaseFragment<FragmentSpaceRestrictedSelectBinding>(),
// RoomJoinRuleChooseRestrictedViewModel.Factory,
ChooseRestrictedController.Listener, ChooseRestrictedController.Listener,
OnBackPressed { OnBackPressed {
// override fun create(initialState: RoomJoinRuleChooseRestrictedState) = viewModelFactory.create(initialState)
private val viewModel: RoomJoinRuleChooseRestrictedViewModel by activityViewModel(RoomJoinRuleChooseRestrictedViewModel::class) private val viewModel: RoomJoinRuleChooseRestrictedViewModel by activityViewModel(RoomJoinRuleChooseRestrictedViewModel::class)
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) = override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
@ -65,11 +61,7 @@ class RoomJoinRuleChooseRestrictedFragment @Inject constructor(
.disposeOnDestroyView() .disposeOnDestroyView()
views.okButton.debouncedClicks { views.okButton.debouncedClicks {
// withState(viewModel) { parentFragmentManager.popBackStack()
// // let's return the updated selection list
// setFragmentResult("SelectAllowList", bundleOf("bundleKey" to it.selectedRoomList))
// parentFragmentManager.popBackStack()
// }
} }
} }

View file

@ -32,14 +32,14 @@ data class RoomJoinRuleChooseRestrictedState(
val roomSummary: Async<RoomSummary> = Uninitialized, val roomSummary: Async<RoomSummary> = Uninitialized,
val initialRoomJoinRules: RoomJoinRules? = null, val initialRoomJoinRules: RoomJoinRules? = null,
val currentRoomJoinRules: RoomJoinRules? = null, val currentRoomJoinRules: RoomJoinRules? = null,
val updatedAllowList: List<MatrixItem>? = null, val updatedAllowList: List<MatrixItem> = emptyList(),
val choices: List<JoinRulesOptionSupport>? = null, val choices: List<JoinRulesOptionSupport>? = null,
val initialAllowList: List<RoomJoinRulesAllowEntry> = emptyList(), val initialAllowList: List<RoomJoinRulesAllowEntry> = emptyList(),
val selectedRoomList: List<String> = emptyList(),
val possibleSpaceCandidate: List<MatrixItem> = emptyList(), val possibleSpaceCandidate: List<MatrixItem> = emptyList(),
val unknownRestricted: List<MatrixItem> = emptyList(), val unknownRestricted: List<MatrixItem> = emptyList(),
val filter: String = "", val filter: String = "",
val filteredResults: Async<List<MatrixItem>> = Uninitialized val filteredResults: Async<List<MatrixItem>> = Uninitialized,
val hasUnsavedChanges: Boolean = false
) : MvRxState { ) : MvRxState {
constructor(args: RoomProfileArgs) : this(roomId = args.roomId) constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
} }

View file

@ -127,7 +127,10 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor(
currentRoomJoinRules = safeRule, currentRoomJoinRules = safeRule,
choices = choices, choices = choices,
initialAllowList = initialAllowList.orEmpty(), initialAllowList = initialAllowList.orEmpty(),
selectedRoomList = initialAllowList.orEmpty().map { it.spaceID }, updatedAllowList = initialAllowList.orEmpty().map {
session.getRoomSummary(it.spaceID)?.toMatrixItem() ?: MatrixItem.RoomItem(it.spaceID, null, null)
},
// selectedRoomList = initialAllowList.orEmpty().map { it.spaceID },
possibleSpaceCandidate = possibleSpaceCandidate, possibleSpaceCandidate = possibleSpaceCandidate,
unknownRestricted = unknownAllowedOrRooms unknownRestricted = unknownAllowedOrRooms
) )
@ -136,6 +139,27 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor(
} }
} }
fun checkForChanges() = withState { state ->
if (state.initialRoomJoinRules != state.currentRoomJoinRules) {
setState {
copy(hasUnsavedChanges = true)
}
return@withState
}
if (state.currentRoomJoinRules == RoomJoinRules.RESTRICTED) {
val allowDidChange = state.initialAllowList.map { it.spaceID } != state.updatedAllowList.map { it.id }
setState {
copy(hasUnsavedChanges = allowDidChange)
}
return@withState
}
setState {
copy(hasUnsavedChanges = false)
}
}
@AssistedFactory @AssistedFactory
interface Factory { interface Factory {
fun create(initialState: RoomJoinRuleChooseRestrictedState): RoomJoinRuleChooseRestrictedViewModel fun create(initialState: RoomJoinRuleChooseRestrictedState): RoomJoinRuleChooseRestrictedViewModel
@ -145,35 +169,50 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor(
when (action) { when (action) {
is RoomJoinRuleChooseRestrictedActions.FilterWith -> handleFilter(action) is RoomJoinRuleChooseRestrictedActions.FilterWith -> handleFilter(action)
is RoomJoinRuleChooseRestrictedActions.ToggleSelection -> handleToggleSelection(action) is RoomJoinRuleChooseRestrictedActions.ToggleSelection -> handleToggleSelection(action)
is RoomJoinRuleChooseRestrictedActions.SelectJoinRules -> handleSelectRule(action)
}.exhaustive }.exhaustive
checkForChanges()
}
fun handleSelectRule(action: RoomJoinRuleChooseRestrictedActions.SelectJoinRules) = withState { state ->
setState {
copy(
currentRoomJoinRules = action.rules
)
}
} }
private fun handleToggleSelection(action: RoomJoinRuleChooseRestrictedActions.ToggleSelection) = withState { state -> private fun handleToggleSelection(action: RoomJoinRuleChooseRestrictedActions.ToggleSelection) = withState { state ->
val selection = state.selectedRoomList.toMutableList() val selection = state.updatedAllowList.toMutableList()
if (selection.contains(action.matrixItem.id)) { if (selection.indexOfFirst { action.matrixItem.id == it.id } != -1) {
selection.remove(action.matrixItem.id) selection.removeAll { it.id == action.matrixItem.id }
} else { } else {
selection.add(action.matrixItem.id) selection.add(action.matrixItem)
} }
val unknownAllowedOrRooms = mutableListOf<MatrixItem>() val unknownAllowedOrRooms = mutableListOf<MatrixItem>()
// we would like to keep initial allowed here to show them unchecked // we would like to keep initial allowed here to show them unchecked
// to make it easier for users to spot the changes // to make it easier for users to spot the changes
state.initialAllowList.map { it.spaceID }.union(selection).sorted().forEach { entry -> val union = mutableListOf<MatrixItem>().apply {
val summary = session.getRoomSummary(entry) addAll(
state.initialAllowList.map {
session.getRoomSummary(it.spaceID)?.toMatrixItem() ?: MatrixItem.RoomItem(it.spaceID, null, null)
}
)
addAll(selection)
}.distinctBy { it.id }.sortedBy { it.id }
union.forEach { entry ->
val summary = session.getRoomSummary(entry.id)
if (summary == null) { if (summary == null) {
unknownAllowedOrRooms.add( unknownAllowedOrRooms.add(
MatrixItem.RoomItem(entry, null, null) entry
) )
} else if (summary.roomType != RoomType.SPACE) { } else if (summary.roomType != RoomType.SPACE) {
unknownAllowedOrRooms.add( unknownAllowedOrRooms.add(entry)
summary.toMatrixItem() } else if (!state.roomSummary.invoke()!!.flattenParentIds.contains(entry.id)) {
)
} else if (!state.roomSummary.invoke()!!.flattenParentIds.contains(entry)) {
// it's a space but not a direct parent // it's a space but not a direct parent
unknownAllowedOrRooms.add( unknownAllowedOrRooms.add(entry)
summary.toMatrixItem()
)
} else { } else {
// nop // nop
} }
@ -181,7 +220,7 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor(
setState { setState {
copy( copy(
selectedRoomList = selection.toList(), updatedAllowList = selection.toList(),
unknownRestricted = unknownAllowedOrRooms unknownRestricted = unknownAllowedOrRooms
) )
} }

View file

@ -31,6 +31,7 @@
app:layout_constraintTop_toBottomOf="@id/genericRecyclerView"> app:layout_constraintTop_toBottomOf="@id/genericRecyclerView">
<Button <Button
android:id="@+id/cancelButton"
style="@style/Widget.Vector.Button.Outlined" style="@style/Widget.Vector.Button.Outlined"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -38,6 +39,7 @@
android:text="@string/cancel" /> android:text="@string/cancel" />
<Button <Button
android:id="@+id/positiveButton"
style="@style/Widget.Vector.Button.Positive" style="@style/Widget.Vector.Button.Positive"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"