diff --git a/src/client/webapp/elements/lists/components/message-element.tsx b/src/client/webapp/elements/lists/components/message-element.tsx index 42dd3e0..bcaa4f7 100644 --- a/src/client/webapp/elements/lists/components/message-element.tsx +++ b/src/client/webapp/elements/lists/components/message-element.tsx @@ -1,7 +1,8 @@ import moment from 'moment'; -import React, { FC, useCallback, useMemo } from 'react'; +import React, { FC, MouseEvent, useCallback, useMemo, useState } from 'react'; import { Member, Message } from '../../../data-types'; import CombinedGuild from '../../../guild-combined'; +import ImageContextMenu from '../../context-menus/context-menu-image'; import ImageOverlay from '../../overlays/overlay-image'; import ElementsUtil from '../../require/elements-util'; import GuildSubscriptions from '../../require/guild-subscriptions'; @@ -50,16 +51,38 @@ interface PreviewImageElementProps { const PreviewImageElement: FC = (props: PreviewImageElementProps) => { const { guild, previewWidth, previewHeight, resourcePreviewId, resourceId, resourceName } = props; - const [ imgSrc ] = GuildSubscriptions.useSoftImageSrcResourceSubscription(guild, resourcePreviewId); + + // TODO: Handle resourceError + const [ previewImgSrc, previewResource, previewResourceError ] = GuildSubscriptions.useSoftImageSrcResourceSubscription(guild, resourcePreviewId); + + const [ relativeToPos, setRelativeToPos ] = useState<{ x: number, y: number }>({ x: 0, y: 0 }); + const [ contextMenu, toggleContextMenu ] = ReactHelper.useContextMenu((close: () => void) => { + if (!previewResource) return null; + return ( + + ) + }, [ previewResource, relativeToPos, resourceName ]); const openImageOverlay = useCallback(() => { // Note: document here isn't 100% guaranteed (I think) but we should be getting rid of this eventually anyway ElementsUtil.presentReactOverlay(document, ); }, [ guild, resourceId, resourceName ]); + const onContextMenu = useCallback((event: MouseEvent) => { + setRelativeToPos({ x: event.clientX, y: event.clientY }); + toggleContextMenu(); + }, [ toggleContextMenu ]); + return ( -
- {resourceName}/ +
+ {resourceName} + {contextMenu}
); } diff --git a/src/client/webapp/elements/overlays/overlay-image.tsx b/src/client/webapp/elements/overlays/overlay-image.tsx index c4fc55a..c7ac808 100644 --- a/src/client/webapp/elements/overlays/overlay-image.tsx +++ b/src/client/webapp/elements/overlays/overlay-image.tsx @@ -24,13 +24,7 @@ const ImageOverlay: FC = (props: ImageOverlayProps) => { // TODO: Handle errors const rootRef = useRef(null); - const [ resource, resourceError ] = GuildSubscriptions.useResourceSubscription(guild, resourceId); - // Note: We want this customization here since we need the resource buffer. - const [ resourceImgSrc ] = ReactHelper.useOneTimeAsyncAction( - async () => await ElementsUtil.getImageSrcFromBufferFailSoftly(resource?.data ?? null), - './img/loading.svg', - [ guild, resource ] - ); + const [ imgSrc, resource, resourceError ] = GuildSubscriptions.useSoftImageSrcResourceSubscription(guild, resourceId); const [ relativeToPos, setRelativeToPos ] = useState<{ x: number, y: number }>({ x: 0, y: 0 }); @@ -54,7 +48,7 @@ const ImageOverlay: FC = (props: ImageOverlayProps) => { return (
- {resourceName} + {resourceName}
{resourceName}
diff --git a/src/client/webapp/elements/require/guild-subscriptions.ts b/src/client/webapp/elements/require/guild-subscriptions.ts index 7489b04..7412674 100644 --- a/src/client/webapp/elements/require/guild-subscriptions.ts +++ b/src/client/webapp/elements/require/guild-subscriptions.ts @@ -574,20 +574,20 @@ export default class GuildSubscriptions { }, fetchResourceFunc); } - static useSoftImageSrcResourceSubscription(guild: CombinedGuild, resourceId: string | null): [ imgSrc: string ] { - const [ value, fetchError ] = GuildSubscriptions.useResourceSubscription(guild, resourceId); + static useSoftImageSrcResourceSubscription(guild: CombinedGuild, resourceId: string | null): [ imgSrc: string, resource: Resource | null, fetchError: unknown | null ] { + const [ resource, fetchError ] = GuildSubscriptions.useResourceSubscription(guild, resourceId); const [ imgSrc ] = ReactHelper.useOneTimeAsyncAction( async () => { if (fetchError) return './img/error.png'; - if (!value) return './img/loading.svg'; - return await ElementsUtil.getImageSrcFromBufferFailSoftly(value.data); + if (!resource) return './img/loading.svg'; + return await ElementsUtil.getImageSrcFromBufferFailSoftly(resource.data); }, './img/loading.svg', - [ value, fetchError ] + [ resource, fetchError ] ); - return [ imgSrc ]; + return [ imgSrc, resource, fetchError ]; } static useChannelsSubscription(guild: CombinedGuild) { diff --git a/src/client/webapp/elements/require/react-helper.ts b/src/client/webapp/elements/require/react-helper.ts index 2c629d0..15088bc 100644 --- a/src/client/webapp/elements/require/react-helper.ts +++ b/src/client/webapp/elements/require/react-helper.ts @@ -413,7 +413,7 @@ export default class ReactHelper { }, []); const contextMenu = useMemo(() => { return createContextMenu(close); - }, createContextMenuDeps); + }, [ close, ...createContextMenuDeps ]); const toggle = useCallback(() => { setIsOpen(oldIsOpen => !!contextMenu && !oldIsOpen); @@ -421,7 +421,7 @@ export default class ReactHelper { const open = useCallback(() => { setIsOpen(!!contextMenu); }, [ contextMenu ]); - + return [ isOpen ? contextMenu : null, toggle, close, open, isOpen ]; } } \ No newline at end of file