Edit room permissions (#2471)

This commit is contained in:
Benoit Marty 2021-01-06 16:15:01 +01:00
parent 22c10f5ada
commit c4a019f0d3
16 changed files with 654 additions and 9 deletions

View file

@ -3,6 +3,7 @@ Changes in Element 1.0.14 (2020-XX-XX)
Features ✨:
- Enable url previews for notices (#2562)
- Edit room permissions (#2471)
Improvements 🙌:
- Add System theme option and set as default (#904) (#2387)

View file

@ -84,6 +84,7 @@ import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
import im.vector.app.features.roomprofile.members.RoomMemberListFragment
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
import im.vector.app.features.roomprofile.alias.RoomAliasFragment
import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment
import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment
@ -364,6 +365,11 @@ interface FragmentModule {
@FragmentKey(RoomAliasFragment::class)
fun bindRoomAliasFragment(fragment: RoomAliasFragment): Fragment
@Binds
@IntoMap
@FragmentKey(RoomPermissionsFragment::class)
fun bindRoomPermissionsFragment(fragment: RoomPermissionsFragment): Fragment
@Binds
@IntoMap
@FragmentKey(RoomMemberProfileFragment::class)

View file

@ -324,7 +324,7 @@ class RoomMemberProfileFragment @Inject constructor(
}
override fun onEditPowerLevel(currentRole: Role) {
EditPowerLevelDialogs.showChoice(requireActivity(), currentRole) { newPowerLevel ->
EditPowerLevelDialogs.showChoice(requireActivity(), R.string.power_level_edit_title, currentRole) { newPowerLevel ->
viewModel.handle(RoomMemberProfileAction.SetPowerLevel(currentRole.value, newPowerLevel, true))
}
}

View file

@ -19,6 +19,7 @@ package im.vector.app.features.roommemberprofile.powerlevel
import android.app.Activity
import android.content.DialogInterface
import android.view.KeyEvent
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import im.vector.app.R
@ -29,7 +30,10 @@ import org.matrix.android.sdk.api.session.room.powerlevels.Role
object EditPowerLevelDialogs {
fun showChoice(activity: Activity, currentRole: Role, listener: (Int) -> Unit) {
fun showChoice(activity: Activity,
@StringRes titleRes: Int,
currentRole: Role,
listener: (Int) -> Unit) {
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_edit_power_level, null)
val views = DialogEditPowerLevelBinding.bind(dialogLayout)
views.powerLevelRadioGroup.setOnCheckedChangeListener { _, checkedId ->
@ -45,7 +49,7 @@ object EditPowerLevelDialogs {
}
AlertDialog.Builder(activity)
.setTitle(R.string.power_level_edit_title)
.setTitle(titleRes)
.setView(dialogLayout)
.setPositiveButton(R.string.edit) { _, _ ->
val newValue = when (views.powerLevelRadioGroup.checkedRadioButtonId) {

View file

@ -27,6 +27,7 @@ import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.extensions.addFragment
import im.vector.app.core.extensions.addFragmentToBackstack
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.ToolbarConfigurable
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivitySimpleBinding
@ -38,6 +39,7 @@ import im.vector.app.features.roomprofile.banned.RoomBannedMemberListFragment
import im.vector.app.features.roomprofile.members.RoomMemberListFragment
import im.vector.app.features.roomprofile.settings.RoomSettingsFragment
import im.vector.app.features.roomprofile.alias.RoomAliasFragment
import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
import javax.inject.Inject
@ -102,12 +104,13 @@ class RoomProfileActivity :
.observe()
.subscribe { sharedAction ->
when (sharedAction) {
is RoomProfileSharedAction.OpenRoomMembers -> openRoomMembers()
is RoomProfileSharedAction.OpenRoomSettings -> openRoomSettings()
is RoomProfileSharedAction.OpenRoomAliasesSettings -> openRoomAlias()
is RoomProfileSharedAction.OpenRoomUploads -> openRoomUploads()
is RoomProfileSharedAction.OpenBannedRoomMembers -> openBannedRoomMembers()
}
RoomProfileSharedAction.OpenRoomMembers -> openRoomMembers()
RoomProfileSharedAction.OpenRoomSettings -> openRoomSettings()
RoomProfileSharedAction.OpenRoomAliasesSettings -> openRoomAlias()
RoomProfileSharedAction.OpenRoomPermissionsSettings -> openRoomPermissions()
RoomProfileSharedAction.OpenRoomUploads -> openRoomUploads()
RoomProfileSharedAction.OpenBannedRoomMembers -> openBannedRoomMembers()
}.exhaustive
}
.disposeOnDestroy()
@ -144,6 +147,10 @@ class RoomProfileActivity :
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomAliasFragment::class.java, roomProfileArgs)
}
private fun openRoomPermissions() {
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomPermissionsFragment::class.java, roomProfileArgs)
}
private fun openRoomMembers() {
addFragmentToBackstack(R.id.simpleFragmentContainer, RoomMemberListFragment::class.java, roomProfileArgs)
}

View file

@ -24,6 +24,7 @@ import im.vector.app.core.platform.VectorSharedAction
sealed class RoomProfileSharedAction : VectorSharedAction {
object OpenRoomSettings : RoomProfileSharedAction()
object OpenRoomAliasesSettings : RoomProfileSharedAction()
object OpenRoomPermissionsSettings : RoomProfileSharedAction()
object OpenRoomUploads : RoomProfileSharedAction()
object OpenRoomMembers : RoomProfileSharedAction()
object OpenBannedRoomMembers : RoomProfileSharedAction()

View file

@ -0,0 +1,104 @@
/*
* 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.permissions
import androidx.annotation.StringRes
import im.vector.app.R
import org.matrix.android.sdk.api.session.events.model.EventType
/**
* Change on each permission has an effect on the power level event. Try to sort the effect by category.
*/
sealed class EditablePermission(@StringRes val labelResId: Int) {
// Updates `content.events.[eventType]`
open class EventTypeEditablePermission(val eventType: String, @StringRes labelResId: Int) : EditablePermission(labelResId)
class ModifyWidgets : EventTypeEditablePermission(
// Note: Element Web still use legacy value
EventType.STATE_ROOM_WIDGET_LEGACY,
R.string.room_permissions_modify_widgets
)
class ChangeRoomAvatar : EventTypeEditablePermission(
EventType.STATE_ROOM_AVATAR,
R.string.room_permissions_change_room_avatar
)
class ChangeMainAddressForTheRoom : EventTypeEditablePermission(
EventType.STATE_ROOM_CANONICAL_ALIAS,
R.string.room_permissions_change_main_address_for_the_room
)
class EnableRoomEncryption : EventTypeEditablePermission(
EventType.STATE_ROOM_ENCRYPTION,
R.string.room_permissions_enable_room_encryption
)
class ChangeHistoryVisibility : EventTypeEditablePermission(
EventType.STATE_ROOM_HISTORY_VISIBILITY,
R.string.room_permissions_change_history_visibility
)
class ChangeRoomName : EventTypeEditablePermission(
EventType.STATE_ROOM_NAME,
R.string.room_permissions_change_room_name
)
class ChangePermissions : EventTypeEditablePermission(
EventType.STATE_ROOM_POWER_LEVELS,
R.string.room_permissions_change_permissions
)
class SendRoomServerAclEvents : EventTypeEditablePermission(
EventType.STATE_ROOM_SERVER_ACL,
R.string.room_permissions_send_m_room_server_acl_events
)
class UpgradeTheRoom : EventTypeEditablePermission(
EventType.STATE_ROOM_TOMBSTONE,
R.string.room_permissions_upgrade_the_room
)
class ChangeTopic : EventTypeEditablePermission(
EventType.STATE_ROOM_TOPIC,
R.string.room_permissions_change_topic
)
// Updates `content.users_default`
class DefaultRole : EditablePermission(R.string.room_permissions_default_role)
// Updates `content.events_default`
class SendMessages : EditablePermission(R.string.room_permissions_send_messages)
// Updates `content.invites`
class InviteUsers : EditablePermission(R.string.room_permissions_invite_users)
// Updates `content.state_default`
class ChangeSettings : EditablePermission(R.string.room_permissions_change_settings)
// Updates `content.kick`
class KickUsers : EditablePermission(R.string.room_permissions_kick_users)
// Updates `content.ban`
class BanUsers : EditablePermission(R.string.room_permissions_ban_users)
// Updates `content.redact`
class RemoveMessagesSentByOthers : EditablePermission(R.string.room_permissions_remove_messages_sent_by_others)
// Updates `content.notification.room`
class NotifyEveryone : EditablePermission(R.string.room_permissions_notify_everyone)
}

View file

@ -0,0 +1,23 @@
/*
* Copyright 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.permissions
import im.vector.app.core.platform.VectorViewModelAction
sealed class RoomPermissionsAction : VectorViewModelAction {
data class UpdatePermission(val editablePermission: EditablePermission, val powerLevel: Int) : RoomPermissionsAction()
}

View file

@ -0,0 +1,144 @@
/*
* Copyright 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.permissions
import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Success
import im.vector.app.R
import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.epoxy.profiles.buildProfileAction
import im.vector.app.core.epoxy.profiles.buildProfileSection
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.discovery.settingsInfoItem
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.powerlevels.Role
import javax.inject.Inject
class RoomPermissionsController @Inject constructor(
private val stringProvider: StringProvider,
colorProvider: ColorProvider
) : TypedEpoxyController<RoomPermissionsViewState>() {
interface Callback {
fun onEditPermission(editablePermission: EditablePermission, currentRole: Role)
}
var callback: Callback? = null
private val dividerColor = colorProvider.getColorFromAttribute(R.attr.vctr_list_divider_color)
// Order is the order applied in the UI
private val allEditablePermissions = listOf(
EditablePermission.DefaultRole(),
EditablePermission.SendMessages(),
EditablePermission.InviteUsers(),
EditablePermission.ChangeSettings(),
EditablePermission.KickUsers(),
EditablePermission.BanUsers(),
EditablePermission.RemoveMessagesSentByOthers(),
EditablePermission.NotifyEveryone(),
EditablePermission.ModifyWidgets(),
EditablePermission.ChangeRoomAvatar(),
EditablePermission.ChangeMainAddressForTheRoom(),
EditablePermission.EnableRoomEncryption(),
EditablePermission.ChangeHistoryVisibility(),
EditablePermission.ChangeRoomName(),
EditablePermission.ChangePermissions(),
EditablePermission.SendRoomServerAclEvents(),
EditablePermission.UpgradeTheRoom(),
EditablePermission.ChangeTopic()
)
init {
setData(null)
}
override fun buildModels(data: RoomPermissionsViewState?) {
buildProfileSection(
stringProvider.getString(R.string.room_permissions_title)
)
settingsInfoItem {
id("notice")
helperText(stringProvider.getString(R.string.room_permissions_notice))
}
when (val content = data?.currentPowerLevelsContent) {
is Success -> buildPermissions(data, content())
else -> {
loadingItem {
id("loading")
loadingText(stringProvider.getString(R.string.loading))
}
}
}
}
private fun buildPermissions(data: RoomPermissionsViewState, content: PowerLevelsContent) {
allEditablePermissions.forEach { editablePermission ->
val currentRole = getCurrentRole(editablePermission, content)
buildProfileAction(
id = editablePermission.labelResId.toString(),
title = stringProvider.getString(editablePermission.labelResId),
subtitle = getSubtitle(currentRole),
dividerColor = dividerColor,
divider = true,
editable = data.actionPermissions.canChangePowerLevels,
action = { callback?.onEditPermission(editablePermission, currentRole) }
)
}
}
private fun getSubtitle(currentRole: Role): String {
return when (currentRole) {
Role.Admin,
Role.Moderator,
Role.Default -> stringProvider.getString(currentRole.res)
is Role.Custom -> stringProvider.getString(currentRole.res, currentRole.value)
}
}
private fun getCurrentRole(editablePermission: EditablePermission, content: PowerLevelsContent): Role {
val value = when (editablePermission) {
is EditablePermission.EventTypeEditablePermission -> content.events[editablePermission.eventType] ?: content.stateDefault
is EditablePermission.DefaultRole -> content.usersDefault
is EditablePermission.SendMessages -> content.eventsDefault
is EditablePermission.InviteUsers -> content.invite
is EditablePermission.ChangeSettings -> content.stateDefault
is EditablePermission.KickUsers -> content.kick
is EditablePermission.BanUsers -> content.ban
is EditablePermission.RemoveMessagesSentByOthers -> content.redact
is EditablePermission.NotifyEveryone -> (content.notifications["room"] as? Int) ?: Role.Moderator.value
}
return Role.fromValue(
value,
when (editablePermission) {
is EditablePermission.EventTypeEditablePermission -> content.stateDefault
is EditablePermission.DefaultRole -> Role.Default.value
is EditablePermission.SendMessages -> Role.Default.value
is EditablePermission.InviteUsers -> Role.Moderator.value
is EditablePermission.ChangeSettings -> Role.Moderator.value
is EditablePermission.KickUsers -> Role.Moderator.value
is EditablePermission.BanUsers -> Role.Moderator.value
is EditablePermission.RemoveMessagesSentByOthers -> Role.Moderator.value
is EditablePermission.NotifyEveryone -> Role.Moderator.value
}
)
}
}

View file

@ -0,0 +1,102 @@
/*
* Copyright 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.permissions
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import com.airbnb.mvrx.args
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.toast
import im.vector.app.databinding.FragmentRoomSettingGenericBinding
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs
import im.vector.app.features.roomprofile.RoomProfileArgs
import org.matrix.android.sdk.api.session.room.powerlevels.Role
import org.matrix.android.sdk.api.util.toMatrixItem
import javax.inject.Inject
class RoomPermissionsFragment @Inject constructor(
val viewModelFactory: RoomPermissionsViewModel.Factory,
private val controller: RoomPermissionsController,
private val avatarRenderer: AvatarRenderer
) :
VectorBaseFragment<FragmentRoomSettingGenericBinding>(),
RoomPermissionsController.Callback {
private val viewModel: RoomPermissionsViewModel by fragmentViewModel()
private val roomProfileArgs: RoomProfileArgs by args()
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRoomSettingGenericBinding {
return FragmentRoomSettingGenericBinding.inflate(inflater, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
controller.callback = this
setupToolbar(views.roomSettingsToolbar)
views.roomSettingsRecyclerView.configureWith(controller, hasFixedSize = true)
views.waitingView.waitingStatusText.setText(R.string.please_wait)
views.waitingView.waitingStatusText.isVisible = true
viewModel.observeViewEvents {
when (it) {
is RoomPermissionsViewEvents.Failure -> showFailure(it.throwable)
RoomPermissionsViewEvents.Success -> showSuccess()
}.exhaustive
}
}
private fun showSuccess() {
activity?.toast(R.string.room_settings_save_success)
}
override fun onDestroyView() {
controller.callback = null
views.roomSettingsRecyclerView.cleanup()
super.onDestroyView()
}
override fun invalidate() = withState(viewModel) { state ->
views.waitingView.root.isVisible = state.isLoading
controller.setData(state)
renderRoomSummary(state)
}
private fun renderRoomSummary(state: RoomPermissionsViewState) {
state.roomSummary()?.let {
views.roomSettingsToolbarTitleView.text = it.displayName
avatarRenderer.render(it.toMatrixItem(), views.roomSettingsToolbarAvatarImageView)
}
}
override fun onEditPermission(editablePermission: EditablePermission, currentRole: Role) {
EditPowerLevelDialogs.showChoice(requireActivity(), editablePermission.labelResId, currentRole) { newPowerLevel ->
viewModel.handle(RoomPermissionsAction.UpdatePermission(editablePermission, newPowerLevel))
}
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright 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.permissions
import im.vector.app.core.platform.VectorViewEvents
/**
* Transient events for room settings screen
*/
sealed class RoomPermissionsViewEvents : VectorViewEvents {
data class Failure(val throwable: Throwable) : RoomPermissionsViewEvents()
object Success : RoomPermissionsViewEvents()
}

View file

@ -0,0 +1,144 @@
/*
* Copyright 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.permissions
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.powerlevel.PowerLevelsObservableFactory
import kotlinx.coroutines.launch
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.toContent
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
import org.matrix.android.sdk.rx.rx
import org.matrix.android.sdk.rx.unwrap
class RoomPermissionsViewModel @AssistedInject constructor(@Assisted initialState: RoomPermissionsViewState,
private val session: Session)
: VectorViewModel<RoomPermissionsViewState, RoomPermissionsAction, RoomPermissionsViewEvents>(initialState) {
@AssistedInject.Factory
interface Factory {
fun create(initialState: RoomPermissionsViewState): RoomPermissionsViewModel
}
companion object : MvRxViewModelFactory<RoomPermissionsViewModel, RoomPermissionsViewState> {
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: RoomPermissionsViewState): RoomPermissionsViewModel? {
val fragment: RoomPermissionsFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.viewModelFactory.create(state)
}
}
private val room = session.getRoom(initialState.roomId)!!
init {
observeRoomSummary()
observePowerLevel()
}
private fun observeRoomSummary() {
room.rx().liveRoomSummary()
.unwrap()
.execute { async ->
copy(
roomSummary = async
)
}
}
private fun observePowerLevel() {
PowerLevelsObservableFactory(room)
.createObservable()
.subscribe { powerLevelContent ->
val powerLevelsHelper = PowerLevelsHelper(powerLevelContent)
val permissions = RoomPermissionsViewState.ActionPermissions(
canChangePowerLevels = powerLevelsHelper.isUserAllowedToSend(
userId = session.myUserId,
isState = true,
eventType = EventType.STATE_ROOM_POWER_LEVELS
)
)
setState {
copy(
actionPermissions = permissions,
currentPowerLevelsContent = Success(powerLevelContent)
)
}
}
.disposeOnClear()
}
override fun handle(action: RoomPermissionsAction) {
when (action) {
is RoomPermissionsAction.UpdatePermission -> updatePermission(action)
}.exhaustive
}
private fun updatePermission(action: RoomPermissionsAction.UpdatePermission) {
withState { state ->
val currentPowerLevel = state.currentPowerLevelsContent.invoke() ?: return@withState
postLoading(true)
viewModelScope.launch {
try {
val newPowerLevelsContent = when(action.editablePermission) {
is EditablePermission.EventTypeEditablePermission -> currentPowerLevel.copy(
events = currentPowerLevel.events.toMutableMap().apply {
put(action.editablePermission.eventType, action.powerLevel)
}
)
is EditablePermission.DefaultRole -> currentPowerLevel.copy(usersDefault = action.powerLevel)
is EditablePermission.SendMessages -> currentPowerLevel.copy(eventsDefault = action.powerLevel)
is EditablePermission.InviteUsers -> currentPowerLevel.copy(invite = action.powerLevel)
is EditablePermission.ChangeSettings -> currentPowerLevel.copy(stateDefault = action.powerLevel)
is EditablePermission.KickUsers -> currentPowerLevel.copy(kick = action.powerLevel)
is EditablePermission.BanUsers -> currentPowerLevel.copy(ban = action.powerLevel)
is EditablePermission.RemoveMessagesSentByOthers -> currentPowerLevel.copy(redact = action.powerLevel)
is EditablePermission.NotifyEveryone -> currentPowerLevel.copy(
notifications = currentPowerLevel.notifications.toMutableMap().apply {
put("room", action.powerLevel)
}
)
}
room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, null, newPowerLevelsContent.toContent())
setState {
copy(
isLoading = false
)
}
} catch (failure: Throwable) {
postLoading(false)
_viewEvents.post(RoomPermissionsViewEvents.Failure(failure))
}
}
}
}
private fun postLoading(isLoading: Boolean) {
setState {
copy(isLoading = isLoading)
}
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright 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.permissions
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.Uninitialized
import im.vector.app.features.roomprofile.RoomProfileArgs
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.RoomSummary
data class RoomPermissionsViewState(
val roomId: String,
val roomSummary: Async<RoomSummary> = Uninitialized,
val actionPermissions: ActionPermissions = ActionPermissions(),
val currentPowerLevelsContent: Async<PowerLevelsContent> = Uninitialized,
val newPowerLevelsContent: PowerLevelsContent? = null,
val isLoading: Boolean = false
) : MvRxState {
constructor(args: RoomProfileArgs) : this(roomId = args.roomId)
data class ActionPermissions(
val canChangePowerLevels: Boolean = false
)
}

View file

@ -46,6 +46,7 @@ class RoomSettingsController @Inject constructor(
fun onTopicChanged(topic: String)
fun onHistoryVisibilityClicked()
fun onRoomAliasesClicked()
fun onRoomPermissionsClicked()
fun onJoinRuleClicked()
}
@ -115,6 +116,16 @@ class RoomSettingsController @Inject constructor(
action = { callback?.onRoomAliasesClicked() }
)
buildProfileAction(
id = "permissions",
title = stringProvider.getString(R.string.room_settings_permissions_title),
subtitle = stringProvider.getString(R.string.room_settings_permissions_subtitle),
dividerColor = dividerColor,
divider = true,
editable = true,
action = { callback?.onRoomPermissionsClicked() }
)
buildProfileAction(
id = "historyReadability",
title = stringProvider.getString(R.string.room_settings_room_read_history_rules_pref_title),

View file

@ -178,6 +178,10 @@ class RoomSettingsFragment @Inject constructor(
roomProfileSharedActionViewModel.post(RoomProfileSharedAction.OpenRoomAliasesSettings)
}
override fun onRoomPermissionsClicked() {
roomProfileSharedActionViewModel.post(RoomProfileSharedAction.OpenRoomPermissionsSettings)
}
override fun onJoinRuleClicked() = withState(viewModel) { state ->
val currentJoinRule = state.newRoomJoinRules.newJoinRules ?: state.currentRoomJoinRules
val currentGuestAccess = state.newRoomJoinRules.newGuestAccess ?: state.currentGuestAccess

View file

@ -609,6 +609,32 @@
<string name="ssl_expected_existing_expl">The certificate has changed from a previously trusted one to one that is not trusted. The server may have renewed its certificate. Contact the server administrator for the expected fingerprint.</string>
<string name="ssl_only_accept">Only accept the certificate if the server administrator has published a fingerprint that matches the one above.</string>
<!-- Room Permissions -->
<string name="room_settings_permissions_title">Room permissions</string>
<string name="room_settings_permissions_subtitle">View and update the roles required to change various parts of the room.</string>
<string name="room_permissions_title">"Permissions"</string>
<string name="room_permissions_notice">"Select the roles required to change various parts of the room"</string>
<string name="room_permissions_default_role">Default role</string>
<string name="room_permissions_send_messages">Send messages</string>
<string name="room_permissions_invite_users">Invite users</string>
<string name="room_permissions_change_settings">Change settings</string>
<string name="room_permissions_kick_users">Kick users</string>
<string name="room_permissions_ban_users">Ban users</string>
<string name="room_permissions_remove_messages_sent_by_others">Remove messages sent by others</string>
<string name="room_permissions_notify_everyone">Notify everyone</string>
<string name="room_permissions_modify_widgets">Modify widgets</string>
<string name="room_permissions_change_room_avatar">Change room avatar</string>
<string name="room_permissions_change_main_address_for_the_room">Change main address for the room</string>
<string name="room_permissions_enable_room_encryption">Enable room encryption</string>
<string name="room_permissions_change_history_visibility">Change history visibility</string>
<string name="room_permissions_change_room_name">Change room name</string>
<string name="room_permissions_change_permissions">Change permissions</string>
<string name="room_permissions_send_m_room_server_acl_events">Send m.room.server_acl events</string>
<string name="room_permissions_upgrade_the_room">Upgrade the room</string>
<string name="room_permissions_change_topic">Change topic</string>
<!-- Room Details -->
<string name="room_details_title">Room Details</string>
<string name="room_details_people">People</string>