Merge branch 'autodownload'
This commit is contained in:
commit
142e26e791
@ -734,7 +734,7 @@ export default class AppSearchSuper {
|
||||
showSender,
|
||||
searchContext: this.copySearchContext(inputFilter),
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
noAutoDownload: true
|
||||
autoDownloadSize: 0
|
||||
});
|
||||
|
||||
if((['audio', 'voice', 'round'] as MyDocument['type'][]).includes(document.type)) {
|
||||
|
@ -26,9 +26,10 @@ import { joinElementsWith } from "../lib/langPack";
|
||||
import { MiddleEllipsisElement } from "./middleEllipsis";
|
||||
import htmlToSpan from "../helpers/dom/htmlToSpan";
|
||||
import { formatFullSentTime } from "../helpers/date";
|
||||
import { clamp, formatBytes } from "../helpers/number";
|
||||
import throttleWithRaf from "../helpers/schedulers/throttleWithRaf";
|
||||
import { NULL_PEER_ID } from "../lib/mtproto/mtproto_config";
|
||||
import formatBytes from "../helpers/formatBytes";
|
||||
import { clamp } from "../helpers/number";
|
||||
|
||||
rootScope.addEventListener('messages_media_read', ({mids, peerId}) => {
|
||||
mids.forEach(mid => {
|
||||
@ -523,7 +524,8 @@ export default class AudioElement extends HTMLElement {
|
||||
if(!isOutgoing) {
|
||||
let preloader: ProgressivePreloader = this.preloader;
|
||||
|
||||
onLoad(doc.type !== 'audio' && !this.noAutoDownload);
|
||||
const autoDownload = doc.type !== 'audio'/* || !this.noAutoDownload */;
|
||||
onLoad(autoDownload);
|
||||
|
||||
const r = (shouldPlay: boolean) => {
|
||||
if(this.audio.src) {
|
||||
@ -634,7 +636,7 @@ export default class AudioElement extends HTMLElement {
|
||||
};
|
||||
|
||||
if(!this.audio?.src) {
|
||||
if(doc.type !== 'audio' && !this.noAutoDownload) {
|
||||
if(autoDownload) {
|
||||
r(false);
|
||||
} else {
|
||||
attachClickEvent(toggle, () => {
|
||||
|
@ -3106,7 +3106,7 @@ export default class ChatBubbles {
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
chat: this.chat,
|
||||
loadPromises,
|
||||
noAutoDownload: this.chat.noAutoDownloadMedia,
|
||||
autoDownload: this.chat.autoDownload,
|
||||
});
|
||||
|
||||
break;
|
||||
@ -3123,7 +3123,7 @@ export default class ChatBubbles {
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
middleware: this.getMiddleware(),
|
||||
loadPromises,
|
||||
noAutoDownload: this.chat.noAutoDownloadMedia,
|
||||
autoDownloadSize: this.chat.autoDownload.photo,
|
||||
});
|
||||
|
||||
break;
|
||||
@ -3178,13 +3178,13 @@ export default class ChatBubbles {
|
||||
isOut,
|
||||
group: CHAT_ANIMATION_GROUP,
|
||||
loadPromises,
|
||||
noAutoDownload: this.chat.noAutoDownloadMedia,
|
||||
autoDownloadSize: this.chat.autoDownload.video,
|
||||
});
|
||||
//}
|
||||
} else {
|
||||
const docDiv = wrapDocument({
|
||||
message,
|
||||
noAutoDownload: this.chat.noAutoDownloadMedia,
|
||||
autoDownloadSize: this.chat.autoDownload.file,
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
loadPromises
|
||||
});
|
||||
@ -3269,7 +3269,7 @@ export default class ChatBubbles {
|
||||
middleware: this.getMiddleware(),
|
||||
loadPromises,
|
||||
withoutPreloader: isSquare,
|
||||
noAutoDownload: this.chat.noAutoDownloadMedia,
|
||||
autoDownloadSize: this.chat.autoDownload.photo,
|
||||
});
|
||||
}
|
||||
|
||||
@ -3350,7 +3350,7 @@ export default class ChatBubbles {
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
chat: this.chat,
|
||||
loadPromises,
|
||||
noAutoDownload: this.chat.noAutoDownloadMedia,
|
||||
autoDownload: this.chat.autoDownload,
|
||||
});
|
||||
} else {
|
||||
const withTail = !IS_ANDROID && !IS_APPLE && !isRound && canHaveTail && !withReplies && USE_MEDIA_TAILS;
|
||||
@ -3367,7 +3367,7 @@ export default class ChatBubbles {
|
||||
middleware: this.getMiddleware(),
|
||||
group: CHAT_ANIMATION_GROUP,
|
||||
loadPromises,
|
||||
noAutoDownload: this.chat.noAutoDownloadMedia,
|
||||
autoDownloadSize: this.chat.autoDownload.video,
|
||||
searchContext: isRound ? {
|
||||
peerId: this.peerId,
|
||||
inputFilter: {_: 'inputMessagesFilterRoundVoice'},
|
||||
@ -3386,7 +3386,7 @@ export default class ChatBubbles {
|
||||
messageDiv,
|
||||
chat: this.chat,
|
||||
loadPromises,
|
||||
noAutoDownload: this.chat.noAutoDownloadMedia,
|
||||
autoDownloadSize: this.chat.autoDownload.file,
|
||||
lazyLoadQueue: this.lazyLoadQueue,
|
||||
searchContext: doc.type === 'voice' || doc.type === 'audio' ? {
|
||||
peerId: this.peerId,
|
||||
|
@ -43,6 +43,7 @@ import renderImageFromUrl from "../../helpers/dom/renderImageFromUrl";
|
||||
import mediaSizes from "../../helpers/mediaSizes";
|
||||
import ChatSearch from "./search";
|
||||
import { IS_TOUCH_SUPPORTED } from "../../environment/touchSupport";
|
||||
import getAutoDownloadSettingsByPeerId, { ChatAutoDownloadSettings } from "../../helpers/autoDownload";
|
||||
|
||||
export type ChatType = 'chat' | 'pinned' | 'replies' | 'discussion' | 'scheduled';
|
||||
|
||||
@ -70,12 +71,12 @@ export default class Chat extends EventListenerBase<{
|
||||
|
||||
public type: ChatType;
|
||||
|
||||
public noAutoDownloadMedia: boolean;
|
||||
public noForwards: boolean;
|
||||
|
||||
public inited: boolean;
|
||||
|
||||
public isRestricted: boolean;
|
||||
public autoDownload: ChatAutoDownloadSettings;
|
||||
|
||||
constructor(
|
||||
public appImManager: AppImManager,
|
||||
@ -351,28 +352,7 @@ export default class Chat extends EventListenerBase<{
|
||||
}
|
||||
|
||||
public setAutoDownloadMedia() {
|
||||
const peerId = this.peerId;
|
||||
if(!peerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let type: keyof State['settings']['autoDownload'];
|
||||
|
||||
if(!peerId.isUser()) {
|
||||
if(peerId.isBroadcast()) {
|
||||
type = 'channels';
|
||||
} else {
|
||||
type = 'groups';
|
||||
}
|
||||
} else {
|
||||
if(peerId.isContact()) {
|
||||
type = 'contacts';
|
||||
} else {
|
||||
type = 'private';
|
||||
}
|
||||
}
|
||||
|
||||
this.noAutoDownloadMedia = !rootScope.settings.autoDownload[type];
|
||||
this.autoDownload = getAutoDownloadSettingsByPeerId(this.peerId);
|
||||
}
|
||||
|
||||
public setMessageId(messageId?: number) {
|
||||
|
53
src/components/sidebarLeft/tabs/autoDownload/file.ts
Normal file
53
src/components/sidebarLeft/tabs/autoDownload/file.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import formatBytes from "../../../../helpers/formatBytes";
|
||||
import debounce from "../../../../helpers/schedulers/debounce";
|
||||
import appStateManager from "../../../../lib/appManagers/appStateManager";
|
||||
import I18n from "../../../../lib/langPack";
|
||||
import rootScope from "../../../../lib/rootScope";
|
||||
import { SliderSuperTabEventable } from "../../../sliderTab";
|
||||
import { RangeSettingSelector } from "../generalSettings";
|
||||
import { autoDownloadPeerTypeSection } from "./photo";
|
||||
|
||||
export default class AppAutoDownloadFileTab extends SliderSuperTabEventable {
|
||||
protected init() {
|
||||
this.header.classList.add('with-border');
|
||||
this.setTitle('AutoDownloadFiles');
|
||||
|
||||
const debouncedSave = debounce((sizeMax: number) => {
|
||||
appStateManager.setByKey('settings.autoDownloadNew.file_size_max', sizeMax);
|
||||
}, 200, false, true);
|
||||
|
||||
const section = autoDownloadPeerTypeSection('file', 'AutoDownloadFilesTitle');
|
||||
|
||||
const MIN = 512 * 1024;
|
||||
// const MAX = 2 * 1024 * 1024 * 1024;
|
||||
const MAX = 20 * 1024 * 1024;
|
||||
const MAX_RANGE = MAX - MIN;
|
||||
|
||||
const sizeMax = rootScope.settings.autoDownloadNew.file_size_max;
|
||||
const value = Math.sqrt(Math.sqrt((sizeMax - MIN) / MAX_RANGE));
|
||||
const upTo = new I18n.IntlElement({
|
||||
key: 'AutodownloadSizeLimitUpTo',
|
||||
args: [formatBytes(sizeMax)]
|
||||
});
|
||||
const range = new RangeSettingSelector('AutoDownloadMaxFileSize', 0.01, value, 0, 1, false);
|
||||
range.onChange = (value) => {
|
||||
const sizeMax = (value ** 4 * MAX_RANGE + MIN) | 0;
|
||||
|
||||
upTo.compareAndUpdate({args: [formatBytes(sizeMax)]});
|
||||
|
||||
debouncedSave(sizeMax);
|
||||
};
|
||||
|
||||
range.valueContainer.append(upTo.element);
|
||||
|
||||
section.content.append(range.container);
|
||||
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
}
|
59
src/components/sidebarLeft/tabs/autoDownload/photo.ts
Normal file
59
src/components/sidebarLeft/tabs/autoDownload/photo.ts
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { SettingSection } from "../..";
|
||||
import { LangPackKey } from "../../../../lib/langPack";
|
||||
import CheckboxField from "../../../checkboxField";
|
||||
import { SliderSuperTabEventable } from "../../../sliderTab";
|
||||
|
||||
export function autoDownloadPeerTypeSection(type: 'photo' | 'video' | 'file', title: LangPackKey) {
|
||||
const section = new SettingSection({name: title});
|
||||
|
||||
const key = 'settings.autoDownload.' + type + '.';
|
||||
const contactsCheckboxField = new CheckboxField({
|
||||
text: 'AutodownloadContacts',
|
||||
name: 'contacts',
|
||||
stateKey: key + 'contacts',
|
||||
withRipple: true
|
||||
});
|
||||
const privateCheckboxField = new CheckboxField({
|
||||
text: 'AutodownloadPrivateChats',
|
||||
name: 'private',
|
||||
stateKey: key + 'private',
|
||||
withRipple: true
|
||||
});
|
||||
const groupsCheckboxField = new CheckboxField({
|
||||
text: 'AutodownloadGroupChats',
|
||||
name: 'groups',
|
||||
stateKey: key + 'groups',
|
||||
withRipple: true
|
||||
});
|
||||
const channelsCheckboxField = new CheckboxField({
|
||||
text: 'AutodownloadChannels',
|
||||
name: 'channels',
|
||||
stateKey: key + 'channels',
|
||||
withRipple: true
|
||||
});
|
||||
|
||||
section.content.append(
|
||||
contactsCheckboxField.label,
|
||||
privateCheckboxField.label,
|
||||
groupsCheckboxField.label,
|
||||
channelsCheckboxField.label
|
||||
);
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
export default class AppAutoDownloadPhotoTab extends SliderSuperTabEventable {
|
||||
protected init() {
|
||||
this.header.classList.add('with-border');
|
||||
this.setTitle('AutoDownloadPhotos');
|
||||
|
||||
const section = autoDownloadPeerTypeSection('photo', 'AutoDownloadPhotosTitle');
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
}
|
18
src/components/sidebarLeft/tabs/autoDownload/video.ts
Normal file
18
src/components/sidebarLeft/tabs/autoDownload/video.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { SliderSuperTabEventable } from "../../../sliderTab";
|
||||
import { autoDownloadPeerTypeSection } from "./photo";
|
||||
|
||||
export default class AppAutoDownloadVideoTab extends SliderSuperTabEventable {
|
||||
protected init() {
|
||||
this.header.classList.add('with-border');
|
||||
this.setTitle('AutoDownloadVideos');
|
||||
|
||||
const section = autoDownloadPeerTypeSection('video', 'AutoDownloadVideosTitle');
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
}
|
196
src/components/sidebarLeft/tabs/dataAndStorage.ts
Normal file
196
src/components/sidebarLeft/tabs/dataAndStorage.ts
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { SettingSection } from "..";
|
||||
import { attachClickEvent } from "../../../helpers/dom/clickEvent";
|
||||
import replaceContent from "../../../helpers/dom/replaceContent";
|
||||
import toggleDisability from "../../../helpers/dom/toggleDisability";
|
||||
import formatBytes from "../../../helpers/formatBytes";
|
||||
import { copy, deepEqual } from "../../../helpers/object";
|
||||
import appStateManager, { AutoDownloadPeerTypeSettings, STATE_INIT } from "../../../lib/appManagers/appStateManager";
|
||||
import { FormatterArguments, i18n, join, LangPackKey } from "../../../lib/langPack";
|
||||
import rootScope from "../../../lib/rootScope";
|
||||
import Button from "../../button";
|
||||
import CheckboxField from "../../checkboxField";
|
||||
import confirmationPopup from "../../confirmationPopup";
|
||||
import Row from "../../row";
|
||||
import { SliderSuperTabEventable, SliderSuperTabEventableConstructable } from "../../sliderTab";
|
||||
import AppAutoDownloadFileTab from "./autoDownload/file";
|
||||
import AppAutoDownloadPhotoTab from "./autoDownload/photo";
|
||||
import AppAutoDownloadVideoTab from "./autoDownload/video";
|
||||
|
||||
const AUTO_DOWNLOAD_FOR_KEYS: {[k in keyof AutoDownloadPeerTypeSettings]: LangPackKey} = {
|
||||
contacts: 'AutoDownloadContacts',
|
||||
private: 'AutoDownloadPm',
|
||||
groups: 'AutoDownloadGroups',
|
||||
channels: 'AutoDownloadChannels'
|
||||
};
|
||||
|
||||
export default class AppDataAndStorageTab extends SliderSuperTabEventable {
|
||||
protected async init() {
|
||||
this.header.classList.add('with-border');
|
||||
this.setTitle('DataSettings');
|
||||
|
||||
{
|
||||
const section = new SettingSection({name: 'AutomaticMediaDownload', caption: 'AutoDownloadAudioInfo'});
|
||||
|
||||
const state = await appStateManager.getState();
|
||||
|
||||
const autoCheckboxField = new CheckboxField({
|
||||
text: 'AutoDownloadMedia',
|
||||
name: 'auto',
|
||||
checked: !state.settings.autoDownloadNew.pFlags.disabled,
|
||||
withRipple: true
|
||||
});
|
||||
|
||||
const onChange = () => {
|
||||
toggleDisability([resetButton],
|
||||
deepEqual(state.settings.autoDownload, STATE_INIT.settings.autoDownload) &&
|
||||
deepEqual(state.settings.autoDownloadNew, STATE_INIT.settings.autoDownloadNew));
|
||||
};
|
||||
|
||||
const setSubtitles = () => {
|
||||
this.setAutoDownloadSubtitle(photoRow, state.settings.autoDownload.photo, /* state.settings.autoDownloadNew.photo_size_max */);
|
||||
this.setAutoDownloadSubtitle(videoRow, state.settings.autoDownload.video/* , state.settings.autoDownloadNew.video_size_max */);
|
||||
this.setAutoDownloadSubtitle(fileRow, state.settings.autoDownload.file, state.settings.autoDownloadNew.file_size_max);
|
||||
};
|
||||
|
||||
const openTab = (tabConstructor: SliderSuperTabEventableConstructable) => {
|
||||
const tab = new tabConstructor(this.slider, true);
|
||||
tab.open();
|
||||
|
||||
this.listenerSetter.add(tab.eventListener)('destroy', () => {
|
||||
setSubtitles();
|
||||
onChange();
|
||||
}, {once: true});
|
||||
};
|
||||
|
||||
const photoRow = new Row({
|
||||
titleLangKey: 'AutoDownloadPhotos',
|
||||
subtitle: '',
|
||||
clickable: () => {
|
||||
openTab(AppAutoDownloadPhotoTab);
|
||||
}
|
||||
});
|
||||
|
||||
const videoRow = new Row({
|
||||
titleLangKey: 'AutoDownloadVideos',
|
||||
subtitle: '',
|
||||
clickable: () => {
|
||||
openTab(AppAutoDownloadVideoTab);
|
||||
}
|
||||
});
|
||||
|
||||
const fileRow = new Row({
|
||||
titleLangKey: 'AutoDownloadFiles',
|
||||
subtitle: '',
|
||||
clickable: () => {
|
||||
openTab(AppAutoDownloadFileTab);
|
||||
}
|
||||
});
|
||||
|
||||
const resetButton = Button('btn-primary btn-transparent primary', {icon: 'delete', text: 'ResetAutomaticMediaDownload'});
|
||||
attachClickEvent(resetButton, () => {
|
||||
confirmationPopup({
|
||||
titleLangKey: 'ResetAutomaticMediaDownloadAlertTitle',
|
||||
descriptionLangKey: 'ResetAutomaticMediaDownloadAlert',
|
||||
button: {
|
||||
langKey: 'Reset'
|
||||
}
|
||||
}).then(() => {
|
||||
rootScope.settings.autoDownloadNew = copy(STATE_INIT.settings.autoDownloadNew);
|
||||
rootScope.settings.autoDownload = copy(STATE_INIT.settings.autoDownload);
|
||||
appStateManager.pushToState('settings', rootScope.settings);
|
||||
rootScope.dispatchEvent('settings_updated', {key: 'settings', value: rootScope.settings});
|
||||
|
||||
setSubtitles();
|
||||
autoCheckboxField.checked = !state.settings.autoDownloadNew.pFlags.disabled;
|
||||
});
|
||||
});
|
||||
|
||||
const onDisabledChange = () => {
|
||||
const disabled = !autoCheckboxField.checked;
|
||||
|
||||
const settings = rootScope.settings;
|
||||
if(disabled) {
|
||||
settings.autoDownloadNew.pFlags.disabled = true;
|
||||
} else {
|
||||
delete settings.autoDownloadNew.pFlags.disabled;
|
||||
}
|
||||
|
||||
[photoRow, videoRow, fileRow].forEach(row => {
|
||||
row.container.classList.toggle('is-disabled', disabled);
|
||||
});
|
||||
|
||||
appStateManager.pushToState('settings', settings);
|
||||
rootScope.dispatchEvent('settings_updated', {key: 'settings', value: settings});
|
||||
|
||||
onChange();
|
||||
};
|
||||
|
||||
autoCheckboxField.input.addEventListener('change', onDisabledChange);
|
||||
onDisabledChange();
|
||||
setSubtitles();
|
||||
|
||||
section.content.append(
|
||||
autoCheckboxField.label,
|
||||
photoRow.container,
|
||||
videoRow.container,
|
||||
fileRow.container,
|
||||
resetButton
|
||||
);
|
||||
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
|
||||
{
|
||||
const section = new SettingSection({name: 'AutoplayMedia'});
|
||||
|
||||
const gifsCheckboxField = new CheckboxField({
|
||||
text: 'AutoplayGIF',
|
||||
name: 'gifs',
|
||||
stateKey: 'settings.autoPlay.gifs',
|
||||
withRipple: true
|
||||
});
|
||||
const videosCheckboxField = new CheckboxField({
|
||||
text: 'AutoplayVideo',
|
||||
name: 'videos',
|
||||
stateKey: 'settings.autoPlay.videos',
|
||||
withRipple: true
|
||||
});
|
||||
|
||||
section.content.append(gifsCheckboxField.label, videosCheckboxField.label);
|
||||
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
}
|
||||
|
||||
private setAutoDownloadSubtitle(row: Row, settings: AutoDownloadPeerTypeSettings, sizeMax?: number) {
|
||||
let key: LangPackKey, args: FormatterArguments = [];
|
||||
|
||||
const peerKeys = Object.keys(settings) as (keyof typeof AUTO_DOWNLOAD_FOR_KEYS)[];
|
||||
const enabledKeys = peerKeys.map(key => settings[key] ? AUTO_DOWNLOAD_FOR_KEYS[key] : undefined).filter(Boolean);
|
||||
if(!enabledKeys.length || sizeMax === 0) {
|
||||
key = 'AutoDownloadOff';
|
||||
} else {
|
||||
const isAll = enabledKeys.length === peerKeys.length;
|
||||
if(sizeMax !== undefined) {
|
||||
key = isAll ? 'AutoDownloadUpToOnAllChats' : 'AutoDownloadOnUpToFor';
|
||||
args.push(formatBytes(sizeMax));
|
||||
} else {
|
||||
key = isAll ? 'AutoDownloadOnAllChats' : 'AutoDownloadOnFor';
|
||||
}
|
||||
|
||||
if(!isAll) {
|
||||
const fragment = document.createElement('span');
|
||||
fragment.append(...join(enabledKeys.map(key => i18n(key)), true, false));
|
||||
args.push(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
replaceContent(row.subtitle, i18n(key, args));
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { generateSection } from "..";
|
||||
import { generateSection, SettingSection } from "..";
|
||||
import RangeSelector from "../../rangeSelector";
|
||||
import Button from "../../button";
|
||||
import CheckboxField from "../../checkboxField";
|
||||
@ -31,11 +31,19 @@ import AppQuickReactionTab from "./quickReaction";
|
||||
|
||||
export class RangeSettingSelector {
|
||||
public container: HTMLDivElement;
|
||||
public valueContainer: HTMLElement;
|
||||
private range: RangeSelector;
|
||||
|
||||
public onChange: (value: number) => void;
|
||||
|
||||
constructor(name: LangPackKey, step: number, initialValue: number, minValue: number, maxValue: number) {
|
||||
constructor(
|
||||
name: LangPackKey,
|
||||
step: number,
|
||||
initialValue: number,
|
||||
minValue: number,
|
||||
maxValue: number,
|
||||
writeValue = true
|
||||
) {
|
||||
const BASE_CLASS = 'range-setting-selector';
|
||||
this.container = document.createElement('div');
|
||||
this.container.classList.add(BASE_CLASS);
|
||||
@ -47,9 +55,12 @@ export class RangeSettingSelector {
|
||||
nameDiv.classList.add(BASE_CLASS + '-name');
|
||||
_i18n(nameDiv, name);
|
||||
|
||||
const valueDiv = document.createElement('div');
|
||||
const valueDiv = this.valueContainer = document.createElement('div');
|
||||
valueDiv.classList.add(BASE_CLASS + '-value');
|
||||
valueDiv.innerHTML = '' + initialValue;
|
||||
|
||||
if(writeValue) {
|
||||
valueDiv.innerHTML = '' + initialValue;
|
||||
}
|
||||
|
||||
details.append(nameDiv, valueDiv);
|
||||
|
||||
@ -65,8 +76,10 @@ export class RangeSettingSelector {
|
||||
this.onChange(value);
|
||||
}
|
||||
|
||||
//console.log('font size scrub:', value);
|
||||
valueDiv.innerText = '' + value;
|
||||
if(writeValue) {
|
||||
//console.log('font size scrub:', value);
|
||||
valueDiv.innerText = '' + value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -213,58 +226,6 @@ export default class AppGeneralSettingsTab extends SliderSuperTabEventable {
|
||||
container.append(form);
|
||||
}
|
||||
|
||||
{
|
||||
const container = section('AutoDownloadMedia');
|
||||
//container.classList.add('sidebar-left-section-disabled');
|
||||
|
||||
const contactsCheckboxField = new CheckboxField({
|
||||
text: 'AutodownloadContacts',
|
||||
name: 'contacts',
|
||||
stateKey: 'settings.autoDownload.contacts',
|
||||
withRipple: true
|
||||
});
|
||||
const privateCheckboxField = new CheckboxField({
|
||||
text: 'AutodownloadPrivateChats',
|
||||
name: 'private',
|
||||
stateKey: 'settings.autoDownload.private',
|
||||
withRipple: true
|
||||
});
|
||||
const groupsCheckboxField = new CheckboxField({
|
||||
text: 'AutodownloadGroupChats',
|
||||
name: 'groups',
|
||||
stateKey: 'settings.autoDownload.groups',
|
||||
withRipple: true
|
||||
});
|
||||
const channelsCheckboxField = new CheckboxField({
|
||||
text: 'AutodownloadChannels',
|
||||
name: 'channels',
|
||||
stateKey: 'settings.autoDownload.channels',
|
||||
withRipple: true
|
||||
});
|
||||
|
||||
container.append(contactsCheckboxField.label, privateCheckboxField.label, groupsCheckboxField.label, channelsCheckboxField.label);
|
||||
}
|
||||
|
||||
{
|
||||
const container = section('General.AutoplayMedia');
|
||||
//container.classList.add('sidebar-left-section-disabled');
|
||||
|
||||
const gifsCheckboxField = new CheckboxField({
|
||||
text: 'AutoplayGIF',
|
||||
name: 'gifs',
|
||||
stateKey: 'settings.autoPlay.gifs',
|
||||
withRipple: true
|
||||
});
|
||||
const videosCheckboxField = new CheckboxField({
|
||||
text: 'AutoplayVideo',
|
||||
name: 'videos',
|
||||
stateKey: 'settings.autoPlay.videos',
|
||||
withRipple: true
|
||||
});
|
||||
|
||||
container.append(gifsCheckboxField.label, videosCheckboxField.label);
|
||||
}
|
||||
|
||||
{
|
||||
const container = section('Emoji');
|
||||
|
||||
@ -285,7 +246,7 @@ export default class AppGeneralSettingsTab extends SliderSuperTabEventable {
|
||||
}
|
||||
|
||||
{
|
||||
const container = section('Telegram.InstalledStickerPacksController');
|
||||
const section = new SettingSection({name: 'Telegram.InstalledStickerPacksController', caption: 'StickersBotInfo'});
|
||||
|
||||
const reactionsRow = new Row({
|
||||
titleLangKey: 'DoubleTapSetting',
|
||||
@ -324,6 +285,8 @@ export default class AppGeneralSettingsTab extends SliderSuperTabEventable {
|
||||
|
||||
const stickerSets: {[id: string]: Row} = {};
|
||||
|
||||
const stickersContent = section.generateContentElement();
|
||||
|
||||
const lazyLoadQueue = new LazyLoadQueue();
|
||||
const renderStickerSet = (stickerSet: StickerSet.stickerSet, method: 'append' | 'prepend' = 'append') => {
|
||||
const row = new Row({
|
||||
@ -353,7 +316,7 @@ export default class AppGeneralSettingsTab extends SliderSuperTabEventable {
|
||||
|
||||
row.container.append(div);
|
||||
|
||||
container[method](row.container);
|
||||
stickersContent[method](row.container);
|
||||
};
|
||||
|
||||
appStickersManager.getAllStickers().then(allStickers => {
|
||||
@ -380,7 +343,8 @@ export default class AppGeneralSettingsTab extends SliderSuperTabEventable {
|
||||
}
|
||||
});
|
||||
|
||||
container.append(reactionsRow.container, suggestCheckboxField.label, loopCheckboxField.label);
|
||||
section.content.append(reactionsRow.container, suggestCheckboxField.label, loopCheckboxField.label);
|
||||
this.scrollable.append(section.container);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,13 +38,14 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTabEventable {
|
||||
private authorizations: Authorization.authorization[];
|
||||
|
||||
protected init() {
|
||||
this.header.classList.add('with-border');
|
||||
this.container.classList.add('dont-u-dare-block-me');
|
||||
this.setTitle('PrivacySettings');
|
||||
|
||||
const SUBTITLE: LangPackKey = 'Loading';
|
||||
|
||||
{
|
||||
const section = new SettingSection({noDelimiter: true});
|
||||
const section = new SettingSection({noDelimiter: true, caption: 'SessionsInfo'});
|
||||
|
||||
let blockedPeerIds: PeerId[];
|
||||
const blockedUsersRow = new Row({
|
||||
@ -141,7 +142,7 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTabEventable {
|
||||
}
|
||||
|
||||
{
|
||||
const section = new SettingSection({name: 'PrivacyTitle'});
|
||||
const section = new SettingSection({name: 'PrivacyTitle', caption: 'GroupsAndChannelsHelp'});
|
||||
|
||||
section.content.classList.add('privacy-navigation-container');
|
||||
|
||||
@ -218,7 +219,14 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTabEventable {
|
||||
});
|
||||
};
|
||||
|
||||
section.content.append(numberVisibilityRow.container, lastSeenTimeRow.container, photoVisibilityRow.container, callRow.container, linkAccountRow.container, groupChatsAddRow.container);
|
||||
section.content.append(
|
||||
numberVisibilityRow.container,
|
||||
lastSeenTimeRow.container,
|
||||
photoVisibilityRow.container,
|
||||
callRow.container,
|
||||
linkAccountRow.container,
|
||||
groupChatsAddRow.container
|
||||
);
|
||||
this.scrollable.append(section.container);
|
||||
|
||||
for(const key in rowsByKeys) {
|
||||
|
@ -19,6 +19,7 @@ import PeerTitle from "../../peerTitle";
|
||||
import AppLanguageTab from "./language";
|
||||
import lottieLoader from "../../../lib/rlottie/lottieLoader";
|
||||
import PopupPeer from "../../popups/peer";
|
||||
import AppDataAndStorageTab from "./dataAndStorage";
|
||||
//import AppMediaViewer from "../../appMediaViewerNew";
|
||||
|
||||
export default class AppSettingsTab extends SliderSuperTab {
|
||||
@ -31,6 +32,7 @@ export default class AppSettingsTab extends SliderSuperTab {
|
||||
folders: HTMLButtonElement,
|
||||
general: HTMLButtonElement,
|
||||
notifications: HTMLButtonElement,
|
||||
storage: HTMLButtonElement,
|
||||
privacy: HTMLButtonElement,
|
||||
language: HTMLButtonElement
|
||||
} = {} as any;
|
||||
@ -115,12 +117,15 @@ export default class AppSettingsTab extends SliderSuperTab {
|
||||
buttonsDiv.classList.add('profile-buttons');
|
||||
|
||||
const className = 'profile-button btn-primary btn-transparent';
|
||||
buttonsDiv.append(this.buttons.edit = Button(className, {icon: 'edit', text: 'EditAccount.Title'}));
|
||||
buttonsDiv.append(this.buttons.folders = Button(className, {icon: 'folder', text: 'AccountSettings.Filters'}));
|
||||
buttonsDiv.append(this.buttons.general = Button(className, {icon: 'settings', text: 'Telegram.GeneralSettingsViewController'}));
|
||||
buttonsDiv.append(this.buttons.notifications = Button(className, {icon: 'unmute', text: 'AccountSettings.Notifications'}));
|
||||
buttonsDiv.append(this.buttons.privacy = Button(className, {icon: 'lock', text: 'AccountSettings.PrivacyAndSecurity'}));
|
||||
buttonsDiv.append(this.buttons.language = Button(className, {icon: 'language', text: 'AccountSettings.Language'}));
|
||||
buttonsDiv.append(
|
||||
this.buttons.edit = Button(className, {icon: 'edit', text: 'EditAccount.Title'}),
|
||||
this.buttons.folders = Button(className, {icon: 'folder', text: 'AccountSettings.Filters'}),
|
||||
this.buttons.general = Button(className, {icon: 'settings', text: 'Telegram.GeneralSettingsViewController'}),
|
||||
this.buttons.storage = Button(className, {icon: 'data', text: 'DataSettings'}),
|
||||
this.buttons.notifications = Button(className, {icon: 'unmute', text: 'AccountSettings.Notifications'}),
|
||||
this.buttons.privacy = Button(className, {icon: 'lock', text: 'AccountSettings.PrivacyAndSecurity'}),
|
||||
this.buttons.language = Button(className, {icon: 'language', text: 'AccountSettings.Language'})
|
||||
);
|
||||
|
||||
this.scrollable.append(this.avatarElem, this.nameDiv, this.phoneDiv, buttonsDiv);
|
||||
this.scrollable.container.classList.add('profile-content-wrapper');
|
||||
@ -142,6 +147,10 @@ export default class AppSettingsTab extends SliderSuperTab {
|
||||
new AppGeneralSettingsTab(this.slider).open();
|
||||
});
|
||||
|
||||
this.buttons.storage.addEventListener('click', () => {
|
||||
new AppDataAndStorageTab(this.slider).open();
|
||||
});
|
||||
|
||||
this.buttons.notifications.addEventListener('click', () => {
|
||||
new AppNotificationsTab(this.slider).open();
|
||||
});
|
||||
|
@ -22,6 +22,10 @@ export interface SliderSuperTabConstructable {
|
||||
new(slider: SidebarSlider, destroyable: boolean): SliderSuperTab;
|
||||
}
|
||||
|
||||
export interface SliderSuperTabEventableConstructable {
|
||||
new(slider: SidebarSlider, destroyable: boolean): SliderSuperTabEventable;
|
||||
}
|
||||
|
||||
export default class SliderSuperTab implements SliderTab {
|
||||
public container: HTMLElement;
|
||||
|
||||
|
@ -9,7 +9,6 @@ import { getEmojiToneIndex } from '../vendor/emoji';
|
||||
import { deferredPromise } from '../helpers/cancellablePromise';
|
||||
import { formatFullSentTime } from '../helpers/date';
|
||||
import mediaSizes, { ScreenSize } from '../helpers/mediaSizes';
|
||||
import { formatBytes } from '../helpers/number';
|
||||
import { IS_SAFARI } from '../environment/userAgent';
|
||||
import { Message, PhotoSize, StickerSet } from '../layer';
|
||||
import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager";
|
||||
@ -56,6 +55,8 @@ import throttle from '../helpers/schedulers/throttle';
|
||||
import { SendMessageEmojiInteractionData } from '../types';
|
||||
import IS_VIBRATE_SUPPORTED from '../environment/vibrateSupport';
|
||||
import Row from './row';
|
||||
import { ChatAutoDownloadSettings } from '../helpers/autoDownload';
|
||||
import formatBytes from '../helpers/formatBytes';
|
||||
|
||||
const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB
|
||||
|
||||
@ -82,7 +83,7 @@ mediaSizes.addEventListener('changeScreen', (from, to) => {
|
||||
}
|
||||
});
|
||||
|
||||
export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue, noInfo, group, onlyPreview, withoutPreloader, loadPromises, noPlayButton, noAutoDownload, size, searchContext}: {
|
||||
export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue, noInfo, group, onlyPreview, withoutPreloader, loadPromises, noPlayButton, autoDownloadSize, size, searchContext}: {
|
||||
doc: MyDocument,
|
||||
container?: HTMLElement,
|
||||
message?: Message.message,
|
||||
@ -98,10 +99,11 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
onlyPreview?: boolean,
|
||||
withoutPreloader?: boolean,
|
||||
loadPromises?: Promise<any>[],
|
||||
noAutoDownload?: boolean,
|
||||
autoDownloadSize?: number,
|
||||
size?: PhotoSize,
|
||||
searchContext?: MediaSearchContext,
|
||||
}) {
|
||||
let noAutoDownload = autoDownloadSize === 0;
|
||||
const isAlbumItem = !(boxWidth && boxHeight);
|
||||
const canAutoplay = /* doc.sticker || */(
|
||||
(
|
||||
@ -163,7 +165,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
middleware,
|
||||
withoutPreloader,
|
||||
loadPromises,
|
||||
noAutoDownload,
|
||||
autoDownloadSize,
|
||||
size
|
||||
});
|
||||
|
||||
@ -371,7 +373,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
|
||||
middleware,
|
||||
withoutPreloader: true,
|
||||
loadPromises,
|
||||
noAutoDownload,
|
||||
autoDownloadSize,
|
||||
size
|
||||
});
|
||||
|
||||
@ -550,7 +552,7 @@ rootScope.addEventListener('download_start', (docId) => {
|
||||
});
|
||||
});
|
||||
|
||||
export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showSender, searchContext, loadPromises, noAutoDownload, lazyLoadQueue}: {
|
||||
export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showSender, searchContext, loadPromises, autoDownloadSize, lazyLoadQueue}: {
|
||||
message: any,
|
||||
withTime?: boolean,
|
||||
fontWeight?: number,
|
||||
@ -558,10 +560,11 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
|
||||
showSender?: boolean,
|
||||
searchContext?: MediaSearchContext,
|
||||
loadPromises?: Promise<any>[],
|
||||
noAutoDownload?: boolean,
|
||||
autoDownloadSize?: number,
|
||||
lazyLoadQueue?: LazyLoadQueue
|
||||
}): HTMLElement {
|
||||
if(!fontWeight) fontWeight = 500;
|
||||
const noAutoDownload = autoDownloadSize === 0;
|
||||
|
||||
const doc = (message.media.document || message.media.webpage.document) as MyDocument;
|
||||
const uploading = message.pFlags.is_outgoing && message.media?.preloader;
|
||||
@ -682,7 +685,7 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
|
||||
}
|
||||
};
|
||||
|
||||
const load = (e: Event) => {
|
||||
const load = (e?: Event) => {
|
||||
const save = !e || e.isTrusted;
|
||||
const doc = appDocsManager.getDoc(docDiv.dataset.docId);
|
||||
let download: DownloadBlob;
|
||||
@ -690,13 +693,16 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
|
||||
if(!save) {
|
||||
download = appDocsManager.downloadDoc(doc, queueId);
|
||||
} else if(doc.type === 'pdf') {
|
||||
const canOpenAfter = appDocsManager.downloading.has(doc.id) || cacheContext.downloaded;
|
||||
download = appDocsManager.downloadDoc(doc, queueId);
|
||||
download.then(() => {
|
||||
setTimeout(() => { // wait for preloader animation end
|
||||
const url = appDownloadManager.getCacheContext(doc).url;
|
||||
window.open(url);
|
||||
}, rootScope.settings.animationsEnabled ? 250 : 0);
|
||||
});
|
||||
if(canOpenAfter) {
|
||||
download.then(() => {
|
||||
setTimeout(() => { // wait for preloader animation end
|
||||
const url = appDownloadManager.getCacheContext(doc).url;
|
||||
window.open(url);
|
||||
}, rootScope.settings.animationsEnabled ? 250 : 0);
|
||||
});
|
||||
}
|
||||
} else if(MEDIA_MIME_TYPES_SUPPORTED.has(doc.mime_type) && doc.thumbs?.length) {
|
||||
download = appDocsManager.downloadDoc(doc, queueId);
|
||||
} else {
|
||||
@ -726,6 +732,10 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
|
||||
preloader.setManual();
|
||||
preloader.attach(downloadDiv);
|
||||
preloader.setDownloadFunction(load);
|
||||
|
||||
if(autoDownloadSize !== undefined && autoDownloadSize >= doc.size) {
|
||||
simulateClickEvent(preloader.preloader);
|
||||
}
|
||||
} else {
|
||||
preloader.attach(downloadDiv);
|
||||
message.media.promise.then(onLoad);
|
||||
@ -739,7 +749,7 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
|
||||
load(e);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return docDiv;
|
||||
}
|
||||
|
||||
@ -802,7 +812,7 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
|
||||
return img;
|
||||
} */
|
||||
|
||||
export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware, size, withoutPreloader, loadPromises, noAutoDownload, noBlur, noThumb, noFadeIn, blurAfter}: {
|
||||
export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware, size, withoutPreloader, loadPromises, autoDownloadSize, noBlur, noThumb, noFadeIn, blurAfter}: {
|
||||
photo: MyPhoto | MyDocument,
|
||||
message?: any,
|
||||
container: HTMLElement,
|
||||
@ -815,7 +825,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
size?: PhotoSize,
|
||||
withoutPreloader?: boolean,
|
||||
loadPromises?: Promise<any>[],
|
||||
noAutoDownload?: boolean,
|
||||
autoDownloadSize?: number,
|
||||
noBlur?: boolean,
|
||||
noThumb?: boolean,
|
||||
noFadeIn?: boolean,
|
||||
@ -840,6 +850,8 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
};
|
||||
}
|
||||
|
||||
let noAutoDownload = autoDownloadSize === 0;
|
||||
|
||||
if(!size) {
|
||||
if(boxWidth === undefined) boxWidth = mediaSizes.active.regular.width;
|
||||
if(boxHeight === undefined) boxHeight = mediaSizes.active.regular.height;
|
||||
@ -897,7 +909,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
middleware,
|
||||
withoutPreloader,
|
||||
withTail,
|
||||
noAutoDownload,
|
||||
autoDownloadSize,
|
||||
noBlur,
|
||||
noThumb: true,
|
||||
blurAfter: true
|
||||
@ -1925,7 +1937,7 @@ export function prepareAlbum(options: {
|
||||
} */
|
||||
}
|
||||
|
||||
export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut, chat, loadPromises, noAutoDownload}: {
|
||||
export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut, chat, loadPromises, autoDownload}: {
|
||||
groupId: string,
|
||||
attachmentDiv: HTMLElement,
|
||||
middleware?: () => boolean,
|
||||
@ -1934,7 +1946,7 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
|
||||
isOut: boolean,
|
||||
chat: Chat,
|
||||
loadPromises?: Promise<any>[],
|
||||
noAutoDownload?: boolean,
|
||||
autoDownload?: ChatAutoDownloadSettings,
|
||||
}) {
|
||||
const items: {size: PhotoSize.photoSize, media: any, message: any}[] = [];
|
||||
|
||||
@ -1969,7 +1981,9 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
|
||||
div.dataset.mid = '' + message.mid;
|
||||
div.dataset.peerId = '' + message.peerId;
|
||||
const mediaDiv = div.firstElementChild as HTMLElement;
|
||||
if(media._ === 'photo') {
|
||||
const isPhoto = media._ === 'photo';
|
||||
const autoDownloadSize = autoDownload ? autoDownload[isPhoto ? 'photo' : 'video'] : undefined;
|
||||
if(isPhoto) {
|
||||
wrapPhoto({
|
||||
photo: media,
|
||||
message,
|
||||
@ -1981,7 +1995,7 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
|
||||
middleware,
|
||||
size,
|
||||
loadPromises,
|
||||
noAutoDownload
|
||||
autoDownloadSize
|
||||
});
|
||||
} else {
|
||||
wrapVideo({
|
||||
@ -1995,13 +2009,13 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
|
||||
lazyLoadQueue,
|
||||
middleware,
|
||||
loadPromises,
|
||||
noAutoDownload
|
||||
autoDownloadSize
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, messageDiv, chat, loadPromises, noAutoDownload, lazyLoadQueue, searchContext, useSearch}: {
|
||||
export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, messageDiv, chat, loadPromises, autoDownloadSize, lazyLoadQueue, searchContext, useSearch}: {
|
||||
albumMustBeRenderedFull: boolean,
|
||||
message: any,
|
||||
messageDiv: HTMLElement,
|
||||
@ -2009,7 +2023,7 @@ export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble,
|
||||
uploading?: boolean,
|
||||
chat: Chat,
|
||||
loadPromises?: Promise<any>[],
|
||||
noAutoDownload?: boolean,
|
||||
autoDownloadSize?: number,
|
||||
lazyLoadQueue?: LazyLoadQueue,
|
||||
searchContext?: MediaSearchContext,
|
||||
useSearch?: boolean,
|
||||
@ -2025,7 +2039,7 @@ export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble,
|
||||
const div = wrapDocument({
|
||||
message,
|
||||
loadPromises,
|
||||
noAutoDownload,
|
||||
autoDownloadSize,
|
||||
lazyLoadQueue,
|
||||
searchContext
|
||||
});
|
||||
|
44
src/helpers/autoDownload.ts
Normal file
44
src/helpers/autoDownload.ts
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { State } from "../lib/appManagers/appStateManager";
|
||||
import rootScope from "../lib/rootScope";
|
||||
|
||||
export type ChatAutoDownloadSettings = {
|
||||
photo: number,
|
||||
video: number,
|
||||
file: number
|
||||
};
|
||||
|
||||
export default function getAutoDownloadSettingsByPeerId(peerId: PeerId): ChatAutoDownloadSettings {
|
||||
let type: keyof State['settings']['autoDownload'];
|
||||
|
||||
let photoSizeMax = 0, videoSizeMax = 0, fileSizeMax = 0;
|
||||
const settings = rootScope.settings;
|
||||
if(!settings.autoDownloadNew.pFlags.disabled && peerId) {
|
||||
if(peerId.isUser()) {
|
||||
if(peerId.isContact()) {
|
||||
type = 'contacts';
|
||||
} else {
|
||||
type = 'private';
|
||||
}
|
||||
} else if(peerId.isBroadcast()) {
|
||||
type = 'channels';
|
||||
} else {
|
||||
type = 'groups';
|
||||
}
|
||||
|
||||
if(settings.autoDownload.photo[type]) photoSizeMax = settings.autoDownloadNew.photo_size_max;
|
||||
if(settings.autoDownload.video[type]) videoSizeMax = settings.autoDownloadNew.video_size_max;
|
||||
if(settings.autoDownload.file[type]) fileSizeMax = settings.autoDownloadNew.file_size_max;
|
||||
}
|
||||
|
||||
return {
|
||||
photo: photoSizeMax,
|
||||
video: videoSizeMax,
|
||||
file: fileSizeMax
|
||||
};
|
||||
}
|
19
src/helpers/formatBytes.ts
Normal file
19
src/helpers/formatBytes.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* https://github.com/morethanwords/tweb
|
||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { i18n, LangPackKey } from "../lib/langPack";
|
||||
|
||||
export default function formatBytes(bytes: number, decimals = 2) {
|
||||
if(bytes === 0) return i18n('FileSize.B', [0]);
|
||||
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes: LangPackKey[] = ['FileSize.B', 'FileSize.KB', 'FileSize.MB', 'FileSize.GB'];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return i18n(sizes[i], [parseFloat((bytes / Math.pow(k, i)).toFixed(dm))]);
|
||||
}
|
@ -10,18 +10,6 @@ export function numberThousandSplitter(x: number, joiner = ' ') {
|
||||
return parts.join(".");
|
||||
}
|
||||
|
||||
export function formatBytes(bytes: number, decimals = 2) {
|
||||
if(bytes === 0) return '0 Bytes';
|
||||
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
export function formatNumber(bytes: number, decimals = 2) {
|
||||
if(bytes === 0) return '0';
|
||||
|
||||
|
37
src/lang.ts
37
src/lang.ts
@ -13,8 +13,6 @@ const lang = {
|
||||
"FilterAllNonContacts": "All Non-Contacts",
|
||||
"FilterAllChannels": "All Channels",
|
||||
"FilterAllBots": "All Bots",
|
||||
"WordDelimiter": ", ",
|
||||
"WordDelimiterLast": " and ",
|
||||
"EditContact.OriginalName": "original name",
|
||||
"EditProfile.FirstNameLabel": "Name",
|
||||
"EditProfile.BioLabel": "Bio (optional)",
|
||||
@ -66,7 +64,6 @@ const lang = {
|
||||
"General.SendShortcut.CtrlEnter": "Send by %s + Enter",
|
||||
"General.SendShortcut.NewLine.ShiftEnter": "New line by Shift + Enter",
|
||||
"General.SendShortcut.NewLine.Enter": "New line by Enter",
|
||||
"General.AutoplayMedia": "Auto-Play Media",
|
||||
"General.TimeFormat": "Time Format",
|
||||
"General.TimeFormat.h12": "12-hour",
|
||||
"General.TimeFormat.h23": "24-hour",
|
||||
@ -652,6 +649,34 @@ const lang = {
|
||||
"other_value": "%1$d Seen"
|
||||
},
|
||||
// "Close": "Close",
|
||||
"DataSettings": "Data and Storage",
|
||||
"GroupsAndChannelsHelp": "Change who can add you to groups and channels.",
|
||||
"SessionsInfo": "Control your sessions on other devices.",
|
||||
"StickersBotInfo": "Artists are welcome to add their own sticker sets using our @stickers bot.",
|
||||
"AutomaticMediaDownload": "Automatic media download",
|
||||
"AutoDownloadPhotos": "Photos",
|
||||
"AutoDownloadVideos": "Videos",
|
||||
"AutoDownloadFiles": "Files",
|
||||
"AutoDownloadOnAllChats": "On in all chats",
|
||||
"AutoDownloadUpToOnAllChats": "Up to %1$s in all chats",
|
||||
"AutoDownloadOff": "Off",
|
||||
"AutoDownloadOnUpToFor": "Up to %1$s for %2$s",
|
||||
"AutoDownloadOnFor": "On for %1$s",
|
||||
"AutoDownloadContacts": "Contacts",
|
||||
"AutoDownloadPm": "PM",
|
||||
"AutoDownloadGroups": "Groups",
|
||||
"AutoDownloadChannels": "Channels",
|
||||
"AutoDownloadAudioInfo": "Voice messages are tiny, so they\'re always downloaded automatically.",
|
||||
"AutoplayMedia": "Auto-play media",
|
||||
"AutoDownloadPhotosTitle": "Auto-download photos",
|
||||
"AutoDownloadVideosTitle": "Auto-download videos and GIFs",
|
||||
"AutoDownloadFilesTitle": "Auto-download files and music",
|
||||
"AutoDownloadMaxFileSize": "Maximum file size",
|
||||
"AutodownloadSizeLimitUpTo": "up to %1$s",
|
||||
"ResetAutomaticMediaDownload": "Reset Auto-Download Settings",
|
||||
"ResetAutomaticMediaDownloadAlertTitle": "Reset settings",
|
||||
"ResetAutomaticMediaDownloadAlert": "Are you sure you want to reset auto-download settings?",
|
||||
"Reset": "Reset",
|
||||
|
||||
// * macos
|
||||
"AccountSettings.Filters": "Chat Folders",
|
||||
@ -661,6 +686,8 @@ const lang = {
|
||||
"Alert.UserDoesntExists": "Sorry, this user doesn't seem to exist.",
|
||||
"Alert.Confirm.Discard": "Discard",
|
||||
"Appearance.Reset": "Reset to Defaults",
|
||||
"AutoDownloadSettings.Delimeter": ", ",
|
||||
"AutoDownloadSettings.LastDelimeter": " and ",
|
||||
"Bio.Description": "Any details such as age, occupation or city.\nExample: 23 y.o. designer from San Francisco",
|
||||
"Call.Accept": "Accept",
|
||||
"Call.Decline": "Decline",
|
||||
@ -853,6 +880,10 @@ const lang = {
|
||||
"Emoji.Objects": "Objects",
|
||||
//"Emoji.Symbols": "Symbols",
|
||||
"Emoji.Flags": "Flags",
|
||||
"FileSize.B": "%@ B",
|
||||
"FileSize.KB": "%@ KB",
|
||||
"FileSize.MB": "%@ MB",
|
||||
"FileSize.GB": "%@ GB",
|
||||
"InstalledStickers.LoopAnimated": "Loop Animated Stickers",
|
||||
"LastSeen.HoursAgo": {
|
||||
"one_value": "last seen %d hour ago",
|
||||
|
@ -18,7 +18,7 @@ import { copy, setDeepProperty, validateInitObject } from '../../helpers/object'
|
||||
import App from '../../config/app';
|
||||
import DEBUG, { MOUNT_CLASS_TO } from '../../config/debug';
|
||||
import AppStorage from '../storage';
|
||||
import { Chat } from '../../layer';
|
||||
import { AutoDownloadSettings, Chat } from '../../layer';
|
||||
import { IS_MOBILE } from '../../environment/userAgent';
|
||||
import DATABASE_STATE from '../../config/databases/state';
|
||||
import sessionStorage from '../sessionStorage';
|
||||
@ -45,6 +45,13 @@ export type Theme = {
|
||||
background: Background
|
||||
};
|
||||
|
||||
export type AutoDownloadPeerTypeSettings = {
|
||||
contacts: boolean,
|
||||
private: boolean,
|
||||
groups: boolean,
|
||||
channels: boolean
|
||||
};
|
||||
|
||||
export type State = {
|
||||
allDialogsLoaded: DialogsStorage['allDialogsLoaded'],
|
||||
pinnedOrders: DialogsStorage['pinnedOrders'],
|
||||
@ -75,11 +82,15 @@ export type State = {
|
||||
sendShortcut: 'enter' | 'ctrlEnter',
|
||||
animationsEnabled: boolean,
|
||||
autoDownload: {
|
||||
contacts: boolean
|
||||
private: boolean
|
||||
groups: boolean
|
||||
channels: boolean
|
||||
contacts?: boolean, // ! DEPRECATED
|
||||
private?: boolean, // ! DEPRECATED
|
||||
groups?: boolean, // ! DEPRECATED
|
||||
channels?: boolean, // ! DEPRECATED
|
||||
photo: AutoDownloadPeerTypeSettings,
|
||||
video: AutoDownloadPeerTypeSettings,
|
||||
file: AutoDownloadPeerTypeSettings
|
||||
},
|
||||
autoDownloadNew: AutoDownloadSettings,
|
||||
autoPlay: {
|
||||
gifs: boolean,
|
||||
videos: boolean
|
||||
@ -129,10 +140,35 @@ export const STATE_INIT: State = {
|
||||
sendShortcut: 'enter',
|
||||
animationsEnabled: true,
|
||||
autoDownload: {
|
||||
contacts: true,
|
||||
private: true,
|
||||
groups: true,
|
||||
channels: true
|
||||
photo: {
|
||||
contacts: true,
|
||||
private: true,
|
||||
groups: true,
|
||||
channels: true
|
||||
},
|
||||
video: {
|
||||
contacts: true,
|
||||
private: true,
|
||||
groups: true,
|
||||
channels: true
|
||||
},
|
||||
file: {
|
||||
contacts: true,
|
||||
private: true,
|
||||
groups: true,
|
||||
channels: true
|
||||
}
|
||||
},
|
||||
autoDownloadNew: {
|
||||
_: 'autoDownloadSettings',
|
||||
file_size_max: 3145728,
|
||||
pFlags: {
|
||||
video_preload_large: true,
|
||||
audio_preload_next: true
|
||||
},
|
||||
photo_size_max: 1048576,
|
||||
video_size_max: 15728640,
|
||||
video_upload_maxbitrate: 100
|
||||
},
|
||||
autoPlay: {
|
||||
gifs: true,
|
||||
@ -423,6 +459,36 @@ export class AppStateManager extends EventListenerBase<{
|
||||
}
|
||||
}
|
||||
|
||||
// * migrate auto download settings
|
||||
const autoDownloadSettings = state.settings.autoDownload;
|
||||
if(autoDownloadSettings?.private !== undefined) {
|
||||
const oldTypes = [
|
||||
'contacts' as const,
|
||||
'private' as const,
|
||||
'groups' as const,
|
||||
'channels' as const
|
||||
];
|
||||
|
||||
const mediaTypes = [
|
||||
'photo' as const,
|
||||
'video' as const,
|
||||
'file' as const
|
||||
];
|
||||
|
||||
mediaTypes.forEach(mediaType => {
|
||||
const peerTypeSettings: AutoDownloadPeerTypeSettings = autoDownloadSettings[mediaType] = {} as any;
|
||||
oldTypes.forEach(peerType => {
|
||||
peerTypeSettings[peerType] = autoDownloadSettings[peerType];
|
||||
});
|
||||
});
|
||||
|
||||
oldTypes.forEach(peerType => {
|
||||
delete autoDownloadSettings[peerType];
|
||||
});
|
||||
|
||||
this.pushToState('settings', state.settings);
|
||||
}
|
||||
|
||||
validateInitObject(STATE_INIT, state, (missingKey) => {
|
||||
// @ts-ignore
|
||||
this.pushToState(missingKey, state[missingKey]);
|
||||
|
@ -9,7 +9,7 @@ import throttle from "../../helpers/schedulers/throttle";
|
||||
import { Updates, PhoneJoinGroupCall, PhoneJoinGroupCallPresentation, Update } from "../../layer";
|
||||
import apiUpdatesManager from "../appManagers/apiUpdatesManager";
|
||||
import appGroupCallsManager, { GroupCallConnectionType, JoinGroupCallJsonPayload } from "../appManagers/appGroupCallsManager";
|
||||
import apiManager from "../mtproto/apiManager";
|
||||
import apiManager from "../mtproto/mtprotoworker";
|
||||
import rootScope from "../rootScope";
|
||||
import CallConnectionInstanceBase, { CallConnectionInstanceOptions } from "./callConnectionInstanceBase";
|
||||
import GroupCallInstance from "./groupCallInstance";
|
||||
|
@ -13,7 +13,7 @@ import apiUpdatesManager from "../appManagers/apiUpdatesManager";
|
||||
import appGroupCallsManager, { GroupCallConnectionType, GroupCallId, GroupCallOutputSource } from "../appManagers/appGroupCallsManager";
|
||||
import appPeersManager from "../appManagers/appPeersManager";
|
||||
import { logger } from "../logger";
|
||||
import apiManager from "../mtproto/apiManager";
|
||||
import apiManager from "../mtproto/mtprotoworker";
|
||||
import { NULL_PEER_ID } from "../mtproto/mtproto_config";
|
||||
import rootScope from "../rootScope";
|
||||
import CallInstanceBase, { TryAddTrackOptions } from "./callInstanceBase";
|
||||
|
@ -528,7 +528,7 @@ export function join(elements: (Node | string)[], useLast?: boolean, plain?: fal
|
||||
export function join(elements: (Node | string)[], useLast: boolean, plain: boolean): string | (string | Node)[];
|
||||
export function join(elements: (Node | string)[], useLast = true, plain?: boolean): string | (string | Node)[] {
|
||||
const joined = joinElementsWith(elements, (isLast) => {
|
||||
const langPackKey: LangPackKey = isLast && useLast ? 'WordDelimiterLast' : 'WordDelimiter';
|
||||
const langPackKey: LangPackKey = isLast && useLast ? 'AutoDownloadSettings.LastDelimeter' : 'AutoDownloadSettings.Delimeter';
|
||||
return plain ? I18n.format(langPackKey, true) : i18n(langPackKey);
|
||||
});
|
||||
|
||||
|
@ -63,7 +63,7 @@ export interface RefreshReferenceTaskResponse extends WorkerTaskVoidTemplate {
|
||||
originalPayload: ReferenceBytes
|
||||
};
|
||||
|
||||
const MAX_FILE_SAVE_SIZE = 20e6;
|
||||
const MAX_FILE_SAVE_SIZE = 20 * 1024 * 1024;
|
||||
|
||||
export class ApiFileManager {
|
||||
private cacheStorage = new CacheStorageController('cachedFiles');
|
||||
|
@ -564,6 +564,10 @@
|
||||
&.danger {
|
||||
@include hover-background-effect(red);
|
||||
}
|
||||
|
||||
&.primary {
|
||||
@include hover-background-effect(primary);
|
||||
}
|
||||
|
||||
// * tgico
|
||||
&:before {
|
||||
|
@ -1110,6 +1110,10 @@ $bubble-beside-button-width: 38px;
|
||||
min-width: 10rem;
|
||||
width: auto;
|
||||
|
||||
@include hover() {
|
||||
background-color: var(--light-filled-message-primary-color);
|
||||
}
|
||||
|
||||
&-media {
|
||||
top: .125rem;
|
||||
}
|
||||
|
@ -12,6 +12,15 @@
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
@include animation-level(2) {
|
||||
transition: opacity var(--transition-standard-in);
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
pointer-events: none !important;
|
||||
opacity: var(--disabled-opacity);
|
||||
}
|
||||
|
||||
a {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
Loading…
Reference in New Issue
Block a user