diff --git a/changelog.d/3951.bugfix b/changelog.d/3951.bugfix new file mode 100644 index 00000000000..cefcb996fa5 --- /dev/null +++ b/changelog.d/3951.bugfix @@ -0,0 +1 @@ +"Non-Admin" user able to invite others to Private Space (by default) \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt index 7be4cdcda95..1f47fe47e44 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt @@ -33,6 +33,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper +import org.matrix.android.sdk.api.session.room.powerlevels.Role import org.matrix.android.sdk.api.session.space.CreateSpaceParams import org.matrix.android.sdk.api.session.space.JoinSpaceResult import org.matrix.android.sdk.api.session.space.Space @@ -77,7 +78,7 @@ internal class DefaultSpaceService @Inject constructor( if (isPublic) { this.roomAliasName = roomAliasLocalPart this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy( - invite = 0 + invite = if (isPublic) Role.Default.value else Role.Moderator.value ) this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT this.historyVisibility = RoomHistoryVisibility.WORLD_READABLE diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt index bb1054b7048..b083209f16b 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/EditablePermission.kt @@ -23,9 +23,12 @@ 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) { +sealed class EditablePermission(@StringRes val labelResId: Int, @StringRes val spaceLabelResId: Int = labelResId) { // Updates `content.events.[eventType]` - open class EventTypeEditablePermission(val eventType: String, @StringRes labelResId: Int) : EditablePermission(labelResId) + open class EventTypeEditablePermission(val eventType: String, + @StringRes labelResId: Int, + @StringRes spaceLabelResId: Int = labelResId + ) : EditablePermission(labelResId, spaceLabelResId) class ModifyWidgets : EventTypeEditablePermission( // Note: Element Web still use legacy value @@ -35,17 +38,20 @@ sealed class EditablePermission(@StringRes val labelResId: Int) { class ChangeRoomAvatar : EventTypeEditablePermission( EventType.STATE_ROOM_AVATAR, - R.string.room_permissions_change_room_avatar + R.string.room_permissions_change_room_avatar, + R.string.room_permissions_change_space_avatar ) class ChangeMainAddressForTheRoom : EventTypeEditablePermission( EventType.STATE_ROOM_CANONICAL_ALIAS, - R.string.room_permissions_change_main_address_for_the_room + R.string.room_permissions_change_main_address_for_the_room, + R.string.room_permissions_change_main_address_for_the_space ) class EnableRoomEncryption : EventTypeEditablePermission( EventType.STATE_ROOM_ENCRYPTION, - R.string.room_permissions_enable_room_encryption + R.string.room_permissions_enable_room_encryption, + R.string.room_permissions_enable_space_encryption ) class ChangeHistoryVisibility : EventTypeEditablePermission( @@ -55,7 +61,8 @@ sealed class EditablePermission(@StringRes val labelResId: Int) { class ChangeRoomName : EventTypeEditablePermission( EventType.STATE_ROOM_NAME, - R.string.room_permissions_change_room_name + R.string.room_permissions_change_room_name, + R.string.room_permissions_change_space_name ) class ChangePermissions : EventTypeEditablePermission( @@ -70,7 +77,8 @@ sealed class EditablePermission(@StringRes val labelResId: Int) { class UpgradeTheRoom : EventTypeEditablePermission( EventType.STATE_ROOM_TOMBSTONE, - R.string.room_permissions_upgrade_the_room + R.string.room_permissions_upgrade_the_room, + R.string.room_permissions_upgrade_the_space ) class ChangeTopic : EventTypeEditablePermission( diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt index ead878936e6..1f2c8769021 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/permissions/RoomPermissionsController.kt @@ -26,6 +26,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.features.discovery.settingsInfoItem import im.vector.app.features.form.formAdvancedToggleItem import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent +import org.matrix.android.sdk.api.session.room.model.RoomType import org.matrix.android.sdk.api.session.room.model.banOrDefault import org.matrix.android.sdk.api.session.room.model.eventsDefaultOrDefault import org.matrix.android.sdk.api.session.room.model.inviteOrDefault @@ -57,6 +58,13 @@ class RoomPermissionsController @Inject constructor( EditablePermission.ChangeTopic() ) + private val usefulEditablePermissionsForSpace = listOf( + EditablePermission.ChangeRoomAvatar(), + EditablePermission.ChangeRoomName(), + EditablePermission.ChangeTopic(), + EditablePermission.InviteUsers() + ) + private val advancedEditablePermissions = listOf( EditablePermission.ChangeMainAddressForTheRoom(), @@ -79,6 +87,27 @@ class RoomPermissionsController @Inject constructor( EditablePermission.UpgradeTheRoom() ) + private val advancedEditablePermissionsForSpace = listOf( + EditablePermission.ChangeMainAddressForTheRoom(), + + EditablePermission.DefaultRole(), + EditablePermission.KickUsers(), + EditablePermission.BanUsers(), + + EditablePermission.SendMessages(), + + EditablePermission.RemoveMessagesSentByOthers(), + EditablePermission.NotifyEveryone(), + + EditablePermission.ChangeSettings(), +// EditablePermission.ModifyWidgets(), + EditablePermission.ChangeHistoryVisibility(), + EditablePermission.ChangePermissions(), + EditablePermission.SendRoomServerAclEvents(), +// EditablePermission.EnableRoomEncryption(), + EditablePermission.UpgradeTheRoom() + ) + init { setData(null) } @@ -103,13 +132,24 @@ class RoomPermissionsController @Inject constructor( private fun buildPermissions(data: RoomPermissionsViewState, content: PowerLevelsContent) { val host = this val editable = data.actionPermissions.canChangePowerLevels + val isSpace = data.roomSummary.invoke()?.roomType == RoomType.SPACE + settingsInfoItem { id("notice") - helperText(host.stringProvider.getString(if (editable) R.string.room_permissions_notice else R.string.room_permissions_notice_read_only)) + helperText(host.stringProvider.getString( + if (editable) { + if (isSpace) R.string.space_permissions_notice else R.string.room_permissions_notice + } else { + if (isSpace) R.string.space_permissions_notice_read_only else R.string.room_permissions_notice_read_only + })) } // Useful permissions - usefulEditablePermissions.forEach { buildPermission(it, content, editable) } + if (isSpace) { + usefulEditablePermissionsForSpace.forEach { buildPermission(it, content, editable, true) } + } else { + usefulEditablePermissions.forEach { buildPermission(it, content, editable, false) } + } // Toggle formAdvancedToggleItem { @@ -121,15 +161,24 @@ class RoomPermissionsController @Inject constructor( // Advanced permissions if (data.showAdvancedPermissions) { - advancedEditablePermissions.forEach { buildPermission(it, content, editable) } + if (isSpace) { + advancedEditablePermissionsForSpace.forEach { buildPermission(it, content, editable, true) } + } else { + advancedEditablePermissions.forEach { buildPermission(it, content, editable, false) } + } } } - private fun buildPermission(editablePermission: EditablePermission, content: PowerLevelsContent, editable: Boolean) { + private fun buildPermission(editablePermission: EditablePermission, + content: PowerLevelsContent, + editable: Boolean, + isSpace: Boolean) { val currentRole = getCurrentRole(editablePermission, content) buildProfileAction( id = editablePermission.labelResId.toString(), - title = stringProvider.getString(editablePermission.labelResId), + title = stringProvider.getString( + if (isSpace) editablePermission.spaceLabelResId else editablePermission.labelResId + ), subtitle = roleFormatter.format(currentRole), divider = true, editable = editable, diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt index 64209127b4e..e6ead2294ef 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt @@ -383,7 +383,7 @@ class CreateSpaceViewModel @AssistedInject constructor( ) ) when (result) { - is CreateSpaceTaskResult.Success -> { + is CreateSpaceTaskResult.Success -> { setState { copy(creationResult = Success(result.spaceId)) } diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModelTask.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModelTask.kt index 41a85d3f308..f6f168c3659 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModelTask.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModelTask.kt @@ -35,6 +35,8 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset + +import org.matrix.android.sdk.api.session.room.powerlevels.Role import org.matrix.android.sdk.api.session.space.CreateSpaceParams import timber.log.Timber import javax.inject.Inject @@ -73,7 +75,7 @@ class CreateSpaceViewModelTask @Inject constructor( if (params.isPublic) { this.roomAliasName = params.spaceAlias this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy( - invite = 0 + invite = Role.Default.value ) this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT this.historyVisibility = RoomHistoryVisibility.WORLD_READABLE @@ -86,6 +88,9 @@ class CreateSpaceViewModelTask @Inject constructor( ThreePid.Email(it) } ) + this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy( + invite = Role.Moderator.value + ) } }) } catch (failure: Throwable) { diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt index 630c5780693..2fd0ff19bfd 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageActivity.kt @@ -20,12 +20,12 @@ import android.content.Context import android.content.Intent import android.os.Bundle import android.os.Parcelable -import com.google.android.material.appbar.MaterialToolbar import androidx.core.view.isGone import androidx.core.view.isVisible import com.airbnb.mvrx.MvRx import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.withState +import com.google.android.material.appbar.MaterialToolbar import im.vector.app.R import im.vector.app.core.di.ScreenComponent import im.vector.app.core.extensions.addFragmentToBackstack @@ -40,6 +40,7 @@ import im.vector.app.features.roomdirectory.createroom.CreateRoomArgs import im.vector.app.features.roomdirectory.createroom.CreateRoomFragment import im.vector.app.features.roomprofile.RoomProfileArgs import im.vector.app.features.roomprofile.alias.RoomAliasFragment +import im.vector.app.features.roomprofile.permissions.RoomPermissionsFragment import kotlinx.parcelize.Parcelize import javax.inject.Inject @@ -98,7 +99,7 @@ class SpaceManageActivity : VectorBaseActivity(), if (isFirstCreation()) { withState(sharedViewModel) { when (it.manageType) { - ManageType.AddRooms -> { + ManageType.AddRooms -> { val simpleName = SpaceAddRoomFragment::class.java.simpleName if (supportFragmentManager.findFragmentByTag(simpleName) == null) { supportFragmentManager.commitTransaction { @@ -110,7 +111,7 @@ class SpaceManageActivity : VectorBaseActivity(), } } } - ManageType.Settings -> { + ManageType.Settings -> { val simpleName = SpaceSettingsFragment::class.java.simpleName if (supportFragmentManager.findFragmentByTag(simpleName) == null && args?.spaceId != null) { supportFragmentManager.commitTransaction { @@ -131,23 +132,23 @@ class SpaceManageActivity : VectorBaseActivity(), sharedViewModel.observeViewEvents { when (it) { - SpaceManagedSharedViewEvents.Finish -> { + SpaceManagedSharedViewEvents.Finish -> { finish() } - SpaceManagedSharedViewEvents.HideLoading -> { + SpaceManagedSharedViewEvents.HideLoading -> { hideWaitingView() } - SpaceManagedSharedViewEvents.ShowLoading -> { + SpaceManagedSharedViewEvents.ShowLoading -> { showWaitingView() } - SpaceManagedSharedViewEvents.NavigateToCreateRoom -> { + SpaceManagedSharedViewEvents.NavigateToCreateRoom -> { addFragmentToBackstack( R.id.simpleFragmentContainer, CreateRoomFragment::class.java, CreateRoomArgs("", parentSpaceId = args?.spaceId) ) } - SpaceManagedSharedViewEvents.NavigateToManageRooms -> { + SpaceManagedSharedViewEvents.NavigateToManageRooms -> { args?.spaceId?.let { spaceId -> addFragmentToBackstack( R.id.simpleFragmentContainer, @@ -156,7 +157,7 @@ class SpaceManageActivity : VectorBaseActivity(), ) } } - SpaceManagedSharedViewEvents.NavigateToAliasSettings -> { + SpaceManagedSharedViewEvents.NavigateToAliasSettings -> { args?.spaceId?.let { spaceId -> addFragmentToBackstack( R.id.simpleFragmentContainer, @@ -165,6 +166,14 @@ class SpaceManageActivity : VectorBaseActivity(), ) } } + SpaceManagedSharedViewEvents.NavigateToPermissionSettings -> { + args?.spaceId?.let { spaceId -> + addFragmentToBackstack( + R.id.simpleFragmentContainer, RoomPermissionsFragment::class.java, + RoomProfileArgs(spaceId) + ) + } + } } } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageSharedViewModel.kt index f1d041056fd..411c987776f 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManageSharedViewModel.kt @@ -48,15 +48,16 @@ class SpaceManageSharedViewModel @AssistedInject constructor( override fun handle(action: SpaceManagedSharedAction) { when (action) { - SpaceManagedSharedAction.HandleBack -> { + SpaceManagedSharedAction.HandleBack -> { // for now finish _viewEvents.post(SpaceManagedSharedViewEvents.Finish) } - SpaceManagedSharedAction.HideLoading -> _viewEvents.post(SpaceManagedSharedViewEvents.HideLoading) - SpaceManagedSharedAction.ShowLoading -> _viewEvents.post(SpaceManagedSharedViewEvents.ShowLoading) - SpaceManagedSharedAction.CreateRoom -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToCreateRoom) - SpaceManagedSharedAction.ManageRooms -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToManageRooms) - SpaceManagedSharedAction.OpenSpaceAliasesSettings -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToAliasSettings) + SpaceManagedSharedAction.HideLoading -> _viewEvents.post(SpaceManagedSharedViewEvents.HideLoading) + SpaceManagedSharedAction.ShowLoading -> _viewEvents.post(SpaceManagedSharedViewEvents.ShowLoading) + SpaceManagedSharedAction.CreateRoom -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToCreateRoom) + SpaceManagedSharedAction.ManageRooms -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToManageRooms) + SpaceManagedSharedAction.OpenSpaceAliasesSettings -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToAliasSettings) + SpaceManagedSharedAction.OpenSpacePermissionSettings -> _viewEvents.post(SpaceManagedSharedViewEvents.NavigateToPermissionSettings) } } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManagedSharedAction.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManagedSharedAction.kt index 77143470bc9..07c305e3eb6 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManagedSharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManagedSharedAction.kt @@ -25,4 +25,5 @@ sealed class SpaceManagedSharedAction : VectorViewModelAction { object CreateRoom : SpaceManagedSharedAction() object ManageRooms : SpaceManagedSharedAction() object OpenSpaceAliasesSettings : SpaceManagedSharedAction() + object OpenSpacePermissionSettings : SpaceManagedSharedAction() } diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManagedSharedViewEvents.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManagedSharedViewEvents.kt index ab993764c68..3d66bde2eef 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManagedSharedViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceManagedSharedViewEvents.kt @@ -25,4 +25,5 @@ sealed class SpaceManagedSharedViewEvents : VectorViewEvents { object NavigateToCreateRoom : SpaceManagedSharedViewEvents() object NavigateToManageRooms : SpaceManagedSharedViewEvents() object NavigateToAliasSettings : SpaceManagedSharedViewEvents() + object NavigateToPermissionSettings : SpaceManagedSharedViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsController.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsController.kt index 27204be8a67..a2b74eb93a1 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsController.kt @@ -53,6 +53,7 @@ class SpaceSettingsController @Inject constructor( fun onManageRooms() fun setIsPublic(public: Boolean) fun onRoomAliasesClicked() + fun onRoomPermissionsClicked() } var callback: Callback? = null @@ -134,7 +135,7 @@ class SpaceSettingsController @Inject constructor( id = "manage_rooms", title = stringProvider.getString(R.string.space_settings_manage_rooms), // subtitle = data.getJoinRuleWording(stringProvider), - divider = vectorPreferences.developerMode() || isPublic, + divider = true, editable = data.actionPermissions.canAddChildren, action = { if (data.actionPermissions.canAddChildren) callback?.onManageRooms() @@ -146,12 +147,21 @@ class SpaceSettingsController @Inject constructor( id = "alias", title = stringProvider.getString(R.string.space_settings_alias_title), subtitle = stringProvider.getString(R.string.space_settings_alias_subtitle), - divider = vectorPreferences.developerMode(), + divider = true, editable = true, action = { callback?.onRoomAliasesClicked() } ) } + buildProfileAction( + id = "permissions", + title = stringProvider.getString(R.string.space_settings_permissions_title), + subtitle = stringProvider.getString(R.string.space_settings_permissions_subtitle), + divider = vectorPreferences.developerMode(), + editable = true, + action = { callback?.onRoomPermissionsClicked() } + ) + if (vectorPreferences.developerMode()) { buildProfileAction( id = "dev_tools", diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt index e831732bccf..8519f1d4896 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt @@ -237,6 +237,10 @@ class SpaceSettingsFragment @Inject constructor( sharedViewModel.handle(SpaceManagedSharedAction.OpenSpaceAliasesSettings) } + override fun onRoomPermissionsClicked() { + sharedViewModel.handle(SpaceManagedSharedAction.OpenSpacePermissionSettings) + } + override fun onImageReady(uri: Uri?) { uri ?: return viewModel.handle( diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index ab4f2803931..cc8bc1e99b4 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -974,11 +974,15 @@ Room permissions + Space permissions View and update the roles required to change various parts of the room. + View and update the roles required to change various parts of the space. "Permissions" "Select the roles required to change various parts of the room" + "Select the roles required to change various parts of this space" "You don't have permission to update the roles required to change various parts of the room" + "You don't have permission to update the roles required to change various parts of this space" Default role Send messages @@ -990,13 +994,18 @@ Notify everyone Modify widgets Change room avatar + Change space avatar Change main address for the room + Change main address for the space Enable room encryption + Enable space encryption Change history visibility Change room name + Change space name Change permissions Send m.room.server_acl events Upgrade the room + Upgrade the space Change topic