Refactor room options
authorAjay Bura <ajbura@gmail.com>
Thu, 13 Jan 2022 13:00:43 +0000 (18:30 +0530)
committerAjay Bura <ajbura@gmail.com>
Thu, 13 Jan 2022 13:00:43 +0000 (18:30 +0530)
Signed-off-by: Ajay Bura <ajbura@gmail.com>
src/app/molecules/room-optons/RoomOptions.jsx [new file with mode: 0644]
src/app/organisms/navigation/Selector.jsx
src/app/organisms/room-optons/RoomOptions.jsx [deleted file]
src/app/organisms/room/RoomViewHeader.jsx
src/app/templates/client/Client.jsx
src/client/action/navigation.js
src/client/state/cons.js
src/client/state/navigation.js

diff --git a/src/app/molecules/room-optons/RoomOptions.jsx b/src/app/molecules/room-optons/RoomOptions.jsx
new file mode 100644 (file)
index 0000000..83a9482
--- /dev/null
@@ -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;
index 80a035743c92254dc07a4749feb65175d3c6e2e7..507dc4258b9502a4b767fa9253274479e82f6387 100644 (file)
@@ -4,12 +4,13 @@ import PropTypes from 'prop-types';
 
 import initMatrix from '../../../client/initMatrix';
 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 { getEventCords, abbreviateNumber } from '../../../util/common';
 
 import IconButton from '../../atoms/button/IconButton';
 import RoomSelector from '../../molecules/room-selector/RoomSelector';
+import RoomOptions from '../../molecules/room-optons/RoomOptions';
 
 import HashIC from '../../../../public/res/ic/outlined/hash.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) => ({
     restricted: () => (room.isSpaceRoom() ? SpaceIC : HashIC),
     invite: () => (room.isSpaceRoom() ? SpaceLockIC : HashLockIC),
@@ -102,7 +112,7 @@ function Selector({
           tooltip="Options"
           tooltipPlacement="right"
           src={VerticalMenuIC}
-          onClick={(e) => openRoomOptions(getEventCords(e), roomId)}
+          onClick={openRoomOptions}
         />
       )}
     />
diff --git a/src/app/organisms/room-optons/RoomOptions.jsx b/src/app/organisms/room-optons/RoomOptions.jsx
deleted file mode 100644 (file)
index a131ddc..0000000
+++ /dev/null
@@ -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;
index 847eb6ea1525e1d46137734750e21b29d7cd8559..9c12a7e753a42fa8ef3ae55d7294a04c608bc344 100644 (file)
@@ -8,7 +8,7 @@ import { blurOnBubbling } from '../../atoms/button/script';
 import initMatrix from '../../../client/initMatrix';
 import cons from '../../../client/state/cons';
 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 colorMXID from '../../../util/colorMXID';
 import { getEventCords } from '../../../util/common';
@@ -18,6 +18,7 @@ import RawIcon from '../../atoms/system-icons/RawIcon';
 import IconButton from '../../atoms/button/IconButton';
 import Header, { TitleWrapper } from '../../atoms/header/Header';
 import Avatar from '../../atoms/avatar/Avatar';
+import RoomOptions from '../../molecules/room-optons/RoomOptions';
 
 import UserIC from '../../../../public/res/ic/outlined/user.svg';
 import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
@@ -60,6 +61,14 @@ function RoomViewHeader({ roomId }) {
     };
   }, [roomId]);
 
+  const openRoomOptions = (e) => {
+    openReusableContextMenu(
+      'bottom',
+      getEventCords(e, '.ic-btn'),
+      (closeMenu) => <RoomOptions roomId={roomId} afterOptionSelect={closeMenu} />,
+    );
+  };
+
   return (
     <Header>
       <button
@@ -77,7 +86,7 @@ function RoomViewHeader({ roomId }) {
       </button>
       <IconButton onClick={togglePeopleDrawer} tooltip="People" src={UserIC} />
       <IconButton
-        onClick={(e) => openRoomOptions(getEventCords(e), roomId)}
+        onClick={openRoomOptions}
         tooltip="Options"
         src={VerticalMenuIC}
       />
index 3ec7f8dd783bf62875c548e1e2893686e4ff0ef5..6130a186fd5544af1678684e8254e82491198521 100644 (file)
@@ -9,7 +9,6 @@ import Room from '../../organisms/room/Room';
 import Windows from '../../organisms/pw/Windows';
 import Dialogs from '../../organisms/pw/Dialogs';
 import EmojiBoardOpener from '../../organisms/emoji-board/EmojiBoardOpener';
-import RoomOptions from '../../organisms/room-optons/RoomOptions';
 import logout from '../../../client/action/logout';
 
 import initMatrix from '../../../client/initMatrix';
@@ -66,7 +65,6 @@ function Client() {
       <Windows />
       <Dialogs />
       <EmojiBoardOpener />
-      <RoomOptions />
       <ReusableContextMenu />
     </div>
   );
index d61ea0be31787ded14f3930621224c2618be6de8..377a6158631497daa6141d944bfc8e57c2de6650 100644 (file)
@@ -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) {
   appDispatcher.dispatch({
     type: cons.actions.navigation.CLICK_REPLY_TO,
index aa49f152302090e7a65e514a588cbc8df4d81308..c0314269e1327713c627aec5a9c4c9af10fe2d67 100644 (file)
@@ -39,7 +39,6 @@ const cons = {
       OPEN_SETTINGS: 'OPEN_SETTINGS',
       OPEN_EMOJIBOARD: 'OPEN_EMOJIBOARD',
       OPEN_READRECEIPTS: 'OPEN_READRECEIPTS',
-      OPEN_ROOMOPTIONS: 'OPEN_ROOMOPTIONS',
       CLICK_REPLY_TO: 'CLICK_REPLY_TO',
       OPEN_SEARCH: 'OPEN_SEARCH',
       OPEN_REUSABLE_CONTEXT_MENU: 'OPEN_REUSABLE_CONTEXT_MENU',
@@ -76,7 +75,6 @@ const cons = {
       PROFILE_VIEWER_OPENED: 'PROFILE_VIEWER_OPENED',
       EMOJIBOARD_OPENED: 'EMOJIBOARD_OPENED',
       READRECEIPTS_OPENED: 'READRECEIPTS_OPENED',
-      ROOMOPTIONS_OPENED: 'ROOMOPTIONS_OPENED',
       REPLY_TO_CLICKED: 'REPLY_TO_CLICKED',
       SEARCH_OPENED: 'SEARCH_OPENED',
       REUSABLE_CONTEXT_MENU_OPENED: 'REUSABLE_CONTEXT_MENU_OPENED',
index c22035b1d15b81f690a47ca76d504a226f610c6a..674449f24103109f268427090e6bbf59ff8126ea 100644 (file)
@@ -126,13 +126,6 @@ class Navigation extends EventEmitter {
           action.userIds,
         );
       },
-      [cons.actions.navigation.OPEN_ROOMOPTIONS]: () => {
-        this.emit(
-          cons.events.navigation.ROOMOPTIONS_OPENED,
-          action.cords,
-          action.roomId,
-        );
-      },
       [cons.actions.navigation.CLICK_REPLY_TO]: () => {
         this.emit(
           cons.events.navigation.REPLY_TO_CLICKED,