Files
cinny/src/app/molecules/room-permissions/RoomPermissions.jsx
Ajay Bura e2228a18c1 handle error in loading screen (#1823)
* handle client boot error in loading screen

* use sync state hook in client root

* add loading screen options

* removed extra condition in loading finish

* add sync connection status bar
2024-07-22 20:47:19 +10:00

283 lines
8.7 KiB
JavaScript

import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import './RoomPermissions.scss';
import { getPowerLabel } from '../../../util/matrixUtil';
import { openReusableContextMenu } from '../../../client/action/navigation';
import { getEventCords } from '../../../util/common';
import Text from '../../atoms/text/Text';
import Button from '../../atoms/button/Button';
import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
import PowerLevelSelector from '../power-level-selector/PowerLevelSelector';
import SettingTile from '../setting-tile/SettingTile';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import { useForceUpdate } from '../../hooks/useForceUpdate';
import { useMatrixClient } from '../../hooks/useMatrixClient';
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,
},
'm.reaction': {
parent: 'events',
name: 'Send reactions',
description: 'Set minimum power level to send reactions 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', 'm.reaction', '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 useRoomStateUpdate(roomId) {
const [, forceUpdate] = useForceUpdate();
const mx = useMatrixClient();
useEffect(() => {
const handleStateEvent = (event) => {
if (event.getRoomId() !== roomId) return;
forceUpdate();
};
mx.on('RoomState.events', handleStateEvent);
return () => {
mx.removeListener('RoomState.events', handleStateEvent);
};
}, [mx, roomId]);
}
function RoomPermissions({ roomId }) {
useRoomStateUpdate(roomId);
const mx = useMatrixClient();
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());
const myPowerLevel = room.getMember(mx.getUserId())?.powerLevel ?? 100;
const handlePowerSelector = (e, permKey, parentKey, powerLevel) => {
const handlePowerLevelChange = (newPowerLevel) => {
if (powerLevel === newPowerLevel) return;
const newPermissions = { ...permissions };
if (parentKey) {
newPermissions[parentKey] = {
...permissions[parentKey],
[permKey]: newPowerLevel,
};
} else if (permKey === 'notifications') {
newPermissions[permKey] = {
...permissions[permKey],
room: newPowerLevel,
};
} else {
newPermissions[permKey] = newPowerLevel;
}
mx.sendStateEvent(roomId, 'm.room.power_levels', newPermissions);
};
openReusableContextMenu(
'bottom',
getEventCords(e, '.btn-surface'),
(closeMenu) => (
<PowerLevelSelector
value={powerLevel}
max={myPowerLevel}
onSelect={(pl) => {
closeMenu();
handlePowerLevelChange(pl);
}}
/>
),
);
};
const permsGroups = room.isSpaceRoom() ? spacePermsGroups : roomPermsGroups;
return (
<div className="room-permissions">
{
Object.keys(permsGroups).map((groupKey) => {
const groupedPermKeys = permsGroups[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 === undefined) 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
onClick={
canChangePermission
? (e) => handlePowerSelector(e, permKey, permInfo.parent, powerLevel)
: null
}
iconSrc={canChangePermission ? ChevronBottomIC : null}
>
<Text variant="b2">
{`${getPowerLabel(powerLevel) || 'Member'} - ${powerLevel}`}
</Text>
</Button>
)}
/>
);
})
}
</div>
);
})
}
</div>
);
}
RoomPermissions.propTypes = {
roomId: PropTypes.string.isRequired,
};
export default RoomPermissions;