diff --git a/src/renderer/components/Avatar.tsx b/src/renderer/components/Avatar.tsx index aab44a8406..871aa0408a 100644 --- a/src/renderer/components/Avatar.tsx +++ b/src/renderer/components/Avatar.tsx @@ -4,7 +4,9 @@ import { useContext } from 'react' import classNames from 'classnames' import { ScreenContext } from '../contexts' import { Type } from '../backend-com' -import FullscreenMedia from './dialogs/FullscreenMedia' +import FullscreenMedia, { + NeighboringMediaMode, +} from './dialogs/FullscreenMedia' import { T } from '@deltachat/jsonrpc-client' export function QRAvatar() { @@ -109,6 +111,7 @@ export function ClickForFullscreenAvatarWrapper(props: { fileMime: 'image/x', file: props.filename, } as T.Message, + neighboringMedia: NeighboringMediaMode.Off, }) }} style={{ diff --git a/src/renderer/components/Gallery.tsx b/src/renderer/components/Gallery.tsx index 9cdd9680b9..dc1ed32f71 100644 --- a/src/renderer/components/Gallery.tsx +++ b/src/renderer/components/Gallery.tsx @@ -15,16 +15,25 @@ import AutoSizer from 'react-virtualized-auto-sizer' import { FixedSizeGrid } from 'react-window' import SettingsStoreInstance, { SettingsStoreState } from '../stores/settings' import moment from 'moment' +import FullscreenMedia, { + NeighboringMediaMode, +} from './dialogs/FullscreenMedia' const log = getLogger('renderer/Gallery') type MediaTabKey = 'images' | 'video' | 'audio' | 'files' | 'webxdc_apps' +type GalleryElement = ( + props: GalleryAttachmentElementProps & { + openFullscreenMedia: (message: Type.Message) => void + } +) => JSX.Element + const MediaTabs: Readonly< { [key in MediaTabKey]: { values: Type.Viewtype[] - element: (props: GalleryAttachmentElementProps) => JSX.Element + element: GalleryElement } } > = { @@ -57,7 +66,7 @@ export default class Gallery extends Component< { id: MediaTabKey msgTypes: Type.Viewtype[] - element: (props: GalleryAttachmentElementProps) => JSX.Element + element: GalleryElement mediaMessageIds: number[] mediaLoadResult: Record loading: boolean @@ -186,6 +195,16 @@ export default class Gallery extends Component< } } + openFullscreenMedia(message: Type.Message) { + window.__openDialog(FullscreenMedia, { + msg: message, + neighboringMedia: + this.props.chatId === 'all' + ? NeighboringMediaMode.Global + : NeighboringMediaMode.Chat, + }) + } + render() { const { mediaMessageIds, @@ -354,6 +373,9 @@ export default class Gallery extends Component< ) diff --git a/src/renderer/components/attachment/mediaAttachment.tsx b/src/renderer/components/attachment/mediaAttachment.tsx index ba66870a49..9a8c57bb90 100644 --- a/src/renderer/components/attachment/mediaAttachment.tsx +++ b/src/renderer/components/attachment/mediaAttachment.tsx @@ -92,9 +92,6 @@ const getMediaActions = ( contextMenuFactory.bind(null, message, openDialog), openContextMenu ), - openFullscreenMedia: openDialog.bind(null, 'FullscreenMedia', { - msg: message, - }), downloadMedia: onDownload.bind(null, message), openInShell: openAttachmentInShell.bind(null, message), } @@ -143,7 +140,10 @@ export type GalleryAttachmentElementProps = { export function ImageAttachment({ msgId, load_result, -}: GalleryAttachmentElementProps) { + openFullscreenMedia, +}: GalleryAttachmentElementProps & { + openFullscreenMedia: (message: Type.Message) => void +}) { const screenContext = useContext(ScreenContext) const tx = window.static_translate @@ -162,18 +162,20 @@ export function ImageAttachment({ ) } else { const message = load_result - const { - openContextMenu, - openFullscreenMedia, - openInShell, - } = getMediaActions(screenContext, message) + const { openContextMenu, openInShell } = getMediaActions( + screenContext, + message + ) const { file, fileMime } = message const hasSupportedFormat = isImage(fileMime) const isBroken = !file || !hasSupportedFormat + return (
{isBroken ? ( @@ -193,7 +195,10 @@ export function ImageAttachment({ export function VideoAttachment({ msgId, load_result, -}: GalleryAttachmentElementProps) { + openFullscreenMedia, +}: GalleryAttachmentElementProps & { + openFullscreenMedia: (message: Type.Message) => void +}) { const screenContext = useContext(ScreenContext) const tx = window.static_translate @@ -214,7 +219,7 @@ export function VideoAttachment({ const message = load_result const { openContextMenu, - openFullscreenMedia, + openInShell, } = getMediaActions(screenContext, message) const { file, fileMime } = message @@ -223,7 +228,9 @@ export function VideoAttachment({ return (
{isBroken ? ( diff --git a/src/renderer/components/attachment/messageAttachment.tsx b/src/renderer/components/attachment/messageAttachment.tsx index 6fa6ec65ff..986a65e49d 100644 --- a/src/renderer/components/attachment/messageAttachment.tsx +++ b/src/renderer/components/attachment/messageAttachment.tsx @@ -17,6 +17,9 @@ import { getDirection } from '../../../shared/util' import filesizeConverter from 'filesize' import { Type } from '../../backend-com' +import FullscreenMedia, { + NeighboringMediaMode, +} from '../dialogs/FullscreenMedia' // const MINIMUM_IMG_HEIGHT = 150 // const MAXIMUM_IMG_HEIGHT = 300 @@ -44,7 +47,10 @@ export default function Attachment({ if (message.viewType === 'Sticker') return ev.stopPropagation() if (isDisplayableByFullscreenMedia(message.fileMime)) { - openDialog('FullscreenMedia', { msg: message }) + openDialog(FullscreenMedia, { + msg: message, + neighboringMedia: NeighboringMediaMode.Chat, + }) } else { openAttachmentInShell(message) } diff --git a/src/renderer/components/dialogs/Edit-Group-Image.tsx b/src/renderer/components/dialogs/Edit-Group-Image.tsx index 0a726cb13b..997e8b936b 100644 --- a/src/renderer/components/dialogs/Edit-Group-Image.tsx +++ b/src/renderer/components/dialogs/Edit-Group-Image.tsx @@ -3,7 +3,7 @@ import React, { useContext } from 'react' import { ScreenContext } from '../../contexts' import { Avatar } from '../Avatar' import { useContextMenu } from '../ContextMenu' -import FullscreenMedia from './FullscreenMedia' +import FullscreenMedia, { NeighboringMediaMode } from './FullscreenMedia' export const GroupImage = (props: { groupImage?: string | null @@ -31,6 +31,7 @@ export const GroupImage = (props: { fileMime: 'image/x', file: groupImage, } as T.Message, + neighboringMedia: NeighboringMediaMode.Off, }) const openContextMenu = useContextMenu([ diff --git a/src/renderer/components/dialogs/FullscreenMedia.tsx b/src/renderer/components/dialogs/FullscreenMedia.tsx index aa14c7e387..ac88b744f0 100644 --- a/src/renderer/components/dialogs/FullscreenMedia.tsx +++ b/src/renderer/components/dialogs/FullscreenMedia.tsx @@ -16,10 +16,18 @@ import { selectedAccountId } from '../../ScreenController' const log = getLogger('renderer/fullscreen_media') +export enum NeighboringMediaMode { + Chat, + Global, + Off, +} + export default function FullscreenMedia(props: { msg: Type.Message + neighboringMedia: NeighboringMediaMode onClose: DialogProps['onClose'] }) { + const accountId = selectedAccountId() const tx = window.static_translate const { onClose } = props @@ -35,6 +43,28 @@ export default function FullscreenMedia(props: { previous: false, next: false, }) + + const [mediaMessageList, setMediaMessageList] = useState([]) + useEffect(() => { + if (props.neighboringMedia === NeighboringMediaMode.Off) { + setMediaMessageList([]) + } else { + const { viewType, chatId } = props.msg + // workaround to get gifs and images into the same media list + let additionalViewType: Type.Viewtype | null = null + if (props.msg.viewType === 'Image') { + additionalViewType = 'Gif' + } else if (props.msg.viewType === 'Gif') { + additionalViewType = 'Image' + } + const scope = + props.neighboringMedia === NeighboringMediaMode.Global ? null : chatId + BackendRemote.rpc + .getChatMedia(accountId, scope, viewType, additionalViewType, null) + .then(setMediaMessageList) + } + }, [props.msg, props.neighboringMedia, accountId]) + const { file, fileMime } = msg if (!file) { @@ -130,15 +160,15 @@ export default function FullscreenMedia(props: { if (!msg.id) { return } - previousNextMessageId.current = await getNeighboringMedia( + previousNextMessageId.current = await getNeighboringMsgIds( msg.id, - msg.viewType + mediaMessageList ) setShowPrevNextMsgBtns({ previous: previousNextMessageId.current[0] !== null, next: previousNextMessageId.current[1] !== null, }) - }, [msg]) + }, [msg, mediaMessageList]) useEffect(() => { updatePreviousNextMessageId() @@ -235,25 +265,10 @@ export default function FullscreenMedia(props: { ) } -async function getNeighboringMedia( - messageId: number, - viewType: Type.Viewtype -): Promise<[previousMessageId: number | null, nextMessageId: number | null]> { - const accountId = selectedAccountId() - - // workaround to get gifs and images into the same media list - let additionalViewType: Type.Viewtype | null = null - if (viewType === 'Image') { - additionalViewType = 'Gif' - } else if (viewType === 'Gif') { - additionalViewType = 'Image' - } - - return await BackendRemote.rpc.getNeighboringChatMedia( - accountId, - messageId, - viewType, - additionalViewType, - null - ) +async function getNeighboringMsgIds(messageId: number, list: number[]) { + const index = list.indexOf(messageId) + return [list[index - 1] || null, list[index + 1] || null] as [ + previousMessageId: number | null, + nextMessageId: number | null + ] }