diff --git a/src/components/views/spaces/SpacePanel.tsx b/src/components/views/spaces/SpacePanel.tsx index 27f097e9d4..2e3bfd157a 100644 --- a/src/components/views/spaces/SpacePanel.tsx +++ b/src/components/views/spaces/SpacePanel.tsx @@ -14,18 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { useEffect, useState } from "react"; +import React, { Dispatch, ReactNode, SetStateAction, useEffect, useState } from "react"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import classNames from "classnames"; import { Room } from "matrix-js-sdk/src/models/room"; -import {_t} from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import RoomAvatar from "../avatars/RoomAvatar"; -import {useContextMenu} from "../../structures/ContextMenu"; +import { useContextMenu } from "../../structures/ContextMenu"; import SpaceCreateMenu from "./SpaceCreateMenu"; -import {SpaceItem} from "./SpaceTreeLevel"; +import { SpaceItem } from "./SpaceTreeLevel"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; -import {useEventEmitter} from "../../../hooks/useEventEmitter"; +import { useEventEmitter } from "../../../hooks/useEventEmitter"; import SpaceStore, { UPDATE_INVITED_SPACES, UPDATE_SELECTED_SPACE, @@ -38,9 +38,9 @@ import { RovingAccessibleTooltipButton, RovingTabIndexProvider, } from "../../../accessibility/RovingTabIndex"; -import {Key} from "../../../Keyboard"; -import {RoomNotificationStateStore} from "../../../stores/notifications/RoomNotificationStateStore"; -import {NotificationState} from "../../../stores/notifications/NotificationState"; +import { Key } from "../../../Keyboard"; +import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; +import { NotificationState } from "../../../stores/notifications/NotificationState"; interface IButtonProps { space?: Room; @@ -121,11 +121,62 @@ const useSpaces = (): [Room[], Room[], Room | null] => { return [invites, spaces, activeSpace]; }; +interface IInnerSpacePanelProps { + children?: ReactNode; + isPanelCollapsed: boolean; + setPanelCollapsed: Dispatch>; +} + +// Optimisation based on https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/droppable.md#recommended-droppable--performance-optimisation +const InnerSpacePanel = React.memo(({ children, isPanelCollapsed, setPanelCollapsed }) => { + const [invites, spaces, activeSpace] = useSpaces(); + const activeSpaces = activeSpace ? [activeSpace] : []; + + return
+ SpaceStore.instance.setActiveSpace(null)} + selected={!activeSpace} + tooltip={_t("All rooms")} + notificationState={RoomNotificationStateStore.instance.globalState} + isNarrow={isPanelCollapsed} + /> + { invites.map(s => ( + setPanelCollapsed(false)} + /> + )) } + { spaces.map((s, i) => ( + + {(provided, snapshot) => ( + setPanelCollapsed(false)} + /> + )} + + )) } + { children } +
; +}); + const SpacePanel = () => { // We don't need the handle as we position the menu in a constant location // eslint-disable-next-line @typescript-eslint/no-unused-vars const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu(); - const [invites, spaces, activeSpace] = useSpaces(); const [isPanelCollapsed, setPanelCollapsed] = useState(true); useEffect(() => { @@ -134,10 +185,6 @@ const SpacePanel = () => { } }, [isPanelCollapsed]); // eslint-disable-line react-hooks/exhaustive-deps - const newClasses = classNames("mx_SpaceButton_new", { - mx_SpaceButton_newCancel: menuDisplayed, - }); - let contextMenu = null; if (menuDisplayed) { contextMenu = ; @@ -204,7 +251,11 @@ const SpacePanel = () => { } }; - const activeSpaces = activeSpace ? [activeSpace] : []; + const onNewClick = menuDisplayed ? closeMenu : () => { + if (!isPanelCollapsed) setPanelCollapsed(true); + openMenu(); + }; + return ( { if (!result.destination) return; // dropped outside the list @@ -226,59 +277,26 @@ const SpacePanel = () => { pointerEvents: "none", } : undefined} > -
- SpaceStore.instance.setActiveSpace(null)} - selected={!activeSpace} - tooltip={_t("All rooms")} - notificationState={RoomNotificationStateStore.instance.globalState} - isNarrow={isPanelCollapsed} - /> - { invites.map(s => ( - setPanelCollapsed(false)} - /> - )) } - { spaces.map((s, i) => ( - - {(provided, snapshot) => ( - setPanelCollapsed(false)} - /> - )} - - )) } + { provided.placeholder } -
+ + { - if (!isPanelCollapsed) setPanelCollapsed(true); - openMenu(); - }} + onClick={onNewClick} isNarrow={isPanelCollapsed} /> )} setPanelCollapsed(!isPanelCollapsed)} title={isPanelCollapsed ? _t("Expand space panel") : _t("Collapse space panel")} />