TelegramPWA/src/components/mediaViewer/MediaViewerActions.tsx

201 lines
5.2 KiB
TypeScript

import React, {
FC,
memo,
useCallback,
useMemo,
} from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiMessage } from '../../api/types';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { getMessageMediaHash } from '../../modules/helpers';
import useLang from '../../hooks/useLang';
import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress';
import { selectIsDownloading } from '../../modules/selectors';
import { pick } from '../../util/iteratees';
import Button from '../ui/Button';
import DropdownMenu from '../ui/DropdownMenu';
import MenuItem from '../ui/MenuItem';
import ProgressSpinner from '../ui/ProgressSpinner';
import './MediaViewerActions.scss';
type StateProps = {
isDownloading: boolean;
};
type OwnProps = {
mediaData?: string;
isVideo: boolean;
isZoomed: boolean;
message?: ApiMessage;
fileName?: string;
isAvatar?: boolean;
onCloseMediaViewer: NoneToVoidFunction;
onForward: NoneToVoidFunction;
onZoomToggle: NoneToVoidFunction;
};
type DispatchProps = Pick<GlobalActions, 'downloadMessageMedia' | 'cancelMessageMediaDownload'>;
const MediaViewerActions: FC<OwnProps & StateProps & DispatchProps> = ({
mediaData,
isVideo,
isZoomed,
message,
fileName,
isAvatar,
isDownloading,
onCloseMediaViewer,
onForward,
onZoomToggle,
downloadMessageMedia,
cancelMessageMediaDownload,
}) => {
const { loadProgress: downloadProgress } = useMediaWithLoadProgress(
message && getMessageMediaHash(message, 'download'),
!isDownloading,
);
const handleDownloadClick = useCallback(() => {
if (isDownloading) {
cancelMessageMediaDownload({ message });
} else {
downloadMessageMedia({ message });
}
}, [cancelMessageMediaDownload, downloadMessageMedia, isDownloading, message]);
const lang = useLang();
const MenuButton: FC<{ onTrigger: () => void; isOpen?: boolean }> = useMemo(() => {
return ({ onTrigger, isOpen }) => (
<Button
round
size="smaller"
color="translucent"
className={isOpen ? 'active' : undefined}
onClick={onTrigger}
ariaLabel="More actions"
>
<i className="icon-more" />
</Button>
);
}, []);
if (IS_SINGLE_COLUMN_LAYOUT) {
return (
<div className="MediaViewerActions-mobile">
<DropdownMenu
trigger={MenuButton}
positionX="right"
>
{!isAvatar && (
<MenuItem
icon="forward"
onClick={onForward}
>
{lang('Forward')}
</MenuItem>
)}
{isVideo ? (
<MenuItem
icon={isDownloading ? 'close' : 'download'}
onClick={handleDownloadClick}
>
{isDownloading ? `${Math.round(downloadProgress * 100)}% Downloading...` : 'Download'}
</MenuItem>
) : (
<MenuItem
icon="download"
href={mediaData}
download={fileName}
>
{lang('AccActionDownload')}
</MenuItem>
)}
</DropdownMenu>
{isDownloading && <ProgressSpinner progress={downloadProgress} size="s" noCross />}
</div>
);
}
return (
<div className="MediaViewerActions">
{!isAvatar && (
<>
<Button
round
size="smaller"
color="translucent-white"
ariaLabel={lang('Forward')}
onClick={onForward}
>
<i className="icon-forward" />
</Button>
</>
)}
{isVideo ? (
<Button
round
size="smaller"
color="translucent-white"
ariaLabel={lang('AccActionDownload')}
onClick={handleDownloadClick}
>
{isDownloading ? (
<ProgressSpinner progress={downloadProgress} size="s" onClick={handleDownloadClick} />
) : (
<i className="icon-download" />
)}
</Button>
) : (
<Button
href={mediaData}
download={fileName}
round
size="smaller"
color="translucent-white"
ariaLabel={lang('AccActionDownload')}
>
<i className="icon-download" />
</Button>
)}
<Button
round
size="smaller"
color="translucent-white"
ariaLabel={isZoomed ? 'Zoom Out' : 'Zoom In'}
onClick={onZoomToggle}
>
<i className={isZoomed ? 'icon-zoom-out' : 'icon-zoom-in'} />
</Button>
<Button
round
size="smaller"
color="translucent-white"
ariaLabel={lang('Close')}
onClick={onCloseMediaViewer}
>
<i className="icon-close" />
</Button>
</div>
);
};
export default memo(withGlobal<OwnProps>(
(global, { message }): StateProps => {
const isDownloading = message ? selectIsDownloading(global, message) : false;
return {
isDownloading,
};
},
(setGlobal, actions): DispatchProps => pick(actions, [
'downloadMessageMedia',
'cancelMessageMediaDownload',
]),
)(MediaViewerActions));