message list image context menu
This commit is contained in:
parent
54536c1b03
commit
916c3b2f24
@ -1,7 +1,8 @@
|
|||||||
import moment from 'moment';
|
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 { Member, Message } from '../../../data-types';
|
||||||
import CombinedGuild from '../../../guild-combined';
|
import CombinedGuild from '../../../guild-combined';
|
||||||
|
import ImageContextMenu from '../../context-menus/context-menu-image';
|
||||||
import ImageOverlay from '../../overlays/overlay-image';
|
import ImageOverlay from '../../overlays/overlay-image';
|
||||||
import ElementsUtil from '../../require/elements-util';
|
import ElementsUtil from '../../require/elements-util';
|
||||||
import GuildSubscriptions from '../../require/guild-subscriptions';
|
import GuildSubscriptions from '../../require/guild-subscriptions';
|
||||||
@ -50,16 +51,38 @@ interface PreviewImageElementProps {
|
|||||||
const PreviewImageElement: FC<PreviewImageElementProps> = (props: PreviewImageElementProps) => {
|
const PreviewImageElement: FC<PreviewImageElementProps> = (props: PreviewImageElementProps) => {
|
||||||
const { guild, previewWidth, previewHeight, resourcePreviewId, resourceId, resourceName } = props;
|
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 (
|
||||||
|
<ImageContextMenu
|
||||||
|
relativeToPos={relativeToPos} close={close}
|
||||||
|
resourceName={resourceName} resourceBuff={previewResource.data} isPreview={true}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}, [ previewResource, relativeToPos, resourceName ]);
|
||||||
|
|
||||||
const openImageOverlay = useCallback(() => {
|
const openImageOverlay = useCallback(() => {
|
||||||
// Note: document here isn't 100% guaranteed (I think) but we should be getting rid of this eventually anyway
|
// Note: document here isn't 100% guaranteed (I think) but we should be getting rid of this eventually anyway
|
||||||
ElementsUtil.presentReactOverlay(document, <ImageOverlay guild={guild} resourceId={resourceId} resourceName={resourceName} />);
|
ElementsUtil.presentReactOverlay(document, <ImageOverlay guild={guild} resourceId={resourceId} resourceName={resourceName} />);
|
||||||
}, [ guild, resourceId, resourceName ]);
|
}, [ guild, resourceId, resourceName ]);
|
||||||
|
|
||||||
|
const onContextMenu = useCallback((event: MouseEvent<HTMLImageElement>) => {
|
||||||
|
setRelativeToPos({ x: event.clientX, y: event.clientY });
|
||||||
|
toggleContextMenu();
|
||||||
|
}, [ toggleContextMenu ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="content image" style={{ width: previewWidth, height: previewHeight }} onClick={openImageOverlay}>
|
<div className="content image" style={{ width: previewWidth, height: previewHeight }}>
|
||||||
<img src={imgSrc} alt={resourceName}/>
|
<img
|
||||||
|
src={previewImgSrc} alt={resourceName}
|
||||||
|
onClick={openImageOverlay} onContextMenu={onContextMenu}
|
||||||
|
/>
|
||||||
|
{contextMenu}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,7 @@ const ImageOverlay: FC<ImageOverlayProps> = (props: ImageOverlayProps) => {
|
|||||||
// TODO: Handle errors
|
// TODO: Handle errors
|
||||||
const rootRef = useRef<HTMLDivElement>(null);
|
const rootRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const [ resource, resourceError ] = GuildSubscriptions.useResourceSubscription(guild, resourceId);
|
const [ imgSrc, resource, resourceError ] = GuildSubscriptions.useSoftImageSrcResourceSubscription(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 [ relativeToPos, setRelativeToPos ] = useState<{ x: number, y: number }>({ x: 0, y: 0 });
|
const [ relativeToPos, setRelativeToPos ] = useState<{ x: number, y: number }>({ x: 0, y: 0 });
|
||||||
|
|
||||||
@ -54,7 +48,7 @@ const ImageOverlay: FC<ImageOverlayProps> = (props: ImageOverlayProps) => {
|
|||||||
return (
|
return (
|
||||||
<Overlay childRootRef={rootRef}>
|
<Overlay childRootRef={rootRef}>
|
||||||
<div ref={rootRef} className="content popup-image">
|
<div ref={rootRef} className="content popup-image">
|
||||||
<img src={resourceImgSrc} alt={resourceName} title={resourceName} onContextMenu={onContextMenu}></img>
|
<img src={imgSrc} alt={resourceName} title={resourceName} onContextMenu={onContextMenu}></img>
|
||||||
<div className="download">
|
<div className="download">
|
||||||
<div className="info">
|
<div className="info">
|
||||||
<div className="name">{resourceName}</div>
|
<div className="name">{resourceName}</div>
|
||||||
|
@ -574,20 +574,20 @@ export default class GuildSubscriptions {
|
|||||||
}, fetchResourceFunc);
|
}, fetchResourceFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static useSoftImageSrcResourceSubscription(guild: CombinedGuild, resourceId: string | null): [ imgSrc: string ] {
|
static useSoftImageSrcResourceSubscription(guild: CombinedGuild, resourceId: string | null): [ imgSrc: string, resource: Resource | null, fetchError: unknown | null ] {
|
||||||
const [ value, fetchError ] = GuildSubscriptions.useResourceSubscription(guild, resourceId);
|
const [ resource, fetchError ] = GuildSubscriptions.useResourceSubscription(guild, resourceId);
|
||||||
|
|
||||||
const [ imgSrc ] = ReactHelper.useOneTimeAsyncAction(
|
const [ imgSrc ] = ReactHelper.useOneTimeAsyncAction(
|
||||||
async () => {
|
async () => {
|
||||||
if (fetchError) return './img/error.png';
|
if (fetchError) return './img/error.png';
|
||||||
if (!value) return './img/loading.svg';
|
if (!resource) return './img/loading.svg';
|
||||||
return await ElementsUtil.getImageSrcFromBufferFailSoftly(value.data);
|
return await ElementsUtil.getImageSrcFromBufferFailSoftly(resource.data);
|
||||||
},
|
},
|
||||||
'./img/loading.svg',
|
'./img/loading.svg',
|
||||||
[ value, fetchError ]
|
[ resource, fetchError ]
|
||||||
);
|
);
|
||||||
|
|
||||||
return [ imgSrc ];
|
return [ imgSrc, resource, fetchError ];
|
||||||
}
|
}
|
||||||
|
|
||||||
static useChannelsSubscription(guild: CombinedGuild) {
|
static useChannelsSubscription(guild: CombinedGuild) {
|
||||||
|
@ -413,7 +413,7 @@ export default class ReactHelper {
|
|||||||
}, []);
|
}, []);
|
||||||
const contextMenu = useMemo(() => {
|
const contextMenu = useMemo(() => {
|
||||||
return createContextMenu(close);
|
return createContextMenu(close);
|
||||||
}, createContextMenuDeps);
|
}, [ close, ...createContextMenuDeps ]);
|
||||||
|
|
||||||
const toggle = useCallback(() => {
|
const toggle = useCallback(() => {
|
||||||
setIsOpen(oldIsOpen => !!contextMenu && !oldIsOpen);
|
setIsOpen(oldIsOpen => !!contextMenu && !oldIsOpen);
|
||||||
@ -421,7 +421,7 @@ export default class ReactHelper {
|
|||||||
const open = useCallback(() => {
|
const open = useCallback(() => {
|
||||||
setIsOpen(!!contextMenu);
|
setIsOpen(!!contextMenu);
|
||||||
}, [ contextMenu ]);
|
}, [ contextMenu ]);
|
||||||
|
|
||||||
return [ isOpen ? contextMenu : null, toggle, close, open, isOpen ];
|
return [ isOpen ? contextMenu : null, toggle, close, open, isOpen ];
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user