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