diff --git a/src/app/molecules/room-optons/RoomOptions.jsx b/src/app/molecules/room-optons/RoomOptions.jsx new file mode 100644 index 0000000..83a9482 --- /dev/null +++ b/src/app/molecules/room-optons/RoomOptions.jsx @@ -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 ( + <> + {twemojify(`Options for ${initMatrix.matrixClient.getRoom(roomId)?.name}`)} + Mark as read + + Invite + + Leave + Notification + + + ); +} + +RoomOptions.defaultProps = { + afterOptionSelect: null, +}; + +RoomOptions.propTypes = { + roomId: PropTypes.string.isRequired, + afterOptionSelect: PropTypes.func, +}; + +export default RoomOptions; diff --git a/src/app/organisms/navigation/Selector.jsx b/src/app/organisms/navigation/Selector.jsx index 80a0357..507dc42 100644 --- a/src/app/organisms/navigation/Selector.jsx +++ b/src/app/organisms/navigation/Selector.jsx @@ -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) => , + ); + }; + 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 index a131ddc..0000000 --- a/src/app/organisms/room-optons/RoomOptions.jsx +++ /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 ( - ( - <> - {twemojify(`Options for ${initMatrix.matrixClient.getRoom(roomId)?.name}`)} - { - handleMarkAsRead(); toggleMenu(); - }} - > - Mark as read - - { - handleInviteClick(); toggleMenu(); - }} - > - Invite - - handleLeaveClick(toggleMenu)}>Leave - Notification - {roomId && } - - )} - render={(toggleMenu) => ( - - )} - /> - ); -} - -export default RoomOptions; diff --git a/src/app/organisms/room/RoomViewHeader.jsx b/src/app/organisms/room/RoomViewHeader.jsx index 847eb6e..9c12a7e 100644 --- a/src/app/organisms/room/RoomViewHeader.jsx +++ b/src/app/organisms/room/RoomViewHeader.jsx @@ -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) => , + ); + }; + return (