Add ability to change power level in profile viewer

Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
Ajay Bura 2022-01-12 13:57:13 +05:30
parent 3f39fd487f
commit 12f2eed5b3
3 changed files with 73 additions and 9 deletions

View file

@ -7,10 +7,11 @@ import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix'; import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons'; import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation'; import navigation from '../../../client/state/navigation';
import { selectRoom } from '../../../client/action/navigation'; import { selectRoom, openReusableContextMenu } from '../../../client/action/navigation';
import * as roomActions from '../../../client/action/room'; import * as roomActions from '../../../client/action/room';
import { getUsername, getUsernameOfRoomMember, getPowerLabel } from '../../../util/matrixUtil'; import { getUsername, getUsernameOfRoomMember, getPowerLabel } from '../../../util/matrixUtil';
import { getEventCords } from '../../../util/common';
import colorMXID from '../../../util/colorMXID'; import colorMXID from '../../../util/colorMXID';
import Text from '../../atoms/text/Text'; import Text from '../../atoms/text/Text';
@ -18,6 +19,7 @@ import Chip from '../../atoms/chip/Chip';
import IconButton from '../../atoms/button/IconButton'; import IconButton from '../../atoms/button/IconButton';
import Avatar from '../../atoms/avatar/Avatar'; import Avatar from '../../atoms/avatar/Avatar';
import Button from '../../atoms/button/Button'; import Button from '../../atoms/button/Button';
import PowerLevelSelector from '../../molecules/power-level-selector/PowerLevelSelector';
import Dialog from '../../molecules/dialog/Dialog'; import Dialog from '../../molecules/dialog/Dialog';
import SettingTile from '../../molecules/setting-tile/SettingTile'; import SettingTile from '../../molecules/setting-tile/SettingTile';
@ -25,6 +27,8 @@ import ShieldEmptyIC from '../../../../public/res/ic/outlined/shield-empty.svg';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg'; import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg'; import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import { useForceUpdate } from '../../hooks/useForceUpdate';
function SessionInfo({ userId }) { function SessionInfo({ userId }) {
const [devices, setDevices] = useState(null); const [devices, setDevices] = useState(null);
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
@ -230,6 +234,7 @@ function ProfileViewer() {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [roomId, setRoomId] = useState(null); const [roomId, setRoomId] = useState(null);
const [userId, setUserId] = useState(null); const [userId, setUserId] = useState(null);
const [, forceUpdate] = useForceUpdate();
const mx = initMatrix.matrixClient; const mx = initMatrix.matrixClient;
const room = roomId ? mx.getRoom(roomId) : null; const room = roomId ? mx.getRoom(roomId) : null;
@ -240,19 +245,30 @@ function ProfileViewer() {
else username = getUsername(userId); else username = getUsername(userId);
} }
function loadProfile(uId, rId) { useEffect(() => {
const loadProfile = (uId, rId) => {
setIsOpen(true); setIsOpen(true);
setUserId(uId); setUserId(uId);
setRoomId(rId); setRoomId(rId);
} };
useEffect(() => {
navigation.on(cons.events.navigation.PROFILE_VIEWER_OPENED, loadProfile); navigation.on(cons.events.navigation.PROFILE_VIEWER_OPENED, loadProfile);
return () => { return () => {
navigation.removeListener(cons.events.navigation.PROFILE_VIEWER_OPENED, loadProfile); navigation.removeListener(cons.events.navigation.PROFILE_VIEWER_OPENED, loadProfile);
}; };
}, []); }, []);
useEffect(() => {
const handlePowerLevelChange = (mEvent, member) => {
if (mEvent.getRoomId() === roomId && member.userId === userId) {
forceUpdate();
}
};
mx.on('RoomMember.powerLevel', handlePowerLevelChange);
return () => {
mx.removeListener('RoomMember.powerLevel', handlePowerLevelChange);
};
}, [roomId, userId]);
const handleAfterClose = () => { const handleAfterClose = () => {
setUserId(null); setUserId(null);
setRoomId(null); setRoomId(null);
@ -261,8 +277,40 @@ 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 powerLevel = member.powerLevel || 0;
const canChangeRole = room.currentState.maySendEvent('m.room.power_levels', mx.getUserId()); const myPowerLevel = room.getMember(mx.getUserId())?.powerLevel || 0;
const canChangeRole = (
room.currentState.maySendEvent('m.room.power_levels', mx.getUserId())
&& (powerLevel < myPowerLevel || userId === mx.getUserId())
);
const handleChangePowerLevel = (newPowerLevel) => {
if (newPowerLevel === powerLevel) return;
if (newPowerLevel === myPowerLevel
? confirm('You will not be able to undo this change as you are promoting the user to have the same power level as yourself. Are you sure?')
: true
) {
roomActions.setPowerLevel(roomId, userId, newPowerLevel);
}
};
const handlePowerSelector = (e) => {
openReusableContextMenu(
'bottom',
getEventCords(e, '.btn-surface'),
(closeMenu) => (
<PowerLevelSelector
value={powerLevel}
max={myPowerLevel}
onSelect={(pl) => {
closeMenu();
handleChangePowerLevel(pl);
}}
/>
),
);
};
return ( return (
<div className="profile-viewer"> <div className="profile-viewer">
@ -279,7 +327,10 @@ 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}> <Button
onClick={canChangeRole ? handlePowerSelector : null}
iconSrc={canChangeRole ? ChevronBottomIC : null}
>
{`${getPowerLabel(powerLevel) || 'Member'} - ${powerLevel}`} {`${getPowerLabel(powerLevel) || 'Member'} - ${powerLevel}`}
</Button> </Button>
</div> </div>

View file

@ -4,6 +4,7 @@ import './Client.scss';
import Text from '../../atoms/text/Text'; import Text from '../../atoms/text/Text';
import Spinner from '../../atoms/spinner/Spinner'; import Spinner from '../../atoms/spinner/Spinner';
import Navigation from '../../organisms/navigation/Navigation'; import Navigation from '../../organisms/navigation/Navigation';
import ReusableContextMenu from '../../atoms/context-menu/ReusableContextMenu';
import Room from '../../organisms/room/Room'; import Room from '../../organisms/room/Room';
import Windows from '../../organisms/pw/Windows'; import Windows from '../../organisms/pw/Windows';
import Dialogs from '../../organisms/pw/Dialogs'; import Dialogs from '../../organisms/pw/Dialogs';
@ -66,6 +67,7 @@ function Client() {
<Dialogs /> <Dialogs />
<EmojiBoardOpener /> <EmojiBoardOpener />
<RoomOptions /> <RoomOptions />
<ReusableContextMenu />
</div> </div>
); );
} }

View file

@ -199,6 +199,16 @@ async function kick(roomId, userId) {
return result; return result;
} }
async function setPowerLevel(roomId, userId, powerLevel) {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const powerlevelEvent = room.currentState.getStateEvents('m.room.power_levels')[0];
const result = await mx.setPowerLevel(roomId, userId, powerLevel, powerlevelEvent);
return result;
}
function createSpaceShortcut(roomId) { function createSpaceShortcut(roomId) {
appDispatcher.dispatch({ appDispatcher.dispatch({
type: cons.actions.room.CREATE_SPACE_SHORTCUT, type: cons.actions.room.CREATE_SPACE_SHORTCUT,
@ -216,5 +226,6 @@ function deleteSpaceShortcut(roomId) {
export { export {
join, leave, join, leave,
create, invite, kick, create, invite, kick,
setPowerLevel,
createSpaceShortcut, deleteSpaceShortcut, createSpaceShortcut, deleteSpaceShortcut,
}; };