Add ability to change power level in profile viewer
Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
parent
3f39fd487f
commit
12f2eed5b3
3 changed files with 73 additions and 9 deletions
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue