From f7433c23be5cc974ff1a205c7631ee066c503e7a Mon Sep 17 00:00:00 2001 From: Michael Peters Date: Sun, 26 Dec 2021 13:41:17 -0600 Subject: [PATCH] split off context-menu into sub-functional component --- src/client/webapp/actions.ts | 23 ---- src/client/webapp/elements/channel.tsx | 54 -------- .../context-menus/components/context-menu.tsx | 42 ------ .../contexts/components/context-menu.tsx | 31 +++++ .../elements/contexts/components/context.tsx | 28 ++++ .../context-menu-connection-info.tsx | 2 +- .../context-menu-guild-title.tsx | 0 .../context-menu-image.tsx | 0 .../webapp/elements/guild-list-guild.tsx | 5 - .../lists/components/message-element.tsx | 2 +- .../elements/overlays/overlay-image.tsx | 2 +- .../webapp/elements/require/react-helper.ts | 27 ++++ .../elements/sections/connection-info.tsx | 2 +- .../webapp/elements/sections/guild-title.tsx | 2 +- src/client/webapp/preload.ts | 29 +--- src/client/webapp/styles/channel-list.scss | 4 - src/client/webapp/ui.ts | 125 +----------------- 17 files changed, 94 insertions(+), 284 deletions(-) delete mode 100644 src/client/webapp/elements/channel.tsx delete mode 100644 src/client/webapp/elements/context-menus/components/context-menu.tsx create mode 100644 src/client/webapp/elements/contexts/components/context-menu.tsx create mode 100644 src/client/webapp/elements/contexts/components/context.tsx rename src/client/webapp/elements/{context-menus => contexts}/context-menu-connection-info.tsx (97%) rename src/client/webapp/elements/{context-menus => contexts}/context-menu-guild-title.tsx (100%) rename src/client/webapp/elements/{context-menus => contexts}/context-menu-image.tsx (100%) diff --git a/src/client/webapp/actions.ts b/src/client/webapp/actions.ts index d157933..f2cc076 100644 --- a/src/client/webapp/actions.ts +++ b/src/client/webapp/actions.ts @@ -20,27 +20,4 @@ export default class Actions { ui.setActiveConnection(guild, { id: null, avatarResourceId: null, displayName: 'Error', status: 'Error', privileges: [], roleName: null, roleColor: null, rolePriority: null }); } } - - static async fetchAndUpdateChannels(q: Q, ui: UI, guild: CombinedGuild) { - await Util.withPotentialErrorWarnOnCancel(q, { - taskFunc: async () => { - if (ui.activeGuild === null || ui.activeGuild.id !== guild.id) return; - const channels = await guild.fetchChannels(); - await ui.setChannels(guild, channels); - if (ui.activeGuild === null || ui.activeGuild.id !== guild.id) return; - if (ui.activeChannel === null) { - // click on the first channel in the list if no channel is active yet - const element = q.$_('#channel-list .channel'); - if (element) { - element.click(); - } - } - }, - errorIndicatorAddFunc: async (errorIndicatorElement) => { - await ui.setChannelsErrorIndicator(guild, errorIndicatorElement); - }, - errorContainer: q.$('#channel-list'), - errorMessage: 'Error fetching channels' - }); - } } diff --git a/src/client/webapp/elements/channel.tsx b/src/client/webapp/elements/channel.tsx deleted file mode 100644 index a1ab02b..0000000 --- a/src/client/webapp/elements/channel.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import ReactHelper from './require/react-helper'; - -import ElementsUtil from './require/elements-util'; -import BaseElements from './require/base-elements'; -import { Channel } from '../data-types'; -import UI from '../ui'; -import Q from '../q-module'; -import CombinedGuild from '../guild-combined'; -import ChannelOverlay from './overlays/overlay-channel'; - -export default function createChannel(document: Document, q: Q, ui: UI, guild: CombinedGuild, channel: Channel) { - const element = ReactHelper.createElementFromJSX( -
-
{BaseElements.TEXT_CHANNEL_ICON}
-
{channel.name}
-
{BaseElements.COG}
-
- ); - - element.addEventListener('click', async () => { - if (element.classList.contains('active')) return; - await ui.setActiveChannel(guild, channel); - q.$('#text-input').focus(); - }); - - const modifyContextElement = q.create({ class: 'context', content: { - class: 'above', content: [ - { class: 'content text', content: 'Modify Channel' }, - { class: 'tab', content: BaseElements.Q_TAB_BELOW } - ] - }}) as HTMLElement; - - q.$$$(element, '.modify').addEventListener('click', async (e) => { - e.stopPropagation(); - if (modifyContextElement.parentElement) { - modifyContextElement.parentElement.removeChild(modifyContextElement); - } - ElementsUtil.presentReactOverlay(document, ); - }); - - q.$$$(element, '.modify').addEventListener('mouseenter', () => { - document.body.appendChild(modifyContextElement); - ElementsUtil.alignContextElement(modifyContextElement, q.$$$(element, '.modify'), { bottom: 'top', centerX: 'centerX' }); - }); - - q.$$$(element, '.modify').addEventListener('mouseleave', () => { - if (modifyContextElement.parentElement) { - modifyContextElement.parentElement.removeChild(modifyContextElement); - } - }); - - return element; -} diff --git a/src/client/webapp/elements/context-menus/components/context-menu.tsx b/src/client/webapp/elements/context-menus/components/context-menu.tsx deleted file mode 100644 index cece528..0000000 --- a/src/client/webapp/elements/context-menus/components/context-menu.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { FC, ReactNode, RefObject, useEffect, useMemo, useRef, useState } from 'react'; -import { ShouldNeverHappenError } from '../../../data-types'; -import ElementsUtil, { IAlignment } from '../../require/elements-util'; -import ReactHelper from '../../require/react-helper'; - -export interface ContextMenuProps { - relativeToRef?: RefObject; - relativeToPos?: { x: number, y: number }; - alignment: IAlignment; - children: ReactNode; - close: () => void; -} - -const ContextMenu: FC = (props: ContextMenuProps) => { - const { relativeToRef, relativeToPos, alignment, children, close } = props; - - const rootRef = useRef(null); - - const [ aligned, setAligned ] = useState(false); - - ReactHelper.useCloseWhenClickedOutsideEffect(rootRef, close); - - useEffect(() => { - if (!rootRef.current) return; - const relativeTo = (relativeToRef && relativeToRef.current) ?? relativeToPos ?? null; - if (!relativeTo) throw new ShouldNeverHappenError('invalid context menu props'); - ElementsUtil.alignContextElement(rootRef.current, relativeTo, alignment); - setAligned(true); - }, [ rootRef, relativeToRef, relativeToPos ]); - - const contextClass = useMemo(() => { - return 'context react' + (aligned ? ' aligned' : ''); - }, [ aligned ]); - - return ( -
-
{children}
-
- ); -} - -export default ContextMenu; diff --git a/src/client/webapp/elements/contexts/components/context-menu.tsx b/src/client/webapp/elements/contexts/components/context-menu.tsx new file mode 100644 index 0000000..3cfc238 --- /dev/null +++ b/src/client/webapp/elements/contexts/components/context-menu.tsx @@ -0,0 +1,31 @@ +import React, { FC, ReactNode, RefObject, useRef } from 'react' +import { IAlignment } from '../../require/elements-util'; +import ReactHelper from '../../require/react-helper'; +import Context from './context'; + +export interface ContextMenuProps { + relativeToRef?: RefObject; + relativeToPos?: { x: number, y: number }; + alignment: IAlignment; + children: ReactNode; + close: () => void; +} + +// Automatically closes when clicked outside of and includes a