Add room permissions

Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
Ajay Bura 2022-01-10 20:34:54 +05:30
parent af61f4f1db
commit 769d24d196
5 changed files with 238 additions and 16 deletions

View file

@ -0,0 +1,208 @@
import React from 'react';
import PropTypes from 'prop-types';
import './RoomPermissions.scss';
import initMatrix from '../../../client/initMatrix';
import { getPowerLabel } from '../../../util/matrixUtil';
import Text from '../../atoms/text/Text';
import Button from '../../atoms/button/Button';
import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
import SettingTile from '../setting-tile/SettingTile';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
const permissionsInfo = {
users_default: {
name: 'Default role',
description: 'Set default role for all members.',
default: 0,
},
events_default: {
name: 'Send messages',
description: 'Set minimum power level to send messages in room.',
default: 0,
},
redact: {
name: 'Delete messages sent by others',
description: 'Set minimum power level to delete messages in room.',
default: 50,
},
notifications: {
name: 'Ping room',
description: 'Set minimum power level to ping room.',
default: {
room: 50,
},
},
'm.space.child': {
parent: 'events',
name: 'Manage rooms in space',
description: 'Set minimum power level to manage rooms in space.',
default: 50,
},
invite: {
name: 'Invite',
description: 'Set minimum power level to invite members.',
default: 50,
},
kick: {
name: 'Kick',
description: 'Set minimum power level to kick members.',
default: 50,
},
ban: {
name: 'Ban',
description: 'Set minimum power level to ban members.',
default: 50,
},
'm.room.avatar': {
parent: 'events',
name: 'Change avatar',
description: 'Set minimum power level to change room/space avatar.',
default: 50,
},
'm.room.name': {
parent: 'events',
name: 'Change name',
description: 'Set minimum power level to change room/space name.',
default: 50,
},
'm.room.topic': {
parent: 'events',
name: 'Change topic',
description: 'Set minimum power level to change room/space topic.',
default: 50,
},
state_default: {
name: 'Change settings',
description: 'Set minimum power level to change settings.',
default: 50,
},
'm.room.canonical_alias': {
parent: 'events',
name: 'Change published address',
description: 'Set minimum power level to publish and set main address.',
default: 50,
},
'm.room.power_levels': {
parent: 'events',
name: 'Change permissions',
description: 'Set minimum power level to change permissions.',
default: 50,
},
'm.room.encryption': {
parent: 'events',
name: 'Enable room encryption',
description: 'Set minimum power level to enable room encryption.',
default: 50,
},
'm.room.history_visibility': {
parent: 'events',
name: 'Change history visibility',
description: 'Set minimum power level to change room messages history visibility.',
default: 50,
},
'm.room.tombstone': {
parent: 'events',
name: 'Upgrade room',
description: 'Set minimum power level to upgrade room.',
default: 50,
},
'm.room.pinned_events': {
parent: 'events',
name: 'Pin messages',
description: 'Set minimum power level to pin messages in room.',
default: 50,
},
'm.room.server_acl': {
parent: 'events',
name: 'Change server ACLs',
description: 'Set minimum power level to change server ACLs.',
default: 50,
},
'im.vector.modular.widgets': {
parent: 'events',
name: 'Modify widgets',
description: 'Set minimum power level to modify room widgets.',
default: 50,
},
};
const roomPermsGroups = {
'General Permissions': ['users_default', 'events_default', 'redact', 'notifications'],
'Manage members permissions': ['invite', 'kick', 'ban'],
'Room profile permissions': ['m.room.avatar', 'm.room.name', 'm.room.topic'],
'Settings permissions': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels', 'm.room.encryption', 'm.room.history_visibility'],
'Other permissions': ['m.room.tombstone', 'm.room.pinned_events', 'm.room.server_acl', 'im.vector.modular.widgets'],
};
const spacePermsGroups = {
'General Permissions': ['users_default', 'm.space.child'],
'Manage members permissions': ['invite', 'kick', 'ban'],
'Space profile permissions': ['m.room.avatar', 'm.room.name', 'm.room.topic'],
'Settings permissions': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels'],
};
function RoomPermissions({ roomId }) {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const pLEvent = room.currentState.getStateEvents('m.room.power_levels')[0];
const permissions = pLEvent.getContent();
const canChangePermission = room.currentState.maySendStateEvent('m.room.power_levels', mx.getUserId());
return (
<div className="room-permissions">
{
Object.keys(roomPermsGroups).map((groupKey) => {
const groupedPermKeys = roomPermsGroups[groupKey];
return (
<div className="room-permissions__card" key={groupKey}>
<MenuHeader>{groupKey}</MenuHeader>
{
groupedPermKeys.map((permKey) => {
const permInfo = permissionsInfo[permKey];
let powerLevel = 0;
let permValue = permInfo.parent
? permissions[permInfo.parent][permKey]
: permissions[permKey];
if (!permValue) permValue = permInfo.default;
if (typeof permValue === 'number') {
powerLevel = permValue;
} else if (permKey === 'notifications') {
powerLevel = permValue.room || 50;
}
return (
<SettingTile
key={permKey}
title={permInfo.name}
content={<Text variant="b3">{permInfo.description}</Text>}
options={(
<Button
iconSrc={canChangePermission ? ChevronBottomIC : null}
>
<Text variant="b2">
{`${getPowerLabel(powerLevel) || 'Member'} - ${powerLevel}`}
</Text>
</Button>
)}
/>
);
})
}
</div>
);
})
}
</div>
);
}
RoomPermissions.propTypes = {
roomId: PropTypes.string.isRequired,
};
export default RoomPermissions;

View file

@ -0,0 +1,11 @@
.room-permissions {
& .setting-tile {
margin: 0 var(--sp-normal);
margin-top: var(--sp-tight);
padding-bottom: var(--sp-tight);
border-bottom: 1px solid var(--bg-surface-border);
&:last-child {
border-bottom: none;
}
}
}

View file

@ -261,6 +261,7 @@ function ProfileViewer() {
function renderProfile() { function renderProfile() {
const member = room.getMember(userId) || mx.getUser(userId) || {}; const member = room.getMember(userId) || mx.getUser(userId) || {};
const avatarMxc = member.getMxcAvatarUrl?.() || member.avatarUrl; const avatarMxc = member.getMxcAvatarUrl?.() || member.avatarUrl;
const powerLevel = member.powerLevel || 0;
const canChangeRole = room.currentState.maySendEvent('m.room.power_levels', mx.getUserId()); const canChangeRole = room.currentState.maySendEvent('m.room.power_levels', mx.getUserId());
return ( return (
@ -278,7 +279,9 @@ function ProfileViewer() {
</div> </div>
<div className="profile-viewer__user__role"> <div className="profile-viewer__user__role">
<Text variant="b3">Role</Text> <Text variant="b3">Role</Text>
<Button iconSrc={canChangeRole ? ChevronBottomIC : null}>{getPowerLabel(member.powerLevel) || 'Member'}</Button> <Button iconSrc={canChangeRole ? ChevronBottomIC : null}>
{`${getPowerLabel(powerLevel) || 'Member'} - ${powerLevel}`}
</Button>
</div> </div>
</div> </div>
<SessionInfo userId={userId} /> <SessionInfo userId={userId} />

View file

@ -19,12 +19,12 @@ import RoomVisibility from '../../molecules/room-visibility/RoomVisibility';
import RoomAliases from '../../molecules/room-aliases/RoomAliases'; import RoomAliases from '../../molecules/room-aliases/RoomAliases';
import RoomHistoryVisibility from '../../molecules/room-history-visibility/RoomHistoryVisibility'; import RoomHistoryVisibility from '../../molecules/room-history-visibility/RoomHistoryVisibility';
import RoomEncryption from '../../molecules/room-encryption/RoomEncryption'; import RoomEncryption from '../../molecules/room-encryption/RoomEncryption';
import RoomPermissions from '../../molecules/room-permissions/RoomPermissions';
import SettingsIC from '../../../../public/res/ic/outlined/settings.svg'; import SettingsIC from '../../../../public/res/ic/outlined/settings.svg';
import SearchIC from '../../../../public/res/ic/outlined/search.svg'; import SearchIC from '../../../../public/res/ic/outlined/search.svg';
import ShieldUserIC from '../../../../public/res/ic/outlined/shield-user.svg'; import ShieldUserIC from '../../../../public/res/ic/outlined/shield-user.svg';
import LockIC from '../../../../public/res/ic/outlined/lock.svg'; import LockIC from '../../../../public/res/ic/outlined/lock.svg';
import InfoIC from '../../../../public/res/ic/outlined/info.svg';
import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg'; import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg';
import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg'; import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg';
@ -35,7 +35,6 @@ const tabText = {
SEARCH: 'Search', SEARCH: 'Search',
PERMISSIONS: 'Permissions', PERMISSIONS: 'Permissions',
SECURITY: 'Security', SECURITY: 'Security',
ADVANCED: 'Advanced',
}; };
const tabItems = [{ const tabItems = [{
@ -54,10 +53,6 @@ const tabItems = [{
iconSrc: LockIC, iconSrc: LockIC,
text: tabText.SECURITY, text: tabText.SECURITY,
disabled: false, disabled: false,
}, {
iconSrc: InfoIC,
text: tabText.ADVANCED,
disabled: false,
}]; }];
function GeneralSettings({ roomId }) { function GeneralSettings({ roomId }) {
@ -156,6 +151,7 @@ function RoomSettings({ roomId }) {
/> />
<div className="room-settings__cards-wrapper"> <div className="room-settings__cards-wrapper">
{selectedTab.text === tabText.GENERAL && <GeneralSettings roomId={roomId} />} {selectedTab.text === tabText.GENERAL && <GeneralSettings roomId={roomId} />}
{selectedTab.text === tabText.PERMISSIONS && <RoomPermissions roomId={roomId} />}
{selectedTab.text === tabText.SECURITY && <SecuritySettings roomId={roomId} />} {selectedTab.text === tabText.SECURITY && <SecuritySettings roomId={roomId} />}
</div> </div>
</div> </div>

View file

@ -32,16 +32,20 @@
padding: 0 var(--sp-normal); padding: 0 var(--sp-normal);
@include dir.side(padding, var(--sp-normal), var(--sp-extra-tight)); @include dir.side(padding, var(--sp-normal), var(--sp-extra-tight));
} }
}
&__card { .room-settings__card {
margin: var(--sp-normal) 0; margin: var(--sp-normal) 0;
background-color: var(--bg-surface); background-color: var(--bg-surface);
border-radius: var(--bo-radius); border-radius: var(--bo-radius);
box-shadow: var(--bs-surface-border); box-shadow: var(--bs-surface-border);
overflow: hidden; overflow: hidden;
& > .context-menu__header:first-child { & > .context-menu__header:first-child {
margin-top: 2px; margin-top: 2px;
}
} }
} }
.room-settings .room-permissions__card {
@extend .room-settings__card;
}