Settings / Data & Storage: More auto-load settings (#1522)
This commit is contained in:
parent
bd914a9024
commit
e9b02557f4
@ -1,5 +1,5 @@
|
|||||||
import React, {
|
import React, {
|
||||||
FC, useCallback, memo, useRef,
|
FC, useCallback, memo, useRef, useEffect, useState,
|
||||||
} from '../../lib/teact/teact';
|
} from '../../lib/teact/teact';
|
||||||
import { getDispatch } from '../../lib/teact/teactn';
|
import { getDispatch } from '../../lib/teact/teactn';
|
||||||
|
|
||||||
@ -15,6 +15,7 @@ import {
|
|||||||
import { ObserveFn, useIsIntersecting } from '../../hooks/useIntersectionObserver';
|
import { ObserveFn, useIsIntersecting } from '../../hooks/useIntersectionObserver';
|
||||||
import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress';
|
import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress';
|
||||||
import useMedia from '../../hooks/useMedia';
|
import useMedia from '../../hooks/useMedia';
|
||||||
|
import useFlag from '../../hooks/useFlag';
|
||||||
|
|
||||||
import File from './File';
|
import File from './File';
|
||||||
|
|
||||||
@ -24,21 +25,27 @@ type OwnProps = {
|
|||||||
smaller?: boolean;
|
smaller?: boolean;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
isSelectable?: boolean;
|
isSelectable?: boolean;
|
||||||
|
canAutoLoad?: boolean;
|
||||||
uploadProgress?: number;
|
uploadProgress?: number;
|
||||||
withDate?: boolean;
|
withDate?: boolean;
|
||||||
datetime?: number;
|
datetime?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
sender?: string;
|
sender?: string;
|
||||||
|
autoLoadFileMaxSizeMb?: number;
|
||||||
isDownloading: boolean;
|
isDownloading: boolean;
|
||||||
onCancelUpload?: () => void;
|
onCancelUpload?: () => void;
|
||||||
onMediaClick?: () => void;
|
onMediaClick?: () => void;
|
||||||
onDateClick?: (messageId: number, chatId: string) => void;
|
onDateClick?: (messageId: number, chatId: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const BYTES_PER_MB = 1024 * 1024;
|
||||||
|
|
||||||
const Document: FC<OwnProps> = ({
|
const Document: FC<OwnProps> = ({
|
||||||
message,
|
message,
|
||||||
observeIntersection,
|
observeIntersection,
|
||||||
smaller,
|
smaller,
|
||||||
|
canAutoLoad,
|
||||||
|
autoLoadFileMaxSizeMb,
|
||||||
uploadProgress,
|
uploadProgress,
|
||||||
withDate,
|
withDate,
|
||||||
datetime,
|
datetime,
|
||||||
@ -51,39 +58,62 @@ const Document: FC<OwnProps> = ({
|
|||||||
onDateClick,
|
onDateClick,
|
||||||
isDownloading,
|
isDownloading,
|
||||||
}) => {
|
}) => {
|
||||||
|
const dispatch = getDispatch();
|
||||||
|
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const document = message.content.document!;
|
const document = message.content.document!;
|
||||||
const extension = getDocumentExtension(document) || '';
|
|
||||||
const { fileName, size, timestamp } = document;
|
const { fileName, size, timestamp } = document;
|
||||||
const withMediaViewer = onMediaClick && Boolean(document.mediaType);
|
const extension = getDocumentExtension(document) || '';
|
||||||
|
|
||||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||||
const dispatch = getDispatch();
|
const [wasIntersected, markIntersected] = useFlag();
|
||||||
|
useEffect(() => {
|
||||||
|
if (isIntersecting) {
|
||||||
|
markIntersected();
|
||||||
|
}
|
||||||
|
}, [isIntersecting, markIntersected]);
|
||||||
|
|
||||||
const { loadProgress: downloadProgress } = useMediaWithLoadProgress<ApiMediaFormat.BlobUrl>(
|
// Auto-loading does not use global download manager because requires additional click to save files locally
|
||||||
getMessageMediaHash(message, 'download'), !isDownloading, undefined, undefined, undefined, true,
|
const [isLoadAllowed, setIsLoadAllowed] = useState(
|
||||||
|
canAutoLoad && (!autoLoadFileMaxSizeMb || size <= autoLoadFileMaxSizeMb * BYTES_PER_MB),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const shouldDownload = Boolean(isDownloading || (isLoadAllowed && wasIntersected));
|
||||||
|
|
||||||
|
const documentHash = getMessageMediaHash(message, 'download');
|
||||||
|
const { loadProgress: downloadProgress, mediaData } = useMediaWithLoadProgress<ApiMediaFormat.BlobUrl>(
|
||||||
|
documentHash, !shouldDownload, undefined, undefined, undefined, true,
|
||||||
|
);
|
||||||
|
const isLoaded = Boolean(mediaData);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isUploading, isTransferring, transferProgress,
|
isUploading, isTransferring, transferProgress,
|
||||||
} = getMediaTransferState(message, uploadProgress || downloadProgress, isDownloading);
|
} = getMediaTransferState(message, uploadProgress || downloadProgress, shouldDownload && !isLoaded);
|
||||||
|
|
||||||
const hasPreview = getDocumentHasPreview(document);
|
const hasPreview = getDocumentHasPreview(document);
|
||||||
const thumbDataUri = hasPreview ? getMessageMediaThumbDataUri(message) : undefined;
|
const thumbDataUri = hasPreview ? getMessageMediaThumbDataUri(message) : undefined;
|
||||||
const localBlobUrl = hasPreview ? document.previewBlobUrl : undefined;
|
const localBlobUrl = hasPreview ? document.previewBlobUrl : undefined;
|
||||||
const previewData = useMedia(getMessageMediaHash(message, 'pictogram'), !isIntersecting);
|
const previewData = useMedia(getMessageMediaHash(message, 'pictogram'), !isIntersecting);
|
||||||
|
|
||||||
|
const withMediaViewer = onMediaClick && Boolean(document.mediaType);
|
||||||
|
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
|
if (isUploading) {
|
||||||
|
if (onCancelUpload) {
|
||||||
|
onCancelUpload();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isDownloading) {
|
if (isDownloading) {
|
||||||
dispatch.cancelMessageMediaDownload({ message });
|
dispatch.cancelMessageMediaDownload({ message });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUploading) {
|
if (isTransferring) {
|
||||||
if (onCancelUpload) {
|
setIsLoadAllowed(false);
|
||||||
onCancelUpload();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +122,9 @@ const Document: FC<OwnProps> = ({
|
|||||||
} else {
|
} else {
|
||||||
dispatch.downloadMessageMedia({ message });
|
dispatch.downloadMessageMedia({ message });
|
||||||
}
|
}
|
||||||
}, [withMediaViewer, isUploading, isDownloading, onMediaClick, onCancelUpload, dispatch, message]);
|
}, [
|
||||||
|
isUploading, isDownloading, isTransferring, withMediaViewer, onCancelUpload, dispatch, message, onMediaClick,
|
||||||
|
]);
|
||||||
|
|
||||||
const handleDateClick = useCallback(() => {
|
const handleDateClick = useCallback(() => {
|
||||||
onDateClick!(message.id, message.chatId);
|
onDateClick!(message.id, message.chatId);
|
||||||
|
|||||||
@ -118,6 +118,7 @@ const LeftColumn: FC<StateProps & DispatchProps> = ({
|
|||||||
case SettingsScreens.Folders:
|
case SettingsScreens.Folders:
|
||||||
case SettingsScreens.General:
|
case SettingsScreens.General:
|
||||||
case SettingsScreens.Notifications:
|
case SettingsScreens.Notifications:
|
||||||
|
case SettingsScreens.DataStorage:
|
||||||
case SettingsScreens.Privacy:
|
case SettingsScreens.Privacy:
|
||||||
case SettingsScreens.Language:
|
case SettingsScreens.Language:
|
||||||
setSettingsScreen(SettingsScreens.Main);
|
setSettingsScreen(SettingsScreens.Main);
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import Transition from '../../ui/Transition';
|
|||||||
import SettingsHeader from './SettingsHeader';
|
import SettingsHeader from './SettingsHeader';
|
||||||
import SettingsMain from './SettingsMain';
|
import SettingsMain from './SettingsMain';
|
||||||
import SettingsEditProfile from './SettingsEditProfile';
|
import SettingsEditProfile from './SettingsEditProfile';
|
||||||
|
import SettingsDataStorage from './SettingsDataStorage';
|
||||||
import SettingsFolders from './folders/SettingsFolders';
|
import SettingsFolders from './folders/SettingsFolders';
|
||||||
import SettingsGeneral from './SettingsGeneral';
|
import SettingsGeneral from './SettingsGeneral';
|
||||||
import SettingsGeneralBackground from './SettingsGeneralBackground';
|
import SettingsGeneralBackground from './SettingsGeneralBackground';
|
||||||
@ -187,6 +188,10 @@ const Settings: FC<OwnProps> = ({
|
|||||||
return (
|
return (
|
||||||
<SettingsNotifications onScreenSelect={onScreenSelect} isActive={isScreenActive} onReset={handleReset} />
|
<SettingsNotifications onScreenSelect={onScreenSelect} isActive={isScreenActive} onReset={handleReset} />
|
||||||
);
|
);
|
||||||
|
case SettingsScreens.DataStorage:
|
||||||
|
return (
|
||||||
|
<SettingsDataStorage onScreenSelect={onScreenSelect} isActive={isScreenActive} onReset={handleReset} />
|
||||||
|
);
|
||||||
case SettingsScreens.Privacy:
|
case SettingsScreens.Privacy:
|
||||||
return (
|
return (
|
||||||
<SettingsPrivacy
|
<SettingsPrivacy
|
||||||
|
|||||||
199
src/components/left/settings/SettingsDataStorage.tsx
Normal file
199
src/components/left/settings/SettingsDataStorage.tsx
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
import React, { FC, memo, useCallback } from '../../../lib/teact/teact';
|
||||||
|
import { withGlobal } from '../../../lib/teact/teactn';
|
||||||
|
|
||||||
|
import { GlobalActions } from '../../../global/types';
|
||||||
|
import { SettingsScreens, ISettings } from '../../../types';
|
||||||
|
|
||||||
|
import { AUTODOWNLOAD_FILESIZE_MB_LIMITS } from '../../../config';
|
||||||
|
import { pick } from '../../../util/iteratees';
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
|
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||||
|
|
||||||
|
import Checkbox from '../../ui/Checkbox';
|
||||||
|
import RangeSlider from '../../ui/RangeSlider';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
isActive?: boolean;
|
||||||
|
onScreenSelect: (screen: SettingsScreens) => void;
|
||||||
|
onReset: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StateProps = Pick<ISettings, (
|
||||||
|
'canAutoLoadPhotoFromContacts' |
|
||||||
|
'canAutoLoadPhotoInPrivateChats' |
|
||||||
|
'canAutoLoadPhotoInGroups' |
|
||||||
|
'canAutoLoadPhotoInChannels' |
|
||||||
|
'canAutoLoadVideoFromContacts' |
|
||||||
|
'canAutoLoadVideoInPrivateChats' |
|
||||||
|
'canAutoLoadVideoInGroups' |
|
||||||
|
'canAutoLoadVideoInChannels' |
|
||||||
|
'canAutoLoadFileFromContacts' |
|
||||||
|
'canAutoLoadFileInPrivateChats' |
|
||||||
|
'canAutoLoadFileInGroups' |
|
||||||
|
'canAutoLoadFileInChannels' |
|
||||||
|
'canAutoPlayGifs' |
|
||||||
|
'canAutoPlayVideos' |
|
||||||
|
'autoLoadFileMaxSizeMb'
|
||||||
|
)>;
|
||||||
|
|
||||||
|
type DispatchProps = Pick<GlobalActions, (
|
||||||
|
'setSettingOption'
|
||||||
|
)>;
|
||||||
|
|
||||||
|
const SettingsDataStorage: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||||
|
isActive,
|
||||||
|
onScreenSelect,
|
||||||
|
onReset,
|
||||||
|
canAutoLoadPhotoFromContacts,
|
||||||
|
canAutoLoadPhotoInPrivateChats,
|
||||||
|
canAutoLoadPhotoInGroups,
|
||||||
|
canAutoLoadPhotoInChannels,
|
||||||
|
canAutoLoadVideoFromContacts,
|
||||||
|
canAutoLoadVideoInPrivateChats,
|
||||||
|
canAutoLoadVideoInGroups,
|
||||||
|
canAutoLoadVideoInChannels,
|
||||||
|
canAutoLoadFileFromContacts,
|
||||||
|
canAutoLoadFileInPrivateChats,
|
||||||
|
canAutoLoadFileInGroups,
|
||||||
|
canAutoLoadFileInChannels,
|
||||||
|
canAutoPlayGifs,
|
||||||
|
canAutoPlayVideos,
|
||||||
|
autoLoadFileMaxSizeMb,
|
||||||
|
setSettingOption,
|
||||||
|
}) => {
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
|
useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.General);
|
||||||
|
|
||||||
|
const renderFileSizeCallback = useCallback((value: number) => {
|
||||||
|
return lang('AutodownloadSizeLimitUpTo', lang('FileSize.MB', String(AUTODOWNLOAD_FILESIZE_MB_LIMITS[value]), 'i'));
|
||||||
|
}, [lang]);
|
||||||
|
|
||||||
|
const handleFileSizeChange = useCallback((value: number) => {
|
||||||
|
setSettingOption({ autoLoadFileMaxSizeMb: AUTODOWNLOAD_FILESIZE_MB_LIMITS[value] });
|
||||||
|
}, [setSettingOption]);
|
||||||
|
|
||||||
|
function renderContentSizeSlider() {
|
||||||
|
const value = AUTODOWNLOAD_FILESIZE_MB_LIMITS.indexOf(autoLoadFileMaxSizeMb);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="pt-5">
|
||||||
|
<RangeSlider
|
||||||
|
label={lang('AutoDownloadMaxFileSize')}
|
||||||
|
min={0}
|
||||||
|
max={5}
|
||||||
|
value={value !== -1 ? value : 2}
|
||||||
|
renderValue={renderFileSizeCallback}
|
||||||
|
onChange={handleFileSizeChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderAutoDownloadBlock(
|
||||||
|
title: string,
|
||||||
|
key: 'Photo' | 'Video' | 'File',
|
||||||
|
canAutoLoadFromContacts: boolean,
|
||||||
|
canAutoLoadInPrivateChats: boolean,
|
||||||
|
canAutoLoadInGroups: boolean,
|
||||||
|
canAutoLoadInChannels: boolean,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<div className="settings-item">
|
||||||
|
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>{title}</h4>
|
||||||
|
|
||||||
|
<Checkbox
|
||||||
|
label={lang('AutoDownloadSettings.Contacts')}
|
||||||
|
checked={canAutoLoadFromContacts}
|
||||||
|
onCheck={(isChecked) => setSettingOption({ [`canAutoLoad${key}FromContacts`]: isChecked })}
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={lang('AutoDownloadSettings.PrivateChats')}
|
||||||
|
checked={canAutoLoadInPrivateChats}
|
||||||
|
onCheck={(isChecked) => setSettingOption({ [`canAutoLoad${key}InPrivateChats`]: isChecked })}
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={lang('AutoDownloadSettings.GroupChats')}
|
||||||
|
checked={canAutoLoadInGroups}
|
||||||
|
onCheck={(isChecked) => setSettingOption({ [`canAutoLoad${key}InGroups`]: isChecked })}
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={lang('AutoDownloadSettings.Channels')}
|
||||||
|
checked={canAutoLoadInChannels}
|
||||||
|
onCheck={(isChecked) => setSettingOption({ [`canAutoLoad${key}InChannels`]: isChecked })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{key === 'File' && renderContentSizeSlider()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="settings-content custom-scroll">
|
||||||
|
{renderAutoDownloadBlock(
|
||||||
|
lang('AutoDownloadPhotosTitle'),
|
||||||
|
'Photo',
|
||||||
|
canAutoLoadPhotoFromContacts,
|
||||||
|
canAutoLoadPhotoInPrivateChats,
|
||||||
|
canAutoLoadPhotoInGroups,
|
||||||
|
canAutoLoadPhotoInChannels,
|
||||||
|
)}
|
||||||
|
{renderAutoDownloadBlock(
|
||||||
|
lang('AutoDownloadVideosTitle'),
|
||||||
|
'Video',
|
||||||
|
canAutoLoadVideoFromContacts,
|
||||||
|
canAutoLoadVideoInPrivateChats,
|
||||||
|
canAutoLoadVideoInGroups,
|
||||||
|
canAutoLoadVideoInChannels,
|
||||||
|
)}
|
||||||
|
{renderAutoDownloadBlock(
|
||||||
|
'Auto-download files', // Proper translation is not available yet
|
||||||
|
'File',
|
||||||
|
canAutoLoadFileFromContacts,
|
||||||
|
canAutoLoadFileInPrivateChats,
|
||||||
|
canAutoLoadFileInGroups,
|
||||||
|
canAutoLoadFileInChannels,
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="settings-item">
|
||||||
|
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>{lang('AutoplayMedia')}</h4>
|
||||||
|
|
||||||
|
<Checkbox
|
||||||
|
label={lang('GifsTab2')}
|
||||||
|
checked={canAutoPlayGifs}
|
||||||
|
onCheck={(isChecked) => setSettingOption({ canAutoPlayGifs: isChecked })}
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label={lang('DataAndStorage.Autoplay.Videos')}
|
||||||
|
checked={canAutoPlayVideos}
|
||||||
|
onCheck={(isChecked) => setSettingOption({ canAutoPlayVideos: isChecked })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(withGlobal<OwnProps>(
|
||||||
|
(global): StateProps => {
|
||||||
|
return pick(global.settings.byKey, [
|
||||||
|
'canAutoLoadPhotoFromContacts',
|
||||||
|
'canAutoLoadPhotoInPrivateChats',
|
||||||
|
'canAutoLoadPhotoInGroups',
|
||||||
|
'canAutoLoadPhotoInChannels',
|
||||||
|
'canAutoLoadVideoFromContacts',
|
||||||
|
'canAutoLoadVideoInPrivateChats',
|
||||||
|
'canAutoLoadVideoInGroups',
|
||||||
|
'canAutoLoadVideoInChannels',
|
||||||
|
'canAutoLoadFileFromContacts',
|
||||||
|
'canAutoLoadFileInPrivateChats',
|
||||||
|
'canAutoLoadFileInGroups',
|
||||||
|
'canAutoLoadFileInChannels',
|
||||||
|
'canAutoPlayGifs',
|
||||||
|
'canAutoPlayVideos',
|
||||||
|
'autoLoadFileMaxSizeMb',
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
(setGlobal, actions): DispatchProps => pick(actions, [
|
||||||
|
'setSettingOption',
|
||||||
|
]),
|
||||||
|
)(SettingsDataStorage));
|
||||||
@ -32,12 +32,6 @@ type StateProps = Pick<ISettings, (
|
|||||||
'messageTextSize' |
|
'messageTextSize' |
|
||||||
'animationLevel' |
|
'animationLevel' |
|
||||||
'messageSendKeyCombo' |
|
'messageSendKeyCombo' |
|
||||||
'shouldAutoDownloadMediaFromContacts' |
|
|
||||||
'shouldAutoDownloadMediaInPrivateChats' |
|
|
||||||
'shouldAutoDownloadMediaInGroups' |
|
|
||||||
'shouldAutoDownloadMediaInChannels' |
|
|
||||||
'shouldAutoPlayGifs' |
|
|
||||||
'shouldAutoPlayVideos' |
|
|
||||||
'shouldSuggestStickers' |
|
'shouldSuggestStickers' |
|
||||||
'shouldLoopStickers' |
|
'shouldLoopStickers' |
|
||||||
'timeFormat'
|
'timeFormat'
|
||||||
@ -73,12 +67,6 @@ const SettingsGeneral: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
messageTextSize,
|
messageTextSize,
|
||||||
animationLevel,
|
animationLevel,
|
||||||
messageSendKeyCombo,
|
messageSendKeyCombo,
|
||||||
shouldAutoDownloadMediaFromContacts,
|
|
||||||
shouldAutoDownloadMediaInPrivateChats,
|
|
||||||
shouldAutoDownloadMediaInGroups,
|
|
||||||
shouldAutoDownloadMediaInChannels,
|
|
||||||
shouldAutoPlayGifs,
|
|
||||||
shouldAutoPlayVideos,
|
|
||||||
shouldSuggestStickers,
|
shouldSuggestStickers,
|
||||||
shouldLoopStickers,
|
shouldLoopStickers,
|
||||||
timeFormat,
|
timeFormat,
|
||||||
@ -211,46 +199,6 @@ const SettingsGeneral: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="settings-item">
|
|
||||||
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>{lang('AutoDownloadMedia')}</h4>
|
|
||||||
|
|
||||||
<Checkbox
|
|
||||||
label={lang('Contacts')}
|
|
||||||
checked={shouldAutoDownloadMediaFromContacts}
|
|
||||||
onCheck={(isChecked) => setSettingOption({ shouldAutoDownloadMediaFromContacts: isChecked })}
|
|
||||||
/>
|
|
||||||
<Checkbox
|
|
||||||
label={lang('AutodownloadPrivateChats')}
|
|
||||||
checked={shouldAutoDownloadMediaInPrivateChats}
|
|
||||||
onCheck={(isChecked) => setSettingOption({ shouldAutoDownloadMediaInPrivateChats: isChecked })}
|
|
||||||
/>
|
|
||||||
<Checkbox
|
|
||||||
label={lang('AutodownloadGroupChats')}
|
|
||||||
checked={shouldAutoDownloadMediaInGroups}
|
|
||||||
onCheck={(isChecked) => setSettingOption({ shouldAutoDownloadMediaInGroups: isChecked })}
|
|
||||||
/>
|
|
||||||
<Checkbox
|
|
||||||
label={lang('FilterChannels')}
|
|
||||||
checked={shouldAutoDownloadMediaInChannels}
|
|
||||||
onCheck={(isChecked) => setSettingOption({ shouldAutoDownloadMediaInChannels: isChecked })}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="settings-item">
|
|
||||||
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>{lang('AutoplayMedia')}</h4>
|
|
||||||
|
|
||||||
<Checkbox
|
|
||||||
label={lang('GifsTab2')}
|
|
||||||
checked={shouldAutoPlayGifs}
|
|
||||||
onCheck={(isChecked) => setSettingOption({ shouldAutoPlayGifs: isChecked })}
|
|
||||||
/>
|
|
||||||
<Checkbox
|
|
||||||
label={lang('DataAndStorage.Autoplay.Videos')}
|
|
||||||
checked={shouldAutoPlayVideos}
|
|
||||||
onCheck={(isChecked) => setSettingOption({ shouldAutoPlayVideos: isChecked })}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="settings-item">
|
<div className="settings-item">
|
||||||
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>{lang('AccDescrStickers')}</h4>
|
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>{lang('AccDescrStickers')}</h4>
|
||||||
|
|
||||||
@ -294,12 +242,6 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
'messageTextSize',
|
'messageTextSize',
|
||||||
'animationLevel',
|
'animationLevel',
|
||||||
'messageSendKeyCombo',
|
'messageSendKeyCombo',
|
||||||
'shouldAutoDownloadMediaFromContacts',
|
|
||||||
'shouldAutoDownloadMediaInPrivateChats',
|
|
||||||
'shouldAutoDownloadMediaInGroups',
|
|
||||||
'shouldAutoDownloadMediaInChannels',
|
|
||||||
'shouldAutoPlayGifs',
|
|
||||||
'shouldAutoPlayVideos',
|
|
||||||
'shouldSuggestStickers',
|
'shouldSuggestStickers',
|
||||||
'shouldLoopStickers',
|
'shouldLoopStickers',
|
||||||
'isSensitiveEnabled',
|
'isSensitiveEnabled',
|
||||||
|
|||||||
@ -90,6 +90,8 @@ const SettingsHeader: FC<OwnProps & DispatchProps> = ({
|
|||||||
return <h3>{lang('General')}</h3>;
|
return <h3>{lang('General')}</h3>;
|
||||||
case SettingsScreens.Notifications:
|
case SettingsScreens.Notifications:
|
||||||
return <h3>{lang('Notifications')}</h3>;
|
return <h3>{lang('Notifications')}</h3>;
|
||||||
|
case SettingsScreens.DataStorage:
|
||||||
|
return <h3>{lang('DataSettings')}</h3>;
|
||||||
case SettingsScreens.Privacy:
|
case SettingsScreens.Privacy:
|
||||||
return <h3>{lang('PrivacySettings')}</h3>;
|
return <h3>{lang('PrivacySettings')}</h3>;
|
||||||
case SettingsScreens.Language:
|
case SettingsScreens.Language:
|
||||||
|
|||||||
@ -79,6 +79,12 @@ const SettingsMain: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
>
|
>
|
||||||
{lang('PrivacySettings')}
|
{lang('PrivacySettings')}
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
icon="data"
|
||||||
|
onClick={() => onScreenSelect(SettingsScreens.DataStorage)}
|
||||||
|
>
|
||||||
|
{lang('DataSettings')}
|
||||||
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
icon="folder"
|
icon="folder"
|
||||||
onClick={() => onScreenSelect(SettingsScreens.Folders)}
|
onClick={() => onScreenSelect(SettingsScreens.Folders)}
|
||||||
|
|||||||
@ -23,8 +23,8 @@ const VideoWithSelect = withSelectControl(Video);
|
|||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
album: IAlbum;
|
album: IAlbum;
|
||||||
observeIntersection: ObserveFn;
|
observeIntersection: ObserveFn;
|
||||||
shouldAutoLoad?: boolean;
|
canAutoLoad?: boolean;
|
||||||
shouldAutoPlay?: boolean;
|
canAutoPlay?: boolean;
|
||||||
hasCustomAppendix?: boolean;
|
hasCustomAppendix?: boolean;
|
||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
isOwn: boolean;
|
isOwn: boolean;
|
||||||
@ -43,8 +43,8 @@ type DispatchProps = Pick<GlobalActions, 'cancelSendingMessage'>;
|
|||||||
const Album: FC<OwnProps & StateProps & DispatchProps> = ({
|
const Album: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||||
album,
|
album,
|
||||||
observeIntersection,
|
observeIntersection,
|
||||||
shouldAutoLoad,
|
canAutoLoad,
|
||||||
shouldAutoPlay,
|
canAutoPlay,
|
||||||
hasCustomAppendix,
|
hasCustomAppendix,
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
isOwn,
|
isOwn,
|
||||||
@ -78,7 +78,7 @@ const Album: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
id={`album-media-${message.id}`}
|
id={`album-media-${message.id}`}
|
||||||
message={message}
|
message={message}
|
||||||
observeIntersection={observeIntersection}
|
observeIntersection={observeIntersection}
|
||||||
shouldAutoLoad={shouldAutoLoad}
|
canAutoLoad={canAutoLoad}
|
||||||
shouldAffectAppendix={shouldAffectAppendix}
|
shouldAffectAppendix={shouldAffectAppendix}
|
||||||
uploadProgress={uploadProgress}
|
uploadProgress={uploadProgress}
|
||||||
dimensions={dimensions}
|
dimensions={dimensions}
|
||||||
@ -94,8 +94,8 @@ const Album: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
id={`album-media-${message.id}`}
|
id={`album-media-${message.id}`}
|
||||||
message={message}
|
message={message}
|
||||||
observeIntersection={observeIntersection}
|
observeIntersection={observeIntersection}
|
||||||
shouldAutoLoad={shouldAutoLoad}
|
canAutoLoad={canAutoLoad}
|
||||||
shouldAutoPlay={shouldAutoPlay}
|
canAutoPlay={canAutoPlay}
|
||||||
uploadProgress={uploadProgress}
|
uploadProgress={uploadProgress}
|
||||||
lastSyncTime={lastSyncTime}
|
lastSyncTime={lastSyncTime}
|
||||||
dimensions={dimensions}
|
dimensions={dimensions}
|
||||||
|
|||||||
@ -39,8 +39,8 @@ import {
|
|||||||
selectSender,
|
selectSender,
|
||||||
selectForwardedSender,
|
selectForwardedSender,
|
||||||
selectThreadTopMessageId,
|
selectThreadTopMessageId,
|
||||||
selectShouldAutoLoadMedia,
|
selectCanAutoLoadMedia,
|
||||||
selectShouldAutoPlayMedia,
|
selectCanAutoPlayMedia,
|
||||||
selectShouldLoopStickers,
|
selectShouldLoopStickers,
|
||||||
selectTheme,
|
selectTheme,
|
||||||
selectAllowedMessageActions,
|
selectAllowedMessageActions,
|
||||||
@ -157,9 +157,10 @@ type StateProps = {
|
|||||||
isDownloading: boolean;
|
isDownloading: boolean;
|
||||||
threadId?: number;
|
threadId?: number;
|
||||||
isPinnedList?: boolean;
|
isPinnedList?: boolean;
|
||||||
shouldAutoLoadMedia?: boolean;
|
canAutoLoadMedia?: boolean;
|
||||||
shouldAutoPlayMedia?: boolean;
|
canAutoPlayMedia?: boolean;
|
||||||
shouldLoopStickers?: boolean;
|
shouldLoopStickers?: boolean;
|
||||||
|
autoLoadFileMaxSizeMb: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type DispatchProps = Pick<GlobalActions, 'toggleMessageSelection' | 'clickInlineButton' | 'disableContextMenuHint'>;
|
type DispatchProps = Pick<GlobalActions, 'toggleMessageSelection' | 'clickInlineButton' | 'disableContextMenuHint'>;
|
||||||
@ -220,9 +221,10 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
messageListType,
|
messageListType,
|
||||||
isPinnedList,
|
isPinnedList,
|
||||||
isDownloading,
|
isDownloading,
|
||||||
shouldAutoLoadMedia,
|
canAutoLoadMedia,
|
||||||
shouldAutoPlayMedia,
|
canAutoPlayMedia,
|
||||||
shouldLoopStickers,
|
shouldLoopStickers,
|
||||||
|
autoLoadFileMaxSizeMb,
|
||||||
toggleMessageSelection,
|
toggleMessageSelection,
|
||||||
clickInlineButton,
|
clickInlineButton,
|
||||||
disableContextMenuHint,
|
disableContextMenuHint,
|
||||||
@ -513,8 +515,8 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
album={album!}
|
album={album!}
|
||||||
albumLayout={albumLayout!}
|
albumLayout={albumLayout!}
|
||||||
observeIntersection={observeIntersectionForMedia}
|
observeIntersection={observeIntersectionForMedia}
|
||||||
shouldAutoLoad={shouldAutoLoadMedia}
|
canAutoLoad={canAutoLoadMedia}
|
||||||
shouldAutoPlay={shouldAutoPlayMedia}
|
canAutoPlay={canAutoPlayMedia}
|
||||||
isOwn={isOwn}
|
isOwn={isOwn}
|
||||||
hasCustomAppendix={hasCustomAppendix}
|
hasCustomAppendix={hasCustomAppendix}
|
||||||
lastSyncTime={lastSyncTime}
|
lastSyncTime={lastSyncTime}
|
||||||
@ -526,7 +528,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
message={message}
|
message={message}
|
||||||
observeIntersection={observeIntersectionForMedia}
|
observeIntersection={observeIntersectionForMedia}
|
||||||
noAvatars={noAvatars}
|
noAvatars={noAvatars}
|
||||||
shouldAutoLoad={shouldAutoLoadMedia}
|
canAutoLoad={canAutoLoadMedia}
|
||||||
uploadProgress={uploadProgress}
|
uploadProgress={uploadProgress}
|
||||||
shouldAffectAppendix={hasCustomAppendix}
|
shouldAffectAppendix={hasCustomAppendix}
|
||||||
onClick={handleMediaClick}
|
onClick={handleMediaClick}
|
||||||
@ -539,8 +541,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<RoundVideo
|
<RoundVideo
|
||||||
message={message}
|
message={message}
|
||||||
observeIntersection={observeIntersectionForMedia}
|
observeIntersection={observeIntersectionForMedia}
|
||||||
shouldAutoLoad={shouldAutoLoadMedia}
|
canAutoLoad={canAutoLoadMedia}
|
||||||
shouldAutoPlay={shouldAutoPlayMedia}
|
|
||||||
lastSyncTime={lastSyncTime}
|
lastSyncTime={lastSyncTime}
|
||||||
isDownloading={isDownloading}
|
isDownloading={isDownloading}
|
||||||
/>
|
/>
|
||||||
@ -550,8 +551,8 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
message={message}
|
message={message}
|
||||||
observeIntersection={observeIntersectionForMedia}
|
observeIntersection={observeIntersectionForMedia}
|
||||||
noAvatars={noAvatars}
|
noAvatars={noAvatars}
|
||||||
shouldAutoLoad={shouldAutoLoadMedia}
|
canAutoLoad={canAutoLoadMedia}
|
||||||
shouldAutoPlay={shouldAutoPlayMedia}
|
canAutoPlay={canAutoPlayMedia}
|
||||||
uploadProgress={uploadProgress}
|
uploadProgress={uploadProgress}
|
||||||
lastSyncTime={lastSyncTime}
|
lastSyncTime={lastSyncTime}
|
||||||
onClick={handleMediaClick}
|
onClick={handleMediaClick}
|
||||||
@ -578,6 +579,8 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<Document
|
<Document
|
||||||
message={message}
|
message={message}
|
||||||
observeIntersection={observeIntersectionForMedia}
|
observeIntersection={observeIntersectionForMedia}
|
||||||
|
canAutoLoad={canAutoLoadMedia}
|
||||||
|
autoLoadFileMaxSizeMb={autoLoadFileMaxSizeMb}
|
||||||
uploadProgress={uploadProgress}
|
uploadProgress={uploadProgress}
|
||||||
isSelectable={isInDocumentGroup}
|
isSelectable={isInDocumentGroup}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
@ -610,8 +613,8 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
message={message}
|
message={message}
|
||||||
observeIntersection={observeIntersectionForMedia}
|
observeIntersection={observeIntersectionForMedia}
|
||||||
noAvatars={noAvatars}
|
noAvatars={noAvatars}
|
||||||
shouldAutoLoad={shouldAutoLoadMedia}
|
canAutoLoad={canAutoLoadMedia}
|
||||||
shouldAutoPlay={shouldAutoPlayMedia}
|
canAutoPlay={canAutoPlayMedia}
|
||||||
lastSyncTime={lastSyncTime}
|
lastSyncTime={lastSyncTime}
|
||||||
onMediaClick={handleMediaClick}
|
onMediaClick={handleMediaClick}
|
||||||
onCancelMediaTransfer={handleCancelUpload}
|
onCancelMediaTransfer={handleCancelUpload}
|
||||||
@ -825,7 +828,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|
|
||||||
const forceSenderName = !isChatWithSelf && isAnonymousOwnMessage(message);
|
const forceSenderName = !isChatWithSelf && isAnonymousOwnMessage(message);
|
||||||
const canShowSender = withSenderName || withAvatar || forceSenderName;
|
const canShowSender = withSenderName || withAvatar || forceSenderName;
|
||||||
const sender = canShowSender ? selectSender(global, message) : undefined;
|
const sender = selectSender(global, message);
|
||||||
const originSender = selectForwardedSender(global, message);
|
const originSender = selectForwardedSender(global, message);
|
||||||
const botSender = viaBotId ? selectUser(global, viaBotId) : undefined;
|
const botSender = viaBotId ? selectUser(global, viaBotId) : undefined;
|
||||||
|
|
||||||
@ -869,7 +872,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
theme: selectTheme(global),
|
theme: selectTheme(global),
|
||||||
chatUsername,
|
chatUsername,
|
||||||
forceSenderName,
|
forceSenderName,
|
||||||
sender,
|
sender: canShowSender ? sender : undefined,
|
||||||
originSender,
|
originSender,
|
||||||
botSender,
|
botSender,
|
||||||
shouldHideReply,
|
shouldHideReply,
|
||||||
@ -894,8 +897,9 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
threadId,
|
threadId,
|
||||||
isDownloading,
|
isDownloading,
|
||||||
isPinnedList: messageListType === 'pinned',
|
isPinnedList: messageListType === 'pinned',
|
||||||
shouldAutoLoadMedia: chat ? selectShouldAutoLoadMedia(global, message, chat, sender) : undefined,
|
canAutoLoadMedia: chat ? selectCanAutoLoadMedia(global, message, chat, sender) : undefined,
|
||||||
shouldAutoPlayMedia: selectShouldAutoPlayMedia(global, message),
|
canAutoPlayMedia: selectCanAutoPlayMedia(global, message),
|
||||||
|
autoLoadFileMaxSizeMb: global.settings.byKey.autoLoadFileMaxSizeMb,
|
||||||
shouldLoopStickers: selectShouldLoopStickers(global),
|
shouldLoopStickers: selectShouldLoopStickers(global),
|
||||||
...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }),
|
...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }),
|
||||||
...(typeof uploadProgress === 'number' && { uploadProgress }),
|
...(typeof uploadProgress === 'number' && { uploadProgress }),
|
||||||
|
|||||||
@ -18,19 +18,19 @@ import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
|
|||||||
import useShowTransition from '../../../hooks/useShowTransition';
|
import useShowTransition from '../../../hooks/useShowTransition';
|
||||||
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
||||||
import usePrevious from '../../../hooks/usePrevious';
|
import usePrevious from '../../../hooks/usePrevious';
|
||||||
|
import useMediaTransition from '../../../hooks/useMediaTransition';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
||||||
import { calculateMediaDimensions } from './helpers/mediaDimensions';
|
import { calculateMediaDimensions } from './helpers/mediaDimensions';
|
||||||
|
|
||||||
import ProgressSpinner from '../../ui/ProgressSpinner';
|
import ProgressSpinner from '../../ui/ProgressSpinner';
|
||||||
import useMediaTransition from '../../../hooks/useMediaTransition';
|
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
id?: string;
|
id?: string;
|
||||||
message: ApiMessage;
|
message: ApiMessage;
|
||||||
observeIntersection?: ObserveFn;
|
observeIntersection?: ObserveFn;
|
||||||
noAvatars?: boolean;
|
noAvatars?: boolean;
|
||||||
shouldAutoLoad?: boolean;
|
canAutoLoad?: boolean;
|
||||||
isInSelectMode?: boolean;
|
isInSelectMode?: boolean;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
uploadProgress?: number;
|
uploadProgress?: number;
|
||||||
@ -51,7 +51,7 @@ const Photo: FC<OwnProps> = ({
|
|||||||
message,
|
message,
|
||||||
observeIntersection,
|
observeIntersection,
|
||||||
noAvatars,
|
noAvatars,
|
||||||
shouldAutoLoad,
|
canAutoLoad,
|
||||||
isInSelectMode,
|
isInSelectMode,
|
||||||
isSelected,
|
isSelected,
|
||||||
uploadProgress,
|
uploadProgress,
|
||||||
@ -72,7 +72,7 @@ const Photo: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||||
|
|
||||||
const [isLoadAllowed, setIsLoadAllowed] = useState(shouldAutoLoad);
|
const [isLoadAllowed, setIsLoadAllowed] = useState(canAutoLoad);
|
||||||
const shouldLoad = isLoadAllowed && isIntersecting;
|
const shouldLoad = isLoadAllowed && isIntersecting;
|
||||||
const {
|
const {
|
||||||
mediaData, loadProgress,
|
mediaData, loadProgress,
|
||||||
@ -98,6 +98,10 @@ const Photo: FC<OwnProps> = ({
|
|||||||
shouldRender: shouldRenderSpinner,
|
shouldRender: shouldRenderSpinner,
|
||||||
transitionClassNames: spinnerClassNames,
|
transitionClassNames: spinnerClassNames,
|
||||||
} = useShowTransition(isTransferring, undefined, wasLoadDisabled, 'slow');
|
} = useShowTransition(isTransferring, undefined, wasLoadDisabled, 'slow');
|
||||||
|
const {
|
||||||
|
shouldRender: shouldRenderDownloadButton,
|
||||||
|
transitionClassNames: downloadButtonClassNames,
|
||||||
|
} = useShowTransition(!fullMediaData && !isLoadAllowed);
|
||||||
|
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
if (isUploading) {
|
if (isUploading) {
|
||||||
@ -164,14 +168,12 @@ const Photo: FC<OwnProps> = ({
|
|||||||
height={height}
|
height={height}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
{shouldRenderSpinner && (
|
{shouldRenderSpinner && !shouldRenderDownloadButton && (
|
||||||
<div className={`media-loading ${spinnerClassNames}`}>
|
<div className={`media-loading ${spinnerClassNames}`}>
|
||||||
<ProgressSpinner progress={transferProgress} onClick={isUploading ? handleClick : undefined} />
|
<ProgressSpinner progress={transferProgress} onClick={isUploading ? handleClick : undefined} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!fullMediaData && !isLoadAllowed && (
|
{shouldRenderDownloadButton && <i className={buildClassName('icon-download', downloadButtonClassNames)} />}
|
||||||
<i className="icon-download" />
|
|
||||||
)}
|
|
||||||
{isTransferring && (
|
{isTransferring && (
|
||||||
<span className="message-transfer-progress">{Math.round(transferProgress * 100)}%</span>
|
<span className="message-transfer-progress">{Math.round(transferProgress * 100)}%</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -34,8 +34,7 @@ import './RoundVideo.scss';
|
|||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
message: ApiMessage;
|
message: ApiMessage;
|
||||||
observeIntersection: ObserveFn;
|
observeIntersection: ObserveFn;
|
||||||
shouldAutoLoad?: boolean;
|
canAutoLoad?: boolean;
|
||||||
shouldAutoPlay?: boolean;
|
|
||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
isDownloading?: boolean;
|
isDownloading?: boolean;
|
||||||
};
|
};
|
||||||
@ -55,8 +54,7 @@ function createCapture(onRelease: NoneToVoidFunction) {
|
|||||||
const RoundVideo: FC<OwnProps> = ({
|
const RoundVideo: FC<OwnProps> = ({
|
||||||
message,
|
message,
|
||||||
observeIntersection,
|
observeIntersection,
|
||||||
shouldAutoLoad,
|
canAutoLoad,
|
||||||
shouldAutoPlay,
|
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
isDownloading,
|
isDownloading,
|
||||||
}) => {
|
}) => {
|
||||||
@ -71,7 +69,7 @@ const RoundVideo: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||||
|
|
||||||
const [isLoadAllowed, setIsLoadAllowed] = useState(shouldAutoLoad && shouldAutoPlay);
|
const [isLoadAllowed, setIsLoadAllowed] = useState(canAutoLoad);
|
||||||
const shouldLoad = Boolean(isLoadAllowed && isIntersecting && lastSyncTime);
|
const shouldLoad = Boolean(isLoadAllowed && isIntersecting && lastSyncTime);
|
||||||
const { mediaData, loadProgress } = useMediaWithLoadProgress(
|
const { mediaData, loadProgress } = useMediaWithLoadProgress(
|
||||||
getMessageMediaHash(message, 'inline'),
|
getMessageMediaHash(message, 'inline'),
|
||||||
@ -243,7 +241,7 @@ const RoundVideo: FC<OwnProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!mediaData && !isLoadAllowed && (
|
{!mediaData && !isLoadAllowed && (
|
||||||
<i className="icon-large-play" />
|
<i className="icon-download" />
|
||||||
)}
|
)}
|
||||||
<div className="message-media-duration">
|
<div className="message-media-duration">
|
||||||
{isActivated ? formatMediaDuration(playerRef.current!.currentTime) : formatMediaDuration(video.duration)}
|
{isActivated ? formatMediaDuration(playerRef.current!.currentTime) : formatMediaDuration(video.duration)}
|
||||||
|
|||||||
@ -36,8 +36,8 @@ export type OwnProps = {
|
|||||||
message: ApiMessage;
|
message: ApiMessage;
|
||||||
observeIntersection: ObserveFn;
|
observeIntersection: ObserveFn;
|
||||||
noAvatars?: boolean;
|
noAvatars?: boolean;
|
||||||
shouldAutoLoad?: boolean;
|
canAutoLoad?: boolean;
|
||||||
shouldAutoPlay?: boolean;
|
canAutoPlay?: boolean;
|
||||||
uploadProgress?: number;
|
uploadProgress?: number;
|
||||||
dimensions?: IMediaDimensions;
|
dimensions?: IMediaDimensions;
|
||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
@ -51,8 +51,8 @@ const Video: FC<OwnProps> = ({
|
|||||||
message,
|
message,
|
||||||
observeIntersection,
|
observeIntersection,
|
||||||
noAvatars,
|
noAvatars,
|
||||||
shouldAutoLoad,
|
canAutoLoad,
|
||||||
shouldAutoPlay,
|
canAutoPlay,
|
||||||
uploadProgress,
|
uploadProgress,
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
dimensions,
|
dimensions,
|
||||||
@ -70,9 +70,9 @@ const Video: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||||
|
|
||||||
const [isLoadAllowed, setIsLoadAllowed] = useState(shouldAutoLoad);
|
const [isLoadAllowed, setIsLoadAllowed] = useState(canAutoLoad);
|
||||||
const shouldLoad = Boolean(isLoadAllowed && isIntersecting && lastSyncTime);
|
const shouldLoad = Boolean(isLoadAllowed && isIntersecting && lastSyncTime);
|
||||||
const [isPlayAllowed, setIsPlayAllowed] = useState(shouldAutoPlay);
|
const [isPlayAllowed, setIsPlayAllowed] = useState(canAutoPlay);
|
||||||
|
|
||||||
const previewBlobUrl = useMedia(
|
const previewBlobUrl = useMedia(
|
||||||
getMessageMediaHash(message, 'pictogram'),
|
getMessageMediaHash(message, 'pictogram'),
|
||||||
@ -105,7 +105,7 @@ const Video: FC<OwnProps> = ({
|
|||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { isBuffered, bufferingHandlers } = useBuffering(!shouldAutoLoad);
|
const { isBuffered, bufferingHandlers } = useBuffering(!canAutoLoad);
|
||||||
const { isUploading, isTransferring, transferProgress } = getMediaTransferState(
|
const { isUploading, isTransferring, transferProgress } = getMediaTransferState(
|
||||||
message,
|
message,
|
||||||
uploadProgress || (isDownloading ? downloadProgress : loadProgress),
|
uploadProgress || (isDownloading ? downloadProgress : loadProgress),
|
||||||
@ -116,6 +116,10 @@ const Video: FC<OwnProps> = ({
|
|||||||
shouldRender: shouldRenderSpinner,
|
shouldRender: shouldRenderSpinner,
|
||||||
transitionClassNames: spinnerClassNames,
|
transitionClassNames: spinnerClassNames,
|
||||||
} = useShowTransition(isTransferring, undefined, wasLoadDisabled);
|
} = useShowTransition(isTransferring, undefined, wasLoadDisabled);
|
||||||
|
const {
|
||||||
|
shouldRender: shouldRenderPlayButton,
|
||||||
|
transitionClassNames: playButtonClassNames,
|
||||||
|
} = useShowTransition(isLoadAllowed && !isPlayAllowed && !shouldRenderSpinner);
|
||||||
|
|
||||||
const [playProgress, setPlayProgress] = useState<number>(0);
|
const [playProgress, setPlayProgress] = useState<number>(0);
|
||||||
const handleTimeUpdate = useCallback((e: React.SyntheticEvent<HTMLVideoElement>) => {
|
const handleTimeUpdate = useCallback((e: React.SyntheticEvent<HTMLVideoElement>) => {
|
||||||
@ -128,7 +132,7 @@ const Video: FC<OwnProps> = ({
|
|||||||
const isForwarded = isForwardedMessage(message);
|
const isForwarded = isForwardedMessage(message);
|
||||||
const { width, height } = dimensions || calculateVideoDimensions(video, isOwn, isForwarded, noAvatars);
|
const { width, height } = dimensions || calculateVideoDimensions(video, isOwn, isForwarded, noAvatars);
|
||||||
|
|
||||||
useHeavyAnimationCheckForVideo(videoRef, Boolean(isInline && shouldAutoPlay));
|
useHeavyAnimationCheckForVideo(videoRef, Boolean(isInline && canAutoPlay));
|
||||||
usePauseOnInactive(videoRef, isPlayAllowed);
|
usePauseOnInactive(videoRef, isPlayAllowed);
|
||||||
useVideoCleanup(videoRef, [isInline]);
|
useVideoCleanup(videoRef, [isInline]);
|
||||||
|
|
||||||
@ -193,11 +197,9 @@ const Video: FC<OwnProps> = ({
|
|||||||
<source src={fullMediaData} />
|
<source src={fullMediaData} />
|
||||||
</video>
|
</video>
|
||||||
)}
|
)}
|
||||||
{(isLoadAllowed && !isPlayAllowed && !shouldRenderSpinner) && (
|
{shouldRenderPlayButton && <i className={buildClassName('icon-large-play', playButtonClassNames)} />}
|
||||||
<i className="icon-large-play" />
|
|
||||||
)}
|
|
||||||
{shouldRenderSpinner && (
|
{shouldRenderSpinner && (
|
||||||
<div className={`media-loading ${spinnerClassNames}`}>
|
<div className={buildClassName('media-loading', spinnerClassNames)}>
|
||||||
<ProgressSpinner progress={transferProgress} onClick={handleClick} />
|
<ProgressSpinner progress={transferProgress} onClick={handleClick} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -22,8 +22,8 @@ type OwnProps = {
|
|||||||
message: ApiMessage;
|
message: ApiMessage;
|
||||||
observeIntersection?: ObserveFn;
|
observeIntersection?: ObserveFn;
|
||||||
noAvatars?: boolean;
|
noAvatars?: boolean;
|
||||||
shouldAutoLoad?: boolean;
|
canAutoLoad?: boolean;
|
||||||
shouldAutoPlay?: boolean;
|
canAutoPlay?: boolean;
|
||||||
inPreview?: boolean;
|
inPreview?: boolean;
|
||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
isDownloading?: boolean;
|
isDownloading?: boolean;
|
||||||
@ -36,8 +36,8 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
message,
|
message,
|
||||||
observeIntersection,
|
observeIntersection,
|
||||||
noAvatars,
|
noAvatars,
|
||||||
shouldAutoLoad,
|
canAutoLoad,
|
||||||
shouldAutoPlay,
|
canAutoPlay,
|
||||||
inPreview,
|
inPreview,
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
isDownloading = false,
|
isDownloading = false,
|
||||||
@ -91,7 +91,7 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
message={message}
|
message={message}
|
||||||
observeIntersection={observeIntersection}
|
observeIntersection={observeIntersection}
|
||||||
noAvatars={noAvatars}
|
noAvatars={noAvatars}
|
||||||
shouldAutoLoad={shouldAutoLoad}
|
canAutoLoad={canAutoLoad}
|
||||||
size={isSquarePhoto ? 'pictogram' : 'inline'}
|
size={isSquarePhoto ? 'pictogram' : 'inline'}
|
||||||
nonInteractive={!isMediaInteractive}
|
nonInteractive={!isMediaInteractive}
|
||||||
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
||||||
@ -114,8 +114,8 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
message={message}
|
message={message}
|
||||||
observeIntersection={observeIntersection!}
|
observeIntersection={observeIntersection!}
|
||||||
noAvatars={noAvatars}
|
noAvatars={noAvatars}
|
||||||
shouldAutoLoad={shouldAutoLoad}
|
canAutoLoad={canAutoLoad}
|
||||||
shouldAutoPlay={shouldAutoPlay}
|
canAutoPlay={canAutoPlay}
|
||||||
lastSyncTime={lastSyncTime}
|
lastSyncTime={lastSyncTime}
|
||||||
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
||||||
onCancelUpload={onCancelMediaTransfer}
|
onCancelUpload={onCancelMediaTransfer}
|
||||||
|
|||||||
@ -495,6 +495,14 @@
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: rgba(black, 0.25);
|
background: rgba(black, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.opacity-transition {
|
||||||
|
transition: opacity .15s ease;
|
||||||
|
|
||||||
|
&:not(.open) {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-download {
|
.icon-download {
|
||||||
|
|||||||
@ -15,6 +15,7 @@ type OwnProps = {
|
|||||||
step?: number;
|
step?: number;
|
||||||
label?: string;
|
label?: string;
|
||||||
value: number;
|
value: number;
|
||||||
|
renderValue?: (value: number) => string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
onChange: (value: number) => void;
|
onChange: (value: number) => void;
|
||||||
};
|
};
|
||||||
@ -26,6 +27,7 @@ const RangeSlider: FC<OwnProps> = ({
|
|||||||
step = 1,
|
step = 1,
|
||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
|
renderValue,
|
||||||
disabled,
|
disabled,
|
||||||
onChange,
|
onChange,
|
||||||
}) => {
|
}) => {
|
||||||
@ -46,7 +48,6 @@ const RangeSlider: FC<OwnProps> = ({
|
|||||||
const possibleValuesLength = (max - min) / step;
|
const possibleValuesLength = (max - min) / step;
|
||||||
return ((value - min) / possibleValuesLength) * 100;
|
return ((value - min) / possibleValuesLength) * 100;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}, [options, value, max, min, step]);
|
}, [options, value, max, min, step]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -55,7 +56,7 @@ const RangeSlider: FC<OwnProps> = ({
|
|||||||
<div className="slider-top-row" dir={lang.isRtl ? 'rtl' : undefined}>
|
<div className="slider-top-row" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||||
<span className="label" dir="auto">{label}</span>
|
<span className="label" dir="auto">{label}</span>
|
||||||
{!options && (
|
{!options && (
|
||||||
<span className="value" dir="auto">{value}</span>
|
<span className="value" dir="auto">{renderValue ? renderValue(value) : value}</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -32,6 +32,7 @@ export const MEDIA_CACHE_MAX_BYTES = 512 * 1024; // 512 KB
|
|||||||
export const CUSTOM_BG_CACHE_NAME = 'tt-custom-bg';
|
export const CUSTOM_BG_CACHE_NAME = 'tt-custom-bg';
|
||||||
export const LANG_CACHE_NAME = 'tt-lang-packs-v6';
|
export const LANG_CACHE_NAME = 'tt-lang-packs-v6';
|
||||||
export const ASSET_CACHE_NAME = 'tt-assets';
|
export const ASSET_CACHE_NAME = 'tt-assets';
|
||||||
|
export const AUTODOWNLOAD_FILESIZE_MB_LIMITS = [1, 5, 10, 50, 100, 500];
|
||||||
|
|
||||||
export const DOWNLOAD_WORKERS = 16;
|
export const DOWNLOAD_WORKERS = 16;
|
||||||
export const UPLOAD_WORKERS = 16;
|
export const UPLOAD_WORKERS = 16;
|
||||||
|
|||||||
@ -107,40 +107,7 @@ function readCache(initialState: GlobalState): GlobalState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cached) {
|
if (cached) {
|
||||||
// Pre-fill defaults in nested objects which may be missing in older cache
|
migrateCache(cached, initialState);
|
||||||
cached.settings.byKey = {
|
|
||||||
...initialState.settings.byKey,
|
|
||||||
...cached.settings.byKey,
|
|
||||||
};
|
|
||||||
cached.settings.themes = {
|
|
||||||
...initialState.settings.themes,
|
|
||||||
...cached.settings.themes,
|
|
||||||
};
|
|
||||||
cached.chatFolders = {
|
|
||||||
...initialState.chatFolders,
|
|
||||||
...cached.chatFolders,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!cached.stickers.greeting) {
|
|
||||||
cached.stickers.greeting = initialState.stickers.greeting;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cached.activeDownloads) {
|
|
||||||
cached.activeDownloads = {
|
|
||||||
byChatId: {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cached.serviceNotifications) {
|
|
||||||
cached.serviceNotifications = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cached.audioPlayer.volume === undefined) {
|
|
||||||
cached.audioPlayer.volume = DEFAULT_VOLUME;
|
|
||||||
}
|
|
||||||
if (cached.audioPlayer.playbackRate === undefined) {
|
|
||||||
cached.audioPlayer.playbackRate = DEFAULT_PLAYBACK_RATE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const newState = {
|
const newState = {
|
||||||
@ -159,6 +126,71 @@ function readCache(initialState: GlobalState): GlobalState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function migrateCache(cached: GlobalState, initialState: GlobalState) {
|
||||||
|
if ('shouldAutoDownloadMediaFromContacts' in cached.settings.byKey) {
|
||||||
|
const {
|
||||||
|
shouldAutoDownloadMediaFromContacts,
|
||||||
|
shouldAutoDownloadMediaInPrivateChats,
|
||||||
|
shouldAutoDownloadMediaInGroups,
|
||||||
|
shouldAutoDownloadMediaInChannels,
|
||||||
|
shouldAutoPlayVideos,
|
||||||
|
shouldAutoPlayGifs,
|
||||||
|
...rest
|
||||||
|
} = cached.settings.byKey;
|
||||||
|
|
||||||
|
cached.settings.byKey = {
|
||||||
|
...rest,
|
||||||
|
canAutoLoadPhotoFromContacts: shouldAutoDownloadMediaFromContacts,
|
||||||
|
canAutoLoadVideoFromContacts: shouldAutoDownloadMediaFromContacts,
|
||||||
|
canAutoLoadPhotoInPrivateChats: shouldAutoDownloadMediaInPrivateChats,
|
||||||
|
canAutoLoadVideoInPrivateChats: shouldAutoDownloadMediaInPrivateChats,
|
||||||
|
canAutoLoadPhotoInGroups: shouldAutoDownloadMediaInGroups,
|
||||||
|
canAutoLoadVideoInGroups: shouldAutoDownloadMediaInGroups,
|
||||||
|
canAutoLoadPhotoInChannels: shouldAutoDownloadMediaInChannels,
|
||||||
|
canAutoLoadVideoInChannels: shouldAutoDownloadMediaInChannels,
|
||||||
|
canAutoPlayVideos: shouldAutoPlayVideos,
|
||||||
|
canAutoPlayGifs: shouldAutoPlayGifs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
cached.settings.byKey = {
|
||||||
|
...initialState.settings.byKey,
|
||||||
|
...cached.settings.byKey,
|
||||||
|
};
|
||||||
|
|
||||||
|
cached.settings.themes = {
|
||||||
|
...initialState.settings.themes,
|
||||||
|
...cached.settings.themes,
|
||||||
|
};
|
||||||
|
|
||||||
|
cached.chatFolders = {
|
||||||
|
...initialState.chatFolders,
|
||||||
|
...cached.chatFolders,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!cached.stickers.greeting) {
|
||||||
|
cached.stickers.greeting = initialState.stickers.greeting;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cached.activeDownloads) {
|
||||||
|
cached.activeDownloads = {
|
||||||
|
byChatId: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cached.serviceNotifications) {
|
||||||
|
cached.serviceNotifications = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cached.audioPlayer.volume === undefined) {
|
||||||
|
cached.audioPlayer.volume = DEFAULT_VOLUME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cached.audioPlayer.playbackRate === undefined) {
|
||||||
|
cached.audioPlayer.playbackRate = DEFAULT_PLAYBACK_RATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateCache() {
|
function updateCache() {
|
||||||
if (!isCaching || isHeavyAnimating) {
|
if (!isCaching || isHeavyAnimating) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -139,15 +139,24 @@ export const INITIAL_STATE: GlobalState = {
|
|||||||
: (IS_MAC_OS ? MACOS_DEFAULT_MESSAGE_TEXT_SIZE_PX : DEFAULT_MESSAGE_TEXT_SIZE_PX),
|
: (IS_MAC_OS ? MACOS_DEFAULT_MESSAGE_TEXT_SIZE_PX : DEFAULT_MESSAGE_TEXT_SIZE_PX),
|
||||||
animationLevel: ANIMATION_LEVEL_DEFAULT,
|
animationLevel: ANIMATION_LEVEL_DEFAULT,
|
||||||
messageSendKeyCombo: 'enter',
|
messageSendKeyCombo: 'enter',
|
||||||
shouldAutoDownloadMediaFromContacts: true,
|
canAutoLoadPhotoFromContacts: true,
|
||||||
shouldAutoDownloadMediaInPrivateChats: true,
|
canAutoLoadPhotoInPrivateChats: true,
|
||||||
shouldAutoDownloadMediaInGroups: true,
|
canAutoLoadPhotoInGroups: true,
|
||||||
shouldAutoDownloadMediaInChannels: true,
|
canAutoLoadPhotoInChannels: true,
|
||||||
|
canAutoLoadVideoFromContacts: true,
|
||||||
|
canAutoLoadVideoInPrivateChats: true,
|
||||||
|
canAutoLoadVideoInGroups: true,
|
||||||
|
canAutoLoadVideoInChannels: true,
|
||||||
|
canAutoLoadFileFromContacts: false,
|
||||||
|
canAutoLoadFileInPrivateChats: false,
|
||||||
|
canAutoLoadFileInGroups: false,
|
||||||
|
canAutoLoadFileInChannels: false,
|
||||||
|
autoLoadFileMaxSizeMb: 10,
|
||||||
hasWebNotifications: true,
|
hasWebNotifications: true,
|
||||||
hasPushNotifications: true,
|
hasPushNotifications: true,
|
||||||
notificationSoundVolume: 5,
|
notificationSoundVolume: 5,
|
||||||
shouldAutoPlayGifs: true,
|
canAutoPlayGifs: true,
|
||||||
shouldAutoPlayVideos: true,
|
canAutoPlayVideos: true,
|
||||||
shouldSuggestStickers: true,
|
shouldSuggestStickers: true,
|
||||||
shouldLoopStickers: true,
|
shouldLoopStickers: true,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
|
|||||||
@ -30,6 +30,11 @@ import {
|
|||||||
isChatSuperGroup,
|
isChatSuperGroup,
|
||||||
getMessageVideo,
|
getMessageVideo,
|
||||||
getMessageWebPageVideo,
|
getMessageWebPageVideo,
|
||||||
|
getMessagePhoto,
|
||||||
|
getMessageAudio,
|
||||||
|
getMessageVoice,
|
||||||
|
getMessageDocument,
|
||||||
|
getMessageWebPagePhoto,
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
import { findLast } from '../../util/iteratees';
|
import { findLast } from '../../util/iteratees';
|
||||||
import { selectIsStickerFavorite } from './symbols';
|
import { selectIsStickerFavorite } from './symbols';
|
||||||
@ -732,41 +737,110 @@ export function selectNewestMessageWithBotKeyboardButtons(
|
|||||||
return messageId ? chatMessages[messageId] : undefined;
|
return messageId ? chatMessages[messageId] : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectShouldAutoLoadMedia(
|
export function selectCanAutoLoadMedia(
|
||||||
global: GlobalState, message: ApiMessage, chat: ApiChat, sender?: ApiChat | ApiUser,
|
global: GlobalState, message: ApiMessage, chat: ApiChat, sender?: ApiChat | ApiUser,
|
||||||
) {
|
) {
|
||||||
|
const isPhoto = Boolean(getMessagePhoto(message) || getMessageWebPagePhoto(message));
|
||||||
|
const isVideo = Boolean(getMessageVideo(message) || getMessageWebPageVideo(message));
|
||||||
|
const isFile = Boolean(getMessageAudio(message) || getMessageVoice(message) || getMessageDocument(message));
|
||||||
|
|
||||||
const {
|
const {
|
||||||
shouldAutoDownloadMediaFromContacts,
|
canAutoLoadPhotoFromContacts,
|
||||||
shouldAutoDownloadMediaInPrivateChats,
|
canAutoLoadPhotoInPrivateChats,
|
||||||
shouldAutoDownloadMediaInGroups,
|
canAutoLoadPhotoInGroups,
|
||||||
shouldAutoDownloadMediaInChannels,
|
canAutoLoadPhotoInChannels,
|
||||||
|
canAutoLoadVideoFromContacts,
|
||||||
|
canAutoLoadVideoInPrivateChats,
|
||||||
|
canAutoLoadVideoInGroups,
|
||||||
|
canAutoLoadVideoInChannels,
|
||||||
|
canAutoLoadFileFromContacts,
|
||||||
|
canAutoLoadFileInPrivateChats,
|
||||||
|
canAutoLoadFileInGroups,
|
||||||
|
canAutoLoadFileInChannels,
|
||||||
} = global.settings.byKey;
|
} = global.settings.byKey;
|
||||||
|
|
||||||
|
if (isPhoto) {
|
||||||
|
return canAutoLoadMedia({
|
||||||
|
global,
|
||||||
|
chat,
|
||||||
|
sender,
|
||||||
|
canAutoLoadMediaFromContacts: canAutoLoadPhotoFromContacts,
|
||||||
|
canAutoLoadMediaInPrivateChats: canAutoLoadPhotoInPrivateChats,
|
||||||
|
canAutoLoadMediaInGroups: canAutoLoadPhotoInGroups,
|
||||||
|
canAutoLoadMediaInChannels: canAutoLoadPhotoInChannels,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVideo) {
|
||||||
|
return canAutoLoadMedia({
|
||||||
|
global,
|
||||||
|
chat,
|
||||||
|
sender,
|
||||||
|
canAutoLoadMediaFromContacts: canAutoLoadVideoFromContacts,
|
||||||
|
canAutoLoadMediaInPrivateChats: canAutoLoadVideoInPrivateChats,
|
||||||
|
canAutoLoadMediaInGroups: canAutoLoadVideoInGroups,
|
||||||
|
canAutoLoadMediaInChannels: canAutoLoadVideoInChannels,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFile) {
|
||||||
|
return canAutoLoadMedia({
|
||||||
|
global,
|
||||||
|
chat,
|
||||||
|
sender,
|
||||||
|
canAutoLoadMediaFromContacts: canAutoLoadFileFromContacts,
|
||||||
|
canAutoLoadMediaInPrivateChats: canAutoLoadFileInPrivateChats,
|
||||||
|
canAutoLoadMediaInGroups: canAutoLoadFileInGroups,
|
||||||
|
canAutoLoadMediaInChannels: canAutoLoadFileInChannels,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canAutoLoadMedia({
|
||||||
|
global,
|
||||||
|
chat,
|
||||||
|
sender,
|
||||||
|
canAutoLoadMediaFromContacts,
|
||||||
|
canAutoLoadMediaInPrivateChats,
|
||||||
|
canAutoLoadMediaInGroups,
|
||||||
|
canAutoLoadMediaInChannels,
|
||||||
|
}: {
|
||||||
|
global: GlobalState;
|
||||||
|
chat: ApiChat;
|
||||||
|
canAutoLoadMediaFromContacts: boolean;
|
||||||
|
canAutoLoadMediaInPrivateChats: boolean;
|
||||||
|
canAutoLoadMediaInGroups: boolean;
|
||||||
|
canAutoLoadMediaInChannels: boolean;
|
||||||
|
sender?: ApiChat | ApiUser;
|
||||||
|
}) {
|
||||||
|
const isMediaFromContact = Boolean(sender && (
|
||||||
|
sender.id === global.currentUserId || selectIsUserOrChatContact(global, sender)
|
||||||
|
));
|
||||||
|
|
||||||
return Boolean(
|
return Boolean(
|
||||||
(shouldAutoDownloadMediaInPrivateChats && isUserId(chat.id))
|
(isMediaFromContact && canAutoLoadMediaFromContacts)
|
||||||
|| (shouldAutoDownloadMediaInGroups && isChatGroup(chat))
|
|| (!isMediaFromContact && canAutoLoadMediaInPrivateChats && isUserId(chat.id))
|
||||||
|| (shouldAutoDownloadMediaInChannels && isChatChannel(chat))
|
|| (canAutoLoadMediaInGroups && isChatGroup(chat))
|
||||||
|| (shouldAutoDownloadMediaFromContacts && sender && (
|
|| (canAutoLoadMediaInChannels && isChatChannel(chat)),
|
||||||
sender.id === global.currentUserId
|
|
||||||
|| selectIsUserOrChatContact(global, sender)
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectShouldAutoPlayMedia(global: GlobalState, message: ApiMessage) {
|
export function selectCanAutoPlayMedia(global: GlobalState, message: ApiMessage) {
|
||||||
const video = getMessageVideo(message) || getMessageWebPageVideo(message);
|
const video = getMessageVideo(message) || getMessageWebPageVideo(message);
|
||||||
if (!video) {
|
if (!video) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
shouldAutoPlayVideos,
|
canAutoPlayVideos,
|
||||||
shouldAutoPlayGifs,
|
canAutoPlayGifs,
|
||||||
} = global.settings.byKey;
|
} = global.settings.byKey;
|
||||||
|
|
||||||
const asGif = video.isGif || video.isRound;
|
const asGif = video.isGif || video.isRound;
|
||||||
|
|
||||||
return (shouldAutoPlayVideos && !asGif) || (shouldAutoPlayGifs && asGif);
|
return (canAutoPlayVideos && !asGif) || (canAutoPlayGifs && asGif);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectShouldLoopStickers(global: GlobalState) {
|
export function selectShouldLoopStickers(global: GlobalState) {
|
||||||
|
|||||||
@ -56,12 +56,21 @@ export interface ISettings extends NotifySettings, Record<string, any> {
|
|||||||
messageTextSize: number;
|
messageTextSize: number;
|
||||||
animationLevel: 0 | 1 | 2;
|
animationLevel: 0 | 1 | 2;
|
||||||
messageSendKeyCombo: 'enter' | 'ctrl-enter';
|
messageSendKeyCombo: 'enter' | 'ctrl-enter';
|
||||||
shouldAutoDownloadMediaFromContacts: boolean;
|
canAutoLoadPhotoFromContacts: boolean;
|
||||||
shouldAutoDownloadMediaInPrivateChats: boolean;
|
canAutoLoadPhotoInPrivateChats: boolean;
|
||||||
shouldAutoDownloadMediaInGroups: boolean;
|
canAutoLoadPhotoInGroups: boolean;
|
||||||
shouldAutoDownloadMediaInChannels: boolean;
|
canAutoLoadPhotoInChannels: boolean;
|
||||||
shouldAutoPlayGifs: boolean;
|
canAutoLoadVideoFromContacts: boolean;
|
||||||
shouldAutoPlayVideos: boolean;
|
canAutoLoadVideoInPrivateChats: boolean;
|
||||||
|
canAutoLoadVideoInGroups: boolean;
|
||||||
|
canAutoLoadVideoInChannels: boolean;
|
||||||
|
canAutoLoadFileFromContacts: boolean;
|
||||||
|
canAutoLoadFileInPrivateChats: boolean;
|
||||||
|
canAutoLoadFileInGroups: boolean;
|
||||||
|
canAutoLoadFileInChannels: boolean;
|
||||||
|
autoLoadFileMaxSizeMb: number;
|
||||||
|
canAutoPlayGifs: boolean;
|
||||||
|
canAutoPlayVideos: boolean;
|
||||||
shouldSuggestStickers: boolean;
|
shouldSuggestStickers: boolean;
|
||||||
shouldLoopStickers: boolean;
|
shouldLoopStickers: boolean;
|
||||||
hasPassword?: boolean;
|
hasPassword?: boolean;
|
||||||
@ -145,6 +154,7 @@ export enum SettingsScreens {
|
|||||||
Main,
|
Main,
|
||||||
EditProfile,
|
EditProfile,
|
||||||
Notifications,
|
Notifications,
|
||||||
|
DataStorage,
|
||||||
Language,
|
Language,
|
||||||
General,
|
General,
|
||||||
GeneralChatBackground,
|
GeneralChatBackground,
|
||||||
|
|||||||
@ -476,6 +476,10 @@ export default {
|
|||||||
key: 'Notifications',
|
key: 'Notifications',
|
||||||
value: 'Notifications',
|
value: 'Notifications',
|
||||||
},
|
},
|
||||||
|
DataSettings: {
|
||||||
|
key: 'DataSettings',
|
||||||
|
value: 'Data and Storage',
|
||||||
|
},
|
||||||
PrivacySettings: {
|
PrivacySettings: {
|
||||||
key: 'PrivacySettings',
|
key: 'PrivacySettings',
|
||||||
value: 'Privacy and Security',
|
value: 'Privacy and Security',
|
||||||
@ -1805,4 +1809,16 @@ export default {
|
|||||||
key: 'PleaseEnterPassword',
|
key: 'PleaseEnterPassword',
|
||||||
value: 'Enter your new password',
|
value: 'Enter your new password',
|
||||||
},
|
},
|
||||||
|
AutoDownloadPhotosTitle: {
|
||||||
|
key: 'AutoDownloadPhotosTitle',
|
||||||
|
value: 'Auto-download photos',
|
||||||
|
},
|
||||||
|
AutoDownloadVideosTitle: {
|
||||||
|
key: 'AutoDownloadVideosTitle',
|
||||||
|
value: 'Auto-download videos and GIFs',
|
||||||
|
},
|
||||||
|
AutoDownloadFilesTitle: {
|
||||||
|
key: 'AutoDownloadFilesTitle',
|
||||||
|
value: 'Auto-download files and music',
|
||||||
|
},
|
||||||
} as ApiLangPack;
|
} as ApiLangPack;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user