SVG: Ask before download (#3872)
This commit is contained in:
parent
f8c021b043
commit
bcb1a7ae26
@ -22,10 +22,13 @@ import { getDocumentExtension, getDocumentHasPreview } from './helpers/documentI
|
||||
|
||||
import useFlag from '../../hooks/useFlag';
|
||||
import { useIsIntersecting } from '../../hooks/useIntersectionObserver';
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
import useMedia from '../../hooks/useMedia';
|
||||
import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress';
|
||||
|
||||
import Checkbox from '../ui/Checkbox';
|
||||
import ConfirmDialog from '../ui/ConfirmDialog';
|
||||
import File from './File';
|
||||
|
||||
type OwnProps = {
|
||||
@ -42,12 +45,14 @@ type OwnProps = {
|
||||
sender?: string;
|
||||
autoLoadFileMaxSizeMb?: number;
|
||||
isDownloading?: boolean;
|
||||
shouldWarnAboutSvg?: boolean;
|
||||
onCancelUpload?: () => void;
|
||||
onMediaClick?: () => void;
|
||||
onDateClick?: (messageId: number, chatId: string) => void;
|
||||
};
|
||||
|
||||
const BYTES_PER_MB = 1024 * 1024;
|
||||
const SVG_EXTENSIONS = new Set(['svg', 'svgz']);
|
||||
|
||||
const Document: FC<OwnProps> = ({
|
||||
message,
|
||||
@ -62,16 +67,21 @@ const Document: FC<OwnProps> = ({
|
||||
sender,
|
||||
isSelected,
|
||||
isSelectable,
|
||||
shouldWarnAboutSvg,
|
||||
isDownloading,
|
||||
onCancelUpload,
|
||||
onMediaClick,
|
||||
onDateClick,
|
||||
isDownloading,
|
||||
}) => {
|
||||
const dispatch = getActions();
|
||||
const { cancelMessageMediaDownload, downloadMessageMedia, setSettingOption } = getActions();
|
||||
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
const lang = useLang();
|
||||
const [isSvgDialogOpen, openSvgDialog, closeSvgDialog] = useFlag();
|
||||
const [shouldNotWarnAboutSvg, setShouldNotWarnAboutSvg] = useState(false);
|
||||
|
||||
const document = message.content.document!;
|
||||
const { fileName, size, timestamp } = document;
|
||||
const extension = getDocumentExtension(document) || '';
|
||||
@ -110,6 +120,10 @@ const Document: FC<OwnProps> = ({
|
||||
SUPPORTED_VIDEO_CONTENT_TYPES.has(document.mimeType) || SUPPORTED_IMAGE_CONTENT_TYPES.has(document.mimeType)
|
||||
);
|
||||
|
||||
const handleDownload = useLastCallback(() => {
|
||||
downloadMessageMedia({ message });
|
||||
});
|
||||
|
||||
const handleClick = useLastCallback(() => {
|
||||
if (isUploading) {
|
||||
if (onCancelUpload) {
|
||||
@ -119,7 +133,7 @@ const Document: FC<OwnProps> = ({
|
||||
}
|
||||
|
||||
if (isDownloading) {
|
||||
dispatch.cancelMessageMediaDownload({ message });
|
||||
cancelMessageMediaDownload({ message });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -130,9 +144,21 @@ const Document: FC<OwnProps> = ({
|
||||
|
||||
if (withMediaViewer) {
|
||||
onMediaClick!();
|
||||
} else {
|
||||
dispatch.downloadMessageMedia({ message });
|
||||
return;
|
||||
}
|
||||
|
||||
if (SVG_EXTENSIONS.has(extension) && shouldWarnAboutSvg) {
|
||||
openSvgDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
handleDownload();
|
||||
});
|
||||
|
||||
const handleSvgConfirm = useLastCallback(() => {
|
||||
setSettingOption({ shouldWarnAboutSvg: !shouldNotWarnAboutSvg });
|
||||
closeSvgDialog();
|
||||
handleDownload();
|
||||
});
|
||||
|
||||
const handleDateClick = useLastCallback(() => {
|
||||
@ -140,26 +166,41 @@ const Document: FC<OwnProps> = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<File
|
||||
ref={ref}
|
||||
name={fileName}
|
||||
extension={extension}
|
||||
size={size}
|
||||
timestamp={withDate ? datetime || timestamp : undefined}
|
||||
thumbnailDataUri={thumbDataUri}
|
||||
previewData={localBlobUrl || previewData}
|
||||
smaller={smaller}
|
||||
isTransferring={isTransferring}
|
||||
isUploading={isUploading}
|
||||
transferProgress={transferProgress}
|
||||
className={className}
|
||||
sender={sender}
|
||||
isSelectable={isSelectable}
|
||||
isSelected={isSelected}
|
||||
actionIcon={withMediaViewer ? (isMessageDocumentVideo(message) ? 'play' : 'eye') : 'download'}
|
||||
onClick={handleClick}
|
||||
onDateClick={onDateClick ? handleDateClick : undefined}
|
||||
/>
|
||||
<>
|
||||
<File
|
||||
ref={ref}
|
||||
name={fileName}
|
||||
extension={extension}
|
||||
size={size}
|
||||
timestamp={withDate ? datetime || timestamp : undefined}
|
||||
thumbnailDataUri={thumbDataUri}
|
||||
previewData={localBlobUrl || previewData}
|
||||
smaller={smaller}
|
||||
isTransferring={isTransferring}
|
||||
isUploading={isUploading}
|
||||
transferProgress={transferProgress}
|
||||
className={className}
|
||||
sender={sender}
|
||||
isSelectable={isSelectable}
|
||||
isSelected={isSelected}
|
||||
actionIcon={withMediaViewer ? (isMessageDocumentVideo(message) ? 'play' : 'eye') : 'download'}
|
||||
onClick={handleClick}
|
||||
onDateClick={onDateClick ? handleDateClick : undefined}
|
||||
/>
|
||||
<ConfirmDialog
|
||||
isOpen={isSvgDialogOpen}
|
||||
onClose={closeSvgDialog}
|
||||
confirmHandler={handleSvgConfirm}
|
||||
>
|
||||
{lang('lng_launch_svg_warning')}
|
||||
<Checkbox
|
||||
className="dialog-checkbox"
|
||||
checked={shouldNotWarnAboutSvg}
|
||||
label={lang('lng_launch_exe_dont_ask')}
|
||||
onCheck={setShouldNotWarnAboutSvg}
|
||||
/>
|
||||
</ConfirmDialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -43,6 +43,7 @@ const FileResults: FC<OwnProps & StateProps> = ({
|
||||
globalMessagesByChatId,
|
||||
foundIds,
|
||||
activeDownloads,
|
||||
shouldWarnAboutSvg,
|
||||
}) => {
|
||||
const {
|
||||
searchMessagesGlobal,
|
||||
@ -117,6 +118,7 @@ const FileResults: FC<OwnProps & StateProps> = ({
|
||||
sender={getSenderName(lang, message, chatsById, usersById)}
|
||||
className="scroll-item"
|
||||
isDownloading={activeDownloads[message.chatId]?.ids?.includes(message.id)}
|
||||
shouldWarnAboutSvg={shouldWarnAboutSvg}
|
||||
observeIntersection={observeIntersectionForMedia}
|
||||
onDateClick={handleMessageFocus}
|
||||
/>
|
||||
|
||||
@ -16,6 +16,7 @@ export type StateProps = {
|
||||
searchChatId?: string;
|
||||
activeDownloads: TabState['activeDownloads']['byChatId'];
|
||||
isChatProtected?: boolean;
|
||||
shouldWarnAboutSvg?: boolean;
|
||||
};
|
||||
|
||||
export function createMapStateToProps(type: ApiGlobalMessageSearchType) {
|
||||
@ -48,6 +49,7 @@ export function createMapStateToProps(type: ApiGlobalMessageSearchType) {
|
||||
searchChatId: chatId,
|
||||
activeDownloads,
|
||||
isChatProtected: chatId ? selectChat(global, chatId)?.isProtected : undefined,
|
||||
shouldWarnAboutSvg: global.settings.byKey.shouldWarnAboutSvg,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@ -191,8 +191,8 @@ type OwnProps =
|
||||
appearanceOrder: number;
|
||||
isJustAdded: boolean;
|
||||
memoFirstUnreadIdRef: { current: number | undefined };
|
||||
onPinnedIntersectionChange: PinnedIntersectionChangedCallback;
|
||||
getIsMessageListReady: Signal<boolean>;
|
||||
onPinnedIntersectionChange: PinnedIntersectionChangedCallback;
|
||||
}
|
||||
& MessagePositionProperties;
|
||||
|
||||
@ -261,6 +261,7 @@ type StateProps = {
|
||||
withStickerEffects?: boolean;
|
||||
webPageStory?: ApiTypeStory;
|
||||
isConnected: boolean;
|
||||
shouldWarnAboutSvg?: boolean;
|
||||
};
|
||||
|
||||
type MetaPosition =
|
||||
@ -367,8 +368,9 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
withStickerEffects,
|
||||
webPageStory,
|
||||
isConnected,
|
||||
onPinnedIntersectionChange,
|
||||
getIsMessageListReady,
|
||||
shouldWarnAboutSvg,
|
||||
onPinnedIntersectionChange,
|
||||
}) => {
|
||||
const {
|
||||
toggleMessageSelection,
|
||||
@ -1094,6 +1096,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
onMediaClick={handleMediaClick}
|
||||
onCancelUpload={handleCancelUpload}
|
||||
isDownloading={isDownloading}
|
||||
shouldWarnAboutSvg={shouldWarnAboutSvg}
|
||||
/>
|
||||
)}
|
||||
{storyData && !isStoryMention && (
|
||||
@ -1584,6 +1587,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
withStickerEffects: selectPerformanceSettingsValue(global, 'stickerEffects'),
|
||||
webPageStory,
|
||||
isConnected,
|
||||
shouldWarnAboutSvg: global.settings.byKey.shouldWarnAboutSvg,
|
||||
...((canShowSender || isLocation) && { sender }),
|
||||
...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }),
|
||||
...(typeof uploadProgress === 'number' && { uploadProgress }),
|
||||
|
||||
@ -112,6 +112,7 @@ type StateProps = {
|
||||
activeDownloadIds?: number[];
|
||||
isChatProtected?: boolean;
|
||||
nextProfileTab?: ProfileTabType;
|
||||
shouldWarnAboutSvg?: boolean;
|
||||
};
|
||||
|
||||
const TABS = [
|
||||
@ -156,6 +157,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
||||
activeDownloadIds,
|
||||
isChatProtected,
|
||||
nextProfileTab,
|
||||
shouldWarnAboutSvg,
|
||||
}) => {
|
||||
const {
|
||||
setLocalMediaSearchType,
|
||||
@ -441,6 +443,7 @@ const Profile: FC<OwnProps & StateProps> = ({
|
||||
isDownloading={activeDownloadIds?.includes(id)}
|
||||
observeIntersection={observeIntersectionForMedia}
|
||||
onDateClick={handleMessageFocus}
|
||||
shouldWarnAboutSvg={shouldWarnAboutSvg}
|
||||
/>
|
||||
))
|
||||
) : resultType === 'links' ? (
|
||||
@ -646,6 +649,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
storyByIds,
|
||||
isChatProtected: chat?.isProtected,
|
||||
nextProfileTab: selectTabState(global).nextProfileTab,
|
||||
shouldWarnAboutSvg: global.settings.byKey.shouldWarnAboutSvg,
|
||||
...(hasMembersTab && members && { members, adminMembersById }),
|
||||
...(hasCommonChatsTab && user && { commonChatIds: user.commonChats?.ids }),
|
||||
};
|
||||
|
||||
@ -237,6 +237,7 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
|
||||
doNotTranslate: [],
|
||||
canDisplayChatInTitle: true,
|
||||
shouldAllowHttpTransport: true,
|
||||
shouldWarnAboutSvg: true,
|
||||
},
|
||||
themes: {
|
||||
light: {
|
||||
|
||||
@ -107,6 +107,7 @@ export interface ISettings extends NotifySettings, Record<string, any> {
|
||||
shouldAllowHttpTransport?: boolean;
|
||||
shouldCollectDebugLogs?: boolean;
|
||||
shouldDebugExportedSenders?: boolean;
|
||||
shouldWarnAboutSvg?: boolean;
|
||||
}
|
||||
|
||||
export interface ApiPrivacySettings {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user