Refactor room options
Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
parent
ba6d9d0c23
commit
60c44da974
8 changed files with 90 additions and 148 deletions
67
src/app/molecules/room-optons/RoomOptions.jsx
Normal file
67
src/app/molecules/room-optons/RoomOptions.jsx
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { twemojify } from '../../../util/twemojify';
|
||||||
|
|
||||||
|
import initMatrix from '../../../client/initMatrix';
|
||||||
|
import { openInviteUser } from '../../../client/action/navigation';
|
||||||
|
import * as roomActions from '../../../client/action/room';
|
||||||
|
|
||||||
|
import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu';
|
||||||
|
import RoomNotification from '../room-notification/RoomNotification';
|
||||||
|
|
||||||
|
import TickMarkIC from '../../../../public/res/ic/outlined/tick-mark.svg';
|
||||||
|
import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg';
|
||||||
|
import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg';
|
||||||
|
|
||||||
|
function RoomOptions({ roomId, afterOptionSelect }) {
|
||||||
|
const mx = initMatrix.matrixClient;
|
||||||
|
const room = mx.getRoom(roomId);
|
||||||
|
const canInvite = room?.canInvite(mx.getUserId());
|
||||||
|
|
||||||
|
const handleMarkAsRead = () => {
|
||||||
|
afterOptionSelect();
|
||||||
|
if (!room) return;
|
||||||
|
const events = room.getLiveTimeline().getEvents();
|
||||||
|
mx.sendReadReceipt(events[events.length - 1]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInviteClick = () => {
|
||||||
|
openInviteUser(roomId);
|
||||||
|
afterOptionSelect();
|
||||||
|
};
|
||||||
|
const handleLeaveClick = () => {
|
||||||
|
if (confirm('Are you really want to leave this room?')) {
|
||||||
|
roomActions.leave(roomId);
|
||||||
|
afterOptionSelect();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MenuHeader>{twemojify(`Options for ${initMatrix.matrixClient.getRoom(roomId)?.name}`)}</MenuHeader>
|
||||||
|
<MenuItem iconSrc={TickMarkIC} onClick={handleMarkAsRead}>Mark as read</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
iconSrc={AddUserIC}
|
||||||
|
onClick={handleInviteClick}
|
||||||
|
disabled={!canInvite}
|
||||||
|
>
|
||||||
|
Invite
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem iconSrc={LeaveArrowIC} variant="danger" onClick={handleLeaveClick}>Leave</MenuItem>
|
||||||
|
<MenuHeader>Notification</MenuHeader>
|
||||||
|
<RoomNotification roomId={roomId} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomOptions.defaultProps = {
|
||||||
|
afterOptionSelect: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
RoomOptions.propTypes = {
|
||||||
|
roomId: PropTypes.string.isRequired,
|
||||||
|
afterOptionSelect: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RoomOptions;
|
|
@ -4,12 +4,13 @@ import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import initMatrix from '../../../client/initMatrix';
|
import initMatrix from '../../../client/initMatrix';
|
||||||
import navigation from '../../../client/state/navigation';
|
import navigation from '../../../client/state/navigation';
|
||||||
import { openRoomOptions } from '../../../client/action/navigation';
|
import { openReusableContextMenu } from '../../../client/action/navigation';
|
||||||
import { createSpaceShortcut, deleteSpaceShortcut } from '../../../client/action/room';
|
import { createSpaceShortcut, deleteSpaceShortcut } from '../../../client/action/room';
|
||||||
import { getEventCords, abbreviateNumber } from '../../../util/common';
|
import { getEventCords, abbreviateNumber } from '../../../util/common';
|
||||||
|
|
||||||
import IconButton from '../../atoms/button/IconButton';
|
import IconButton from '../../atoms/button/IconButton';
|
||||||
import RoomSelector from '../../molecules/room-selector/RoomSelector';
|
import RoomSelector from '../../molecules/room-selector/RoomSelector';
|
||||||
|
import RoomOptions from '../../molecules/room-optons/RoomOptions';
|
||||||
|
|
||||||
import HashIC from '../../../../public/res/ic/outlined/hash.svg';
|
import HashIC from '../../../../public/res/ic/outlined/hash.svg';
|
||||||
import HashGlobeIC from '../../../../public/res/ic/outlined/hash-globe.svg';
|
import HashGlobeIC from '../../../../public/res/ic/outlined/hash-globe.svg';
|
||||||
|
@ -49,6 +50,15 @@ function Selector({
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const openRoomOptions = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
openReusableContextMenu(
|
||||||
|
'right',
|
||||||
|
getEventCords(e, '.room-selector'),
|
||||||
|
(closeMenu) => <RoomOptions roomId={roomId} afterOptionSelect={closeMenu} />,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const joinRuleToIconSrc = (joinRule) => ({
|
const joinRuleToIconSrc = (joinRule) => ({
|
||||||
restricted: () => (room.isSpaceRoom() ? SpaceIC : HashIC),
|
restricted: () => (room.isSpaceRoom() ? SpaceIC : HashIC),
|
||||||
invite: () => (room.isSpaceRoom() ? SpaceLockIC : HashLockIC),
|
invite: () => (room.isSpaceRoom() ? SpaceLockIC : HashLockIC),
|
||||||
|
@ -102,7 +112,7 @@ function Selector({
|
||||||
tooltip="Options"
|
tooltip="Options"
|
||||||
tooltipPlacement="right"
|
tooltipPlacement="right"
|
||||||
src={VerticalMenuIC}
|
src={VerticalMenuIC}
|
||||||
onClick={(e) => openRoomOptions(getEventCords(e), roomId)}
|
onClick={openRoomOptions}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
import React, { useEffect, useRef } from 'react';
|
|
||||||
|
|
||||||
import { twemojify } from '../../../util/twemojify';
|
|
||||||
|
|
||||||
import initMatrix from '../../../client/initMatrix';
|
|
||||||
import cons from '../../../client/state/cons';
|
|
||||||
import navigation from '../../../client/state/navigation';
|
|
||||||
import { openInviteUser } from '../../../client/action/navigation';
|
|
||||||
import * as roomActions from '../../../client/action/room';
|
|
||||||
|
|
||||||
import ContextMenu, { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu';
|
|
||||||
import RoomNotification from '../../molecules/room-notification/RoomNotification';
|
|
||||||
|
|
||||||
import TickMarkIC from '../../../../public/res/ic/outlined/tick-mark.svg';
|
|
||||||
import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg';
|
|
||||||
import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg';
|
|
||||||
|
|
||||||
import { useForceUpdate } from '../../hooks/useForceUpdate';
|
|
||||||
|
|
||||||
let isRoomOptionVisible = false;
|
|
||||||
let roomId = null;
|
|
||||||
function RoomOptions() {
|
|
||||||
const openerRef = useRef(null);
|
|
||||||
const [, forceUpdate] = useForceUpdate();
|
|
||||||
|
|
||||||
function openRoomOptions(cords, rId) {
|
|
||||||
if (roomId !== null || isRoomOptionVisible) {
|
|
||||||
roomId = null;
|
|
||||||
if (cords.detail === 0) openerRef.current.click();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
openerRef.current.style.transform = `translate(${cords.x}px, ${cords.y}px)`;
|
|
||||||
roomId = rId;
|
|
||||||
openerRef.current.click();
|
|
||||||
forceUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
const afterRoomOptionsToggle = (isVisible) => {
|
|
||||||
isRoomOptionVisible = isVisible;
|
|
||||||
if (!isVisible) {
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!isRoomOptionVisible) roomId = null;
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
navigation.on(cons.events.navigation.ROOMOPTIONS_OPENED, openRoomOptions);
|
|
||||||
return () => {
|
|
||||||
navigation.on(cons.events.navigation.ROOMOPTIONS_OPENED, openRoomOptions);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleMarkAsRead = () => {
|
|
||||||
const mx = initMatrix.matrixClient;
|
|
||||||
const room = mx.getRoom(roomId);
|
|
||||||
if (!room) return;
|
|
||||||
const events = room.getLiveTimeline().getEvents();
|
|
||||||
mx.sendReadReceipt(events[events.length - 1]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInviteClick = () => openInviteUser(roomId);
|
|
||||||
const handleLeaveClick = (toggleMenu) => {
|
|
||||||
if (confirm('Are you really want to leave this room?')) {
|
|
||||||
roomActions.leave(roomId);
|
|
||||||
toggleMenu();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const mx = initMatrix.matrixClient;
|
|
||||||
const room = mx.getRoom(roomId);
|
|
||||||
const canInvite = room?.canInvite(mx.getUserId());
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ContextMenu
|
|
||||||
afterToggle={afterRoomOptionsToggle}
|
|
||||||
maxWidth={298}
|
|
||||||
content={(toggleMenu) => (
|
|
||||||
<>
|
|
||||||
<MenuHeader>{twemojify(`Options for ${initMatrix.matrixClient.getRoom(roomId)?.name}`)}</MenuHeader>
|
|
||||||
<MenuItem
|
|
||||||
iconSrc={TickMarkIC}
|
|
||||||
onClick={() => {
|
|
||||||
handleMarkAsRead(); toggleMenu();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Mark as read
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem
|
|
||||||
disabled={!canInvite}
|
|
||||||
iconSrc={AddUserIC}
|
|
||||||
onClick={() => {
|
|
||||||
handleInviteClick(); toggleMenu();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Invite
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem iconSrc={LeaveArrowIC} variant="danger" onClick={() => handleLeaveClick(toggleMenu)}>Leave</MenuItem>
|
|
||||||
<MenuHeader>Notification</MenuHeader>
|
|
||||||
{roomId && <RoomNotification roomId={roomId} />}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
render={(toggleMenu) => (
|
|
||||||
<input
|
|
||||||
ref={openerRef}
|
|
||||||
onClick={toggleMenu}
|
|
||||||
type="button"
|
|
||||||
style={{
|
|
||||||
width: '32px',
|
|
||||||
height: '32px',
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
position: 'absolute',
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
padding: 0,
|
|
||||||
border: 'none',
|
|
||||||
visibility: 'hidden',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default RoomOptions;
|
|
|
@ -8,7 +8,7 @@ import { blurOnBubbling } from '../../atoms/button/script';
|
||||||
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 { toggleRoomSettings, openRoomOptions } from '../../../client/action/navigation';
|
import { toggleRoomSettings, openReusableContextMenu } from '../../../client/action/navigation';
|
||||||
import { togglePeopleDrawer } from '../../../client/action/settings';
|
import { togglePeopleDrawer } from '../../../client/action/settings';
|
||||||
import colorMXID from '../../../util/colorMXID';
|
import colorMXID from '../../../util/colorMXID';
|
||||||
import { getEventCords } from '../../../util/common';
|
import { getEventCords } from '../../../util/common';
|
||||||
|
@ -18,6 +18,7 @@ import RawIcon from '../../atoms/system-icons/RawIcon';
|
||||||
import IconButton from '../../atoms/button/IconButton';
|
import IconButton from '../../atoms/button/IconButton';
|
||||||
import Header, { TitleWrapper } from '../../atoms/header/Header';
|
import Header, { TitleWrapper } from '../../atoms/header/Header';
|
||||||
import Avatar from '../../atoms/avatar/Avatar';
|
import Avatar from '../../atoms/avatar/Avatar';
|
||||||
|
import RoomOptions from '../../molecules/room-optons/RoomOptions';
|
||||||
|
|
||||||
import UserIC from '../../../../public/res/ic/outlined/user.svg';
|
import UserIC from '../../../../public/res/ic/outlined/user.svg';
|
||||||
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
|
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
|
||||||
|
@ -60,6 +61,14 @@ function RoomViewHeader({ roomId }) {
|
||||||
};
|
};
|
||||||
}, [roomId]);
|
}, [roomId]);
|
||||||
|
|
||||||
|
const openRoomOptions = (e) => {
|
||||||
|
openReusableContextMenu(
|
||||||
|
'bottom',
|
||||||
|
getEventCords(e, '.ic-btn'),
|
||||||
|
(closeMenu) => <RoomOptions roomId={roomId} afterOptionSelect={closeMenu} />,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Header>
|
<Header>
|
||||||
<button
|
<button
|
||||||
|
@ -77,7 +86,7 @@ function RoomViewHeader({ roomId }) {
|
||||||
</button>
|
</button>
|
||||||
<IconButton onClick={togglePeopleDrawer} tooltip="People" src={UserIC} />
|
<IconButton onClick={togglePeopleDrawer} tooltip="People" src={UserIC} />
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={(e) => openRoomOptions(getEventCords(e), roomId)}
|
onClick={openRoomOptions}
|
||||||
tooltip="Options"
|
tooltip="Options"
|
||||||
src={VerticalMenuIC}
|
src={VerticalMenuIC}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -9,7 +9,6 @@ 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';
|
||||||
import EmojiBoardOpener from '../../organisms/emoji-board/EmojiBoardOpener';
|
import EmojiBoardOpener from '../../organisms/emoji-board/EmojiBoardOpener';
|
||||||
import RoomOptions from '../../organisms/room-optons/RoomOptions';
|
|
||||||
import logout from '../../../client/action/logout';
|
import logout from '../../../client/action/logout';
|
||||||
|
|
||||||
import initMatrix from '../../../client/initMatrix';
|
import initMatrix from '../../../client/initMatrix';
|
||||||
|
@ -66,7 +65,6 @@ function Client() {
|
||||||
<Windows />
|
<Windows />
|
||||||
<Dialogs />
|
<Dialogs />
|
||||||
<EmojiBoardOpener />
|
<EmojiBoardOpener />
|
||||||
<RoomOptions />
|
|
||||||
<ReusableContextMenu />
|
<ReusableContextMenu />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -87,14 +87,6 @@ export function openReadReceipts(roomId, userIds) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openRoomOptions(cords, roomId) {
|
|
||||||
appDispatcher.dispatch({
|
|
||||||
type: cons.actions.navigation.OPEN_ROOMOPTIONS,
|
|
||||||
cords,
|
|
||||||
roomId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function replyTo(userId, eventId, body) {
|
export function replyTo(userId, eventId, body) {
|
||||||
appDispatcher.dispatch({
|
appDispatcher.dispatch({
|
||||||
type: cons.actions.navigation.CLICK_REPLY_TO,
|
type: cons.actions.navigation.CLICK_REPLY_TO,
|
||||||
|
|
|
@ -39,7 +39,6 @@ const cons = {
|
||||||
OPEN_SETTINGS: 'OPEN_SETTINGS',
|
OPEN_SETTINGS: 'OPEN_SETTINGS',
|
||||||
OPEN_EMOJIBOARD: 'OPEN_EMOJIBOARD',
|
OPEN_EMOJIBOARD: 'OPEN_EMOJIBOARD',
|
||||||
OPEN_READRECEIPTS: 'OPEN_READRECEIPTS',
|
OPEN_READRECEIPTS: 'OPEN_READRECEIPTS',
|
||||||
OPEN_ROOMOPTIONS: 'OPEN_ROOMOPTIONS',
|
|
||||||
CLICK_REPLY_TO: 'CLICK_REPLY_TO',
|
CLICK_REPLY_TO: 'CLICK_REPLY_TO',
|
||||||
OPEN_SEARCH: 'OPEN_SEARCH',
|
OPEN_SEARCH: 'OPEN_SEARCH',
|
||||||
OPEN_REUSABLE_CONTEXT_MENU: 'OPEN_REUSABLE_CONTEXT_MENU',
|
OPEN_REUSABLE_CONTEXT_MENU: 'OPEN_REUSABLE_CONTEXT_MENU',
|
||||||
|
@ -76,7 +75,6 @@ const cons = {
|
||||||
PROFILE_VIEWER_OPENED: 'PROFILE_VIEWER_OPENED',
|
PROFILE_VIEWER_OPENED: 'PROFILE_VIEWER_OPENED',
|
||||||
EMOJIBOARD_OPENED: 'EMOJIBOARD_OPENED',
|
EMOJIBOARD_OPENED: 'EMOJIBOARD_OPENED',
|
||||||
READRECEIPTS_OPENED: 'READRECEIPTS_OPENED',
|
READRECEIPTS_OPENED: 'READRECEIPTS_OPENED',
|
||||||
ROOMOPTIONS_OPENED: 'ROOMOPTIONS_OPENED',
|
|
||||||
REPLY_TO_CLICKED: 'REPLY_TO_CLICKED',
|
REPLY_TO_CLICKED: 'REPLY_TO_CLICKED',
|
||||||
SEARCH_OPENED: 'SEARCH_OPENED',
|
SEARCH_OPENED: 'SEARCH_OPENED',
|
||||||
REUSABLE_CONTEXT_MENU_OPENED: 'REUSABLE_CONTEXT_MENU_OPENED',
|
REUSABLE_CONTEXT_MENU_OPENED: 'REUSABLE_CONTEXT_MENU_OPENED',
|
||||||
|
|
|
@ -126,13 +126,6 @@ class Navigation extends EventEmitter {
|
||||||
action.userIds,
|
action.userIds,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[cons.actions.navigation.OPEN_ROOMOPTIONS]: () => {
|
|
||||||
this.emit(
|
|
||||||
cons.events.navigation.ROOMOPTIONS_OPENED,
|
|
||||||
action.cords,
|
|
||||||
action.roomId,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[cons.actions.navigation.CLICK_REPLY_TO]: () => {
|
[cons.actions.navigation.CLICK_REPLY_TO]: () => {
|
||||||
this.emit(
|
this.emit(
|
||||||
cons.events.navigation.REPLY_TO_CLICKED,
|
cons.events.navigation.REPLY_TO_CLICKED,
|
||||||
|
|
Loading…
Reference in a new issue