Browse Source

Auto-download settings

master
Eduard Kuzmenko 3 years ago
parent
commit
e1de44ebe4
  1. 17
      src/components/appMediaPlaybackController.ts
  2. 6
      src/components/audio.ts
  3. 28
      src/components/chat/bubbles.ts
  4. 23
      src/components/chat/chat.ts
  5. 4
      src/components/lazyLoadQueue.ts
  6. 2
      src/components/preloader.ts
  7. 2
      src/components/sidebarLeft/tabs/generalSettings.ts
  8. 5
      src/components/sidebarLeft/tabs/settings.ts
  9. 206
      src/components/wrappers.ts
  10. 13
      src/lib/appManagers/appDocsManager.ts
  11. 18
      src/lib/appManagers/appDownloadManager.ts
  12. 10
      src/lib/appManagers/appImManager.ts
  13. 16
      src/lib/appManagers/appMessagesManager.ts
  14. 10
      src/lib/appManagers/appPhotosManager.ts
  15. 3
      src/lib/mtproto/apiFileManager.ts

17
src/components/appMediaPlaybackController.ts

@ -3,7 +3,6 @@ import appMessagesManager from "../lib/appManagers/appMessagesManager"; @@ -3,7 +3,6 @@ import appMessagesManager from "../lib/appManagers/appMessagesManager";
import appDocsManager, {MyDocument} from "../lib/appManagers/appDocsManager";
import { CancellablePromise, deferredPromise } from "../helpers/cancellablePromise";
import { isSafari } from "../helpers/userAgent";
import { isInDOM } from "../helpers/dom";
import { MOUNT_CLASS_TO } from "../config/debug";
// TODO: если удалить сообщение, и при этом аудио будет играть - оно не остановится, и можно будет по нему перейти вникуда
@ -111,17 +110,17 @@ class AppMediaPlaybackController { @@ -111,17 +110,17 @@ class AppMediaPlaybackController {
waitingStorage[mid] = deferred;
}
// если что - загрузит voice или round заранее, так правильнее
const downloadPromise: Promise<any> = !doc.supportsStreaming ? appDocsManager.downloadDoc(doc) : Promise.resolve();
Promise.all([deferred, downloadPromise]).then(() => {
deferred.then(() => {
//media.autoplay = true;
//console.log('will set media url:', media, doc, doc.type, doc.url);
if(doc.type === 'audio' && doc.supportsStreaming && isSafari) {
this.handleSafariStreamable(media);
}
media.src = doc.url;
((!doc.supportsStreaming ? appDocsManager.downloadDoc(doc) : Promise.resolve()) as Promise<any>).then(() => {
if(doc.type === 'audio' && doc.supportsStreaming && isSafari) {
this.handleSafariStreamable(media);
}
media.src = doc.url;
});
}, onError);
return storage[mid] = media;

6
src/components/audio.ts

@ -341,6 +341,7 @@ export default class AudioElement extends HTMLElement { @@ -341,6 +341,7 @@ export default class AudioElement extends HTMLElement {
public voiceAsMusic = false;
public searchContext: SearchSuperContext;
public showSender = false;
public noAutoDownload: boolean;
private attachedHandlers: {[name: string]: any[]} = {};
private onTypeDisconnect: () => void;
@ -464,7 +465,10 @@ export default class AudioElement extends HTMLElement { @@ -464,7 +465,10 @@ export default class AudioElement extends HTMLElement {
};
attachClickEvent(this, onClick);
onClick();
if(!this.noAutoDownload) {
onClick();
}
} else {
if(doc.supportsStreaming) {
onLoad(false);

28
src/components/chat/bubbles.ts

@ -30,7 +30,7 @@ import { langPack } from "../../lib/langPack"; @@ -30,7 +30,7 @@ import { langPack } from "../../lib/langPack";
import AvatarElement from "../avatar";
import { formatPhoneNumber } from "../misc";
import { ripple } from "../ripple";
import { wrapAlbum, wrapPhoto, wrapVideo, wrapDocument, wrapSticker, wrapPoll, wrapReply, wrapGroupedDocuments } from "../wrappers";
import { wrapAlbum, wrapPhoto, wrapVideo, wrapDocument, wrapSticker, wrapPoll, wrapGroupedDocuments } from "../wrappers";
import { MessageRender } from "./messageRender";
import LazyLoadQueue from "../lazyLoadQueue";
import { AppChatsManager } from "../../lib/appManagers/appChatsManager";
@ -1669,6 +1669,8 @@ export default class ChatBubbles { @@ -1669,6 +1669,8 @@ export default class ChatBubbles {
}).catch(reject);
}, 0);
});
//this.messagesQueuePromise.catch(() => {});
}
public setBubblePosition(bubble: HTMLElement, message: any, reverse: boolean) {
@ -2033,7 +2035,8 @@ export default class ChatBubbles { @@ -2033,7 +2035,8 @@ export default class ChatBubbles {
isOut: our,
lazyLoadQueue: this.lazyLoadQueue,
chat: this.chat,
loadPromises
loadPromises,
noAutoDownload: this.chat.noAutoDownloadMedia,
});
break;
@ -2049,7 +2052,8 @@ export default class ChatBubbles { @@ -2049,7 +2052,8 @@ export default class ChatBubbles {
isOut,
lazyLoadQueue: this.lazyLoadQueue,
middleware: this.getMiddleware(),
loadPromises
loadPromises,
noAutoDownload: this.chat.noAutoDownloadMedia,
});
break;
@ -2098,12 +2102,14 @@ export default class ChatBubbles { @@ -2098,12 +2102,14 @@ export default class ChatBubbles {
middleware: this.getMiddleware(),
isOut,
group: CHAT_ANIMATION_GROUP,
loadPromises
loadPromises,
noAutoDownload: this.chat.noAutoDownloadMedia,
});
//}
} else {
const docDiv = wrapDocument({
message
message,
noAutoDownload: this.chat.noAutoDownloadMedia,
});
preview.append(docDiv);
preview.classList.add('preview-with-document');
@ -2166,7 +2172,8 @@ export default class ChatBubbles { @@ -2166,7 +2172,8 @@ export default class ChatBubbles {
lazyLoadQueue: this.lazyLoadQueue,
middleware: this.getMiddleware(),
loadPromises,
withoutPreloader: isSquare
withoutPreloader: isSquare,
noAutoDownload: this.chat.noAutoDownloadMedia,
});
}
@ -2233,7 +2240,8 @@ export default class ChatBubbles { @@ -2233,7 +2240,8 @@ export default class ChatBubbles {
isOut: our,
lazyLoadQueue: this.lazyLoadQueue,
chat: this.chat,
loadPromises
loadPromises,
noAutoDownload: this.chat.noAutoDownloadMedia,
});
} else {
const withTail = !isAndroid && !isApple && doc.type !== 'round' && canHaveTail && !withReplies && USE_MEDIA_TAILS;
@ -2249,7 +2257,8 @@ export default class ChatBubbles { @@ -2249,7 +2257,8 @@ export default class ChatBubbles {
lazyLoadQueue: this.lazyLoadQueue,
middleware: this.getMiddleware(),
group: CHAT_ANIMATION_GROUP,
loadPromises
loadPromises,
noAutoDownload: this.chat.noAutoDownloadMedia,
});
}
@ -2261,7 +2270,8 @@ export default class ChatBubbles { @@ -2261,7 +2270,8 @@ export default class ChatBubbles {
bubble,
messageDiv,
chat: this.chat,
loadPromises
loadPromises,
noAutoDownload: this.chat.noAutoDownloadMedia
});
if(newNameContainer) {

23
src/components/chat/chat.ts

@ -29,6 +29,7 @@ import { renderImageFromUrl } from "../misc"; @@ -29,6 +29,7 @@ import { renderImageFromUrl } from "../misc";
import SetTransition from "../singleTransition";
import { fastRaf } from "../../helpers/schedulers";
import AppPrivateSearchTab from "../sidebarRight/tabs/search";
import type { State } from "../../lib/appManagers/appStateManager";
export type ChatType = 'chat' | 'pinned' | 'replies' | 'discussion' | 'scheduled';
@ -54,6 +55,8 @@ export default class Chat extends EventListenerBase<{ @@ -54,6 +55,8 @@ export default class Chat extends EventListenerBase<{
public log: ReturnType<typeof logger>;
public type: ChatType = 'chat';
public noAutoDownloadMedia: boolean;
constructor(public appImManager: AppImManager, public appChatsManager: AppChatsManager, public appDocsManager: AppDocsManager, public appInlineBotsManager: AppInlineBotsManager, public appMessagesManager: AppMessagesManager, public appPeersManager: AppPeersManager, public appPhotosManager: AppPhotosManager, public appProfileManager: AppProfileManager, public appStickersManager: AppStickersManager, public appUsersManager: AppUsersManager, public appWebPagesManager: AppWebPagesManager, public appPollsManager: AppPollsManager, public apiManager: ApiManagerProxy, public appDraftsManager: AppDraftsManager, public serverTimeManager: ServerTimeManager, public storage: typeof sessionStorage, public appNotificationsManager: AppNotificationsManager) {
super();
@ -210,6 +213,7 @@ export default class Chat extends EventListenerBase<{ @@ -210,6 +213,7 @@ export default class Chat extends EventListenerBase<{
appSidebarRight.sharedMediaTab.setPeer(peerId, this.threadId);
this.input.clearHelper(); // костыль
this.selection.cleanup(); // TODO: REFACTOR !!!!!!
this.setAutoDownloadMedia();
}
this.peerChanged = samePeer;
@ -238,6 +242,25 @@ export default class Chat extends EventListenerBase<{ @@ -238,6 +242,25 @@ export default class Chat extends EventListenerBase<{
return result;
}
public setAutoDownloadMedia() {
let type: keyof State['settings']['autoDownload'];
if(this.peerId < 0) {
if(this.appPeersManager.isBroadcast(this.peerId)) {
type = 'channels';
} else {
type = 'groups';
}
} else {
if(this.appUsersManager.isContact(this.peerId)) {
type = 'contacts';
} else {
type = 'private';
}
}
this.noAutoDownloadMedia = !rootScope.settings.autoDownload[type];
}
public setMessageId(messageId?: number) {
return this.setPeer(this.peerId, messageId);
}

4
src/components/lazyLoadQueue.ts

@ -81,7 +81,9 @@ export class LazyLoadQueueBase { @@ -81,7 +81,9 @@ export class LazyLoadQueueBase {
//await item.load(item.div);
await this.loadItem(item);
} catch(err) {
this.log.error('loadMediaQueue error:', err/* , item */);
if(err !== 'NO_ENTRY_FOUND') {
this.log.error('loadMediaQueue error:', err/* , item */);
}
}
this.inProcess.delete(item);

2
src/components/preloader.ts

@ -22,7 +22,7 @@ export default class ProgressivePreloader { @@ -22,7 +22,7 @@ export default class ProgressivePreloader {
private tryAgainOnFail = true;
private attachMethod: 'append' | 'prepend' = 'append';
private loadFunc: () => {download: CancellablePromise<any>};
public loadFunc: () => {download: CancellablePromise<any>};
private totalLength: number;

2
src/components/sidebarLeft/tabs/generalSettings.ts

@ -103,7 +103,7 @@ export default class AppGeneralSettingsTab extends SliderSuperTab { @@ -103,7 +103,7 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
{
const container = section('Auto-Download Media');
container.classList.add('sidebar-left-section-disabled');
//container.classList.add('sidebar-left-section-disabled');
const contactsCheckboxField = new CheckboxField({
text: 'Contacts',

5
src/components/sidebarLeft/tabs/settings.ts

@ -9,6 +9,7 @@ import AppGeneralSettingsTab from "./generalSettings"; @@ -9,6 +9,7 @@ import AppGeneralSettingsTab from "./generalSettings";
import AppEditProfileTab from "./editProfile";
import AppChatFoldersTab from "./chatFolders";
import AppNotificationsTab from "./notifications";
import PeerTitle from "../../peerTitle";
//import AppMediaViewer from "../../appMediaViewerNew";
export default class AppSettingsTab extends SliderSuperTab {
@ -120,7 +121,7 @@ export default class AppSettingsTab extends SliderSuperTab { @@ -120,7 +121,7 @@ export default class AppSettingsTab extends SliderSuperTab {
});
this.buttons.general.addEventListener('click', () => {
new AppGeneralSettingsTab(this.slider as any).open();
new AppGeneralSettingsTab(this.slider).open();
});
this.buttons.notifications.addEventListener('click', () => {
@ -136,7 +137,7 @@ export default class AppSettingsTab extends SliderSuperTab { @@ -136,7 +137,7 @@ export default class AppSettingsTab extends SliderSuperTab {
let user = appUsersManager.getSelf();
this.avatarElem.setAttribute('peer', '' + user.id);
this.nameDiv.innerHTML = user.rFullName || '';
this.nameDiv.append(new PeerTitle({peerId: user.id}).element);
this.phoneDiv.innerHTML = user.rPhone || '';
}

206
src/components/wrappers.ts

@ -5,13 +5,12 @@ import { deferredPromise } from '../helpers/cancellablePromise'; @@ -5,13 +5,12 @@ import { deferredPromise } from '../helpers/cancellablePromise';
import { formatDateAccordingToToday, months } from '../helpers/date';
import mediaSizes from '../helpers/mediaSizes';
import { formatBytes } from '../helpers/number';
import { isAppleMobile, isSafari } from '../helpers/userAgent';
import { isSafari } from '../helpers/userAgent';
import { PhotoSize } from '../layer';
import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager";
import appMessagesManager from '../lib/appManagers/appMessagesManager';
import appPhotosManager, { MyPhoto } from '../lib/appManagers/appPhotosManager';
import LottieLoader from '../lib/lottieLoader';
import VideoPlayer from '../lib/mediaPlayer';
import { attachClickEvent, cancelEvent, isInDOM } from "../helpers/dom";
import webpWorkerController from '../lib/webp/webpWorkerController';
import animationIntersector from './animationIntersector';
@ -34,7 +33,7 @@ import { animateSingle } from '../helpers/animation'; @@ -34,7 +33,7 @@ import { animateSingle } from '../helpers/animation';
const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB
export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue, noInfo, group, onlyPreview, withoutPreloader, loadPromises, noPlayButton}: {
export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTail, isOut, middleware, lazyLoadQueue, noInfo, group, onlyPreview, withoutPreloader, loadPromises, noPlayButton, noAutoDownload}: {
doc: MyDocument,
container?: HTMLElement,
message?: any,
@ -49,7 +48,8 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -49,7 +48,8 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
group?: string,
onlyPreview?: boolean,
withoutPreloader?: boolean,
loadPromises?: Promise<any>[]
loadPromises?: Promise<any>[],
noAutoDownload?: boolean,
}) {
const isAlbumItem = !(boxWidth && boxHeight);
const canAutoplay = doc.type !== 'video' || (doc.size <= MAX_VIDEO_AUTOPLAY_SIZE && !isAlbumItem);
@ -94,7 +94,8 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -94,7 +94,8 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
lazyLoadQueue,
middleware,
withoutPreloader,
loadPromises
loadPromises,
noAutoDownload
});
res.thumb = photoRes;
@ -112,7 +113,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -112,7 +113,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
video.setAttribute('playsinline', 'true');
video.muted = true;
if(doc.type === 'round') {
const globalVideo = appMediaPlaybackController.addMedia(message.peerId, doc, message.mid) as HTMLVideoElement;
const globalVideo = appMediaPlaybackController.addMedia(message.peerId, doc, message.mid, !noAutoDownload) as HTMLVideoElement;
const divRound = document.createElement('div');
divRound.classList.add('media-round', 'z-depth-1');
@ -230,7 +231,8 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -230,7 +231,8 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
lazyLoadQueue,
middleware,
withoutPreloader: true,
loadPromises
loadPromises,
noAutoDownload
});
res.thumb = photoRes;
@ -259,85 +261,97 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -259,85 +261,97 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
container.append(video);
}
const loadVideo = async() => {
if(middleware && !middleware()) {
return;
let preloader: ProgressivePreloader;
if(message?.media?.preloader) { // means upload
preloader = message.media.preloader as ProgressivePreloader;
preloader.attach(container, false);
noAutoDownload = undefined;
} else if(!doc.downloaded && !doc.supportsStreaming) {
preloader = new ProgressivePreloader({
attachMethod: 'prepend'
});
} else if(doc.supportsStreaming) {
preloader = new ProgressivePreloader({
cancelable: false,
attachMethod: 'prepend'
});
}
let f = noAutoDownload && photoRes?.preloader?.loadFunc;
const load = () => {
if(preloader && noAutoDownload && !withoutPreloader) {
preloader.construct();
preloader.setManual();
}
let loadPromise: Promise<any> = Promise.resolve();
let preloader: ProgressivePreloader;
if(message?.media?.preloader) { // means upload
preloader = message.media.preloader as ProgressivePreloader;
preloader.attach(container, false);
} else if(!doc.downloaded && !doc.supportsStreaming) {
const promise = loadPromise = appDocsManager.downloadDoc(doc, lazyLoadQueue?.queueId);
preloader = new ProgressivePreloader({
attachMethod: 'prepend'
});
preloader.attach(container, true, promise);
//if(doc.type !== 'round') {
await promise;
if(middleware && !middleware()) {
return;
if(preloader) {
if(!doc.downloaded && !doc.supportsStreaming) {
const promise = loadPromise = appDocsManager.downloadDoc(doc, lazyLoadQueue?.queueId, noAutoDownload);
preloader.attach(container, false, promise);
} else if(doc.supportsStreaming) {
if(noAutoDownload) {
loadPromise = Promise.reject();
} else {
preloader.attach(container, false, null);
video.addEventListener(isSafari ? 'timeupdate' : 'canplay', () => {
preloader.detach();
}, {once: true});
}
//}
} else if(doc.supportsStreaming) {
preloader = new ProgressivePreloader({
cancelable: false,
attachMethod: 'prepend'
});
preloader.attach(container, false, null);
video.addEventListener(isSafari ? 'timeupdate' : 'canplay', () => {
preloader.detach();
}, {once: true});
}
}
/* if(doc.type === 'round') {
return;
} */
//console.log('loaded doc:', doc, doc.url, container);
if(!noAutoDownload && f) {
f();
f = null;
}
noAutoDownload = undefined;
const deferred = deferredPromise<void>();
loadPromise.then(() => {
if(middleware && !middleware()) {
deferred.resolve();
return;
}
if(doc.type === 'round') {
appMediaPlaybackController.resolveWaitingForLoadMedia(message.peerId, message.mid);
}
//if(doc.type === 'gif'/* || true */) {
onVideoLoad(video).then(() => {
/* if(!video.paused) {
video.pause();
} */
if(group) {
animationIntersector.addAnimation(video, group);
}
// test lazyLoadQueue
//setTimeout(() => {
deferred.resolve();
//}, 5000);
deferred.resolve();
});
//}
if(doc.type === 'video') {
video.addEventListener('timeupdate', () => {
spanTime.innerText = (video.duration - video.currentTime + '').toHHMMSS(false);
if(doc.type === 'video') {
video.addEventListener('timeupdate', () => {
spanTime.innerText = (video.duration - video.currentTime + '').toHHMMSS(false);
});
}
video.addEventListener('error', (e) => {
deferred.resolve();
});
}
video.addEventListener('error', (e) => {
deferred.resolve();
});
video.muted = true;
video.loop = true;
//video.play();
video.autoplay = true;
video.muted = true;
video.loop = true;
//video.play();
video.autoplay = true;
renderImageFromUrl(video, doc.url);
renderImageFromUrl(video, doc.url);
}, () => {});
return Promise.all([loadPromise, deferred]);
return {download: loadPromise, render: deferred};
};
if(preloader) {
preloader.setDownloadFunction(load);
}
/* if(doc.size >= 20e6 && !doc.downloaded) {
let downloadDiv = document.createElement('div');
downloadDiv.classList.add('download');
@ -356,7 +370,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai @@ -356,7 +370,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
return;
} */
res.loadPromise = !lazyLoadQueue ? loadVideo() : (lazyLoadQueue.push({div: container, load: loadVideo}), Promise.resolve());
res.loadPromise = !lazyLoadQueue ? load().render : (lazyLoadQueue.push({div: container, load: () => load().render}), Promise.resolve());
return res;
}
@ -375,14 +389,15 @@ export const formatDate = (timestamp: number, monthShort = false, withYear = tru @@ -375,14 +389,15 @@ export const formatDate = (timestamp: number, monthShort = false, withYear = tru
return str + ' at ' + date.getHours() + ':' + ('0' + date.getMinutes()).slice(-2);
};
export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showSender, searchContext, loadPromises}: {
export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showSender, searchContext, loadPromises, noAutoDownload}: {
message: any,
withTime?: boolean,
fontWeight?: number,
voiceAsMusic?: boolean,
showSender?: boolean,
searchContext?: SearchSuperContext,
loadPromises?: Promise<any>[]
loadPromises?: Promise<any>[],
noAutoDownload?: boolean,
}): HTMLElement {
if(!fontWeight) fontWeight = 500;
@ -394,6 +409,7 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS @@ -394,6 +409,7 @@ export function wrapDocument({message, withTime, fontWeight, voiceAsMusic, showS
audioElement.setAttribute('peer-id', '' + message.peerId);
audioElement.withTime = withTime;
audioElement.message = message;
audioElement.noAutoDownload = noAutoDownload;
if(voiceAsMusic) audioElement.voiceAsMusic = voiceAsMusic;
if(searchContext) audioElement.searchContext = searchContext;
@ -590,7 +606,7 @@ function wrapMediaWithTail(photo: MyPhoto | MyDocument, message: {mid: number, m @@ -590,7 +606,7 @@ function wrapMediaWithTail(photo: MyPhoto | MyDocument, message: {mid: number, m
return img;
}
export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware, size, withoutPreloader, loadPromises}: {
export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware, size, withoutPreloader, loadPromises, noAutoDownload}: {
photo: MyPhoto | MyDocument,
message: any,
container: HTMLElement,
@ -602,7 +618,8 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT @@ -602,7 +618,8 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
middleware?: () => boolean,
size?: PhotoSize,
withoutPreloader?: boolean,
loadPromises?: Promise<any>[]
loadPromises?: Promise<any>[],
noAutoDownload?: boolean,
}) {
if(!((photo as MyPhoto).sizes || (photo as MyDocument).thumbs)) {
if(boxWidth && boxHeight && photo._ === 'document') {
@ -617,7 +634,8 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT @@ -617,7 +634,8 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
images: {
thumb: null,
full: null
}
},
preloader: null
};
}
@ -660,6 +678,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT @@ -660,6 +678,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
if(message?.media?.preloader) { // means upload
preloader = message.media.preloader;
preloader.attach(container);
noAutoDownload = undefined;
} else {
preloader = new ProgressivePreloader({
attachMethod: 'prepend'
@ -669,7 +688,9 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT @@ -669,7 +688,9 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
const getDownloadPromise = () => {
const promise = photo._ === 'document' && photo.mime_type === 'image/gif' ?
appDocsManager.downloadDoc(photo, /* undefined, */lazyLoadQueue?.queueId) :
appPhotosManager.preloadPhoto(photo, size, lazyLoadQueue?.queueId);
appPhotosManager.preloadPhoto(photo, size, lazyLoadQueue?.queueId, noAutoDownload);
noAutoDownload = undefined;
return promise;
};
@ -701,13 +722,20 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT @@ -701,13 +722,20 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
let loadPromise: Promise<any>;
const load = () => {
if(noAutoDownload && !withoutPreloader) {
preloader.construct();
preloader.setManual();
}
const promise = getDownloadPromise();
if(!cacheContext.downloaded && !withoutPreloader && (size as PhotoSize.photoSize).w >= 150 && (size as PhotoSize.photoSize).h >= 150) {
preloader.attach(container, false, promise);
}
return {download: promise, render: promise.then(onLoad)};
const renderPromise = promise.then(onLoad);
renderPromise.catch(() => {});
return {download: promise, render: renderPromise};
};
preloader.setDownloadFunction(load);
@ -716,7 +744,11 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT @@ -716,7 +744,11 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
loadThumbPromise = loadPromise = load().render;
} else {
if(!lazyLoadQueue) loadPromise = load().render;
else lazyLoadQueue.push({div: container, load: () => load().download});
/* else if(noAutoDownload) {
preloader.construct();
preloader.setManual();
preloader.attach(container);
} */ else lazyLoadQueue.push({div: container, load: () => load().download});
}
if(loadPromises && loadThumbPromise) {
@ -731,7 +763,8 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT @@ -731,7 +763,8 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
images: {
thumb: thumbImage,
full: image
}
},
preloader
};
}
@ -1089,7 +1122,7 @@ export function prepareAlbum(options: { @@ -1089,7 +1122,7 @@ export function prepareAlbum(options: {
} */
}
export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut, chat, loadPromises}: {
export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLoadQueue, isOut, chat, loadPromises, noAutoDownload}: {
groupId: string,
attachmentDiv: HTMLElement,
middleware?: () => boolean,
@ -1097,7 +1130,8 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo @@ -1097,7 +1130,8 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
uploading?: boolean,
isOut: boolean,
chat: Chat,
loadPromises?: Promise<any>[]
loadPromises?: Promise<any>[],
noAutoDownload?: boolean,
}) {
const items: {size: PhotoSize.photoSize, media: any, message: any}[] = [];
@ -1142,7 +1176,8 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo @@ -1142,7 +1176,8 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
lazyLoadQueue,
middleware,
size,
loadPromises
loadPromises,
noAutoDownload
});
} else {
wrapVideo({
@ -1155,20 +1190,22 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo @@ -1155,20 +1190,22 @@ export function wrapAlbum({groupId, attachmentDiv, middleware, uploading, lazyLo
isOut,
lazyLoadQueue,
middleware,
loadPromises
loadPromises,
noAutoDownload
});
}
});
}
export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, messageDiv, chat, loadPromises}: {
export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, messageDiv, chat, loadPromises, noAutoDownload}: {
albumMustBeRenderedFull: boolean,
message: any,
messageDiv: HTMLElement,
bubble: HTMLElement,
uploading?: boolean,
chat: Chat,
loadPromises?: Promise<any>[]
loadPromises?: Promise<any>[],
noAutoDownload?: boolean,
}) {
let nameContainer: HTMLElement;
const mids = albumMustBeRenderedFull ? chat.getMidsByMid(message.mid) : [message.mid];
@ -1180,7 +1217,8 @@ export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble, @@ -1180,7 +1217,8 @@ export function wrapGroupedDocuments({albumMustBeRenderedFull, message, bubble,
const message = chat.getMessage(mid);
const div = wrapDocument({
message,
loadPromises
loadPromises,
noAutoDownload
});
const container = document.createElement('div');

13
src/lib/appManagers/appDocsManager.ts

@ -214,7 +214,7 @@ export class AppDocsManager { @@ -214,7 +214,7 @@ export class AppDocsManager {
};
}
public getFileDownloadOptions(doc: MyDocument, thumb?: PhotoSize.photoSize, queueId?: number) {
public getFileDownloadOptions(doc: MyDocument, thumb?: PhotoSize.photoSize, queueId?: number, onlyCache?: boolean) {
const inputFileLocation = this.getInput(doc, thumb?.type);
let mimeType: string;
@ -230,7 +230,8 @@ export class AppDocsManager { @@ -230,7 +230,8 @@ export class AppDocsManager {
size: thumb ? thumb.size : doc.size,
mimeType: mimeType,
fileName: doc.file_name,
queueId
queueId,
onlyCache
};
}
@ -278,7 +279,7 @@ export class AppDocsManager { @@ -278,7 +279,7 @@ export class AppDocsManager {
return getFileNameByLocation(this.getInput(doc, thumbSize), {fileName: doc.file_name});
}
public downloadDoc(doc: MyDocument, queueId?: number): DownloadBlob {
public downloadDoc(doc: MyDocument, queueId?: number, onlyCache?: boolean): DownloadBlob {
const fileName = this.getInputFileName(doc);
let download: DownloadBlob = appDownloadManager.getDownload(fileName);
@ -286,15 +287,15 @@ export class AppDocsManager { @@ -286,15 +287,15 @@ export class AppDocsManager {
return download;
}
const downloadOptions = this.getFileDownloadOptions(doc, undefined, queueId);
const downloadOptions = this.getFileDownloadOptions(doc, undefined, queueId, onlyCache);
download = appDownloadManager.download(downloadOptions);
const originalPromise = download;
originalPromise.then((blob) => {
doc.url = URL.createObjectURL(blob);
doc.downloaded = true;
});
}, () => {});
if(doc.type === 'voice' && !opusDecodeController.isPlaySupported()) {
download = originalPromise.then(async(blob) => {
const reader = new FileReader();

18
src/lib/appManagers/appDownloadManager.ts

@ -56,8 +56,7 @@ export class AppDownloadManager { @@ -56,8 +56,7 @@ export class AppDownloadManager {
error.name = 'AbortError';
apiManager.cancelDownload(fileName);
this.clearDownload(fileName);
deferred.reject(error);
deferred.cancel = () => {};
/* } catch(err) {
@ -70,6 +69,10 @@ export class AppDownloadManager { @@ -70,6 +69,10 @@ export class AppDownloadManager {
delete this.progressCallbacks[fileName];
});
deferred.catch(() => {
this.clearDownload(fileName);
});
return this.downloads[fileName] = deferred;
}
@ -121,11 +124,14 @@ export class AppDownloadManager { @@ -121,11 +124,14 @@ export class AppDownloadManager {
const tryDownload = (): Promise<unknown> => {
//return Promise.resolve();
if(!apiManager.worker) {
return this.cacheStorage.getFile(fileName).then((blob) => {
if(!apiManager.worker || options.onlyCache) {
const promise = this.cacheStorage.getFile(fileName).then((blob) => {
if(blob.size < options.size) throw 'wrong size';
else deferred.resolve(blob);
}).catch(() => {
});
if(options.onlyCache) return promise.catch(onError);
return promise.catch(() => {
return apiManager.downloadFile(options).then(deferred.resolve, onError);
});
} else {
@ -237,4 +243,4 @@ export class AppDownloadManager { @@ -237,4 +243,4 @@ export class AppDownloadManager {
}
}
export default new AppDownloadManager();
export default new AppDownloadManager();

10
src/lib/appManagers/appImManager.ts

@ -161,7 +161,7 @@ export class AppImManager { @@ -161,7 +161,7 @@ export class AppImManager {
});
this.setSettings();
rootScope.on('settings_updated', () => this.setSettings());
rootScope.on('settings_updated', this.setSettings);
useHeavyAnimationCheck(() => {
animationIntersector.setOnlyOnePlayableGroup('lock');
@ -237,7 +237,7 @@ export class AppImManager { @@ -237,7 +237,7 @@ export class AppImManager {
return sessionStorage.getFromCache('chatPositions')[key];
} */
private setSettings() {
private setSettings = () => {
document.documentElement.style.setProperty('--messages-text-size', rootScope.settings.messagesTextSize + 'px');
if(rootScope.settings.background.highlightningColor) {
@ -261,7 +261,11 @@ export class AppImManager { @@ -261,7 +261,11 @@ export class AppImManager {
lottieLoader.setLoop(rootScope.settings.stickers.loop);
animationIntersector.checkAnimations(false);
}
for(const chat of this.chats) {
chat.setAutoDownloadMedia();
}
};
// * не могу использовать тут TransitionSlider, так как мне нужен отрисованный блок рядом
// * (или под текущим чатом) чтобы правильно отрендерить чат (напр. scrollTop)

16
src/lib/appManagers/appMessagesManager.ts

@ -6,7 +6,7 @@ import { createPosterForVideo } from "../../helpers/files"; @@ -6,7 +6,7 @@ import { createPosterForVideo } from "../../helpers/files";
import { copy, defineNotNumerableProperties, getObjectKeysAndSort } from "../../helpers/object";
import { randomLong } from "../../helpers/random";
import { splitStringByLength, limitSymbols } from "../../helpers/string";
import { ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MessagesPeerDialogs, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update } from "../../layer";
import { Chat, ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MessagesPeerDialogs, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update } from "../../layer";
import { InvokeApiOptions } from "../../types";
import { langPack } from "../langPack";
import { logger, LogLevels } from "../logger";
@ -1759,6 +1759,10 @@ export class AppMessagesManager { @@ -1759,6 +1759,10 @@ export class AppMessagesManager {
// ! нужно передавать folderId, так как по папке !== 0 нет свойства folder_id
this.saveConversation(dialog, dialog.folder_id ?? folderId);
if(dialog.peerId === undefined) {
return;
}
/* if(dialog.peerId === -1213511294) {
this.log.error('lun bot', folderId, d);
} */
@ -2894,7 +2898,7 @@ export class AppMessagesManager { @@ -2894,7 +2898,7 @@ export class AppMessagesManager {
}
/**
* Won't save migrated from peer
* Won't save migrated from peer, forbidden peers, left and kicked
*/
public saveConversation(dialog: Dialog, folderId = 0) {
const peerId = appPeersManager.getPeerId(dialog.peer);
@ -2908,6 +2912,14 @@ export class AppMessagesManager { @@ -2908,6 +2912,14 @@ export class AppMessagesManager {
}
const channelId = appPeersManager.isChannel(peerId) ? -peerId : 0;
if(peerId < 0) {
const chat: Chat = appChatsManager.getChat(-peerId);
if(chat._ === 'channelForbidden' || chat._ === 'chatForbidden' || (chat as Chat.chat).pFlags.left || (chat as Chat.chat).pFlags.kicked) {
return false;
}
}
const peerText = appPeersManager.getPeerSearchText(peerId);
searchIndexManager.indexObject(peerId, peerText, this.dialogsIndex);

10
src/lib/appManagers/appPhotosManager.ts

@ -256,7 +256,7 @@ export class AppPhotosManager { @@ -256,7 +256,7 @@ export class AppPhotosManager {
return null;
}
public getPhotoDownloadOptions(photo: MyPhoto | MyDocument, photoSize: PhotoSize, queueId?: number) {
public getPhotoDownloadOptions(photo: MyPhoto | MyDocument, photoSize: PhotoSize, queueId?: number, onlyCache?: boolean) {
const isMyDocument = photo._ === 'document';
if(!photoSize || photoSize._ === 'photoSizeEmpty') {
@ -274,7 +274,7 @@ export class AppPhotosManager { @@ -274,7 +274,7 @@ export class AppPhotosManager {
thumb_size: photoSize.type
} : (photoSize as PhotoSize.photoSize).location;
return {dcId: photo.dc_id, location, size: isPhoto ? (photoSize as PhotoSize.photoSize).size : undefined, queueId};
return {dcId: photo.dc_id, location, size: isPhoto ? (photoSize as PhotoSize.photoSize).size : undefined, queueId, onlyCache};
}
/* public getPhotoURL(photo: MTPhoto | MTMyDocument, photoSize: MTPhotoSize) {
@ -297,7 +297,7 @@ export class AppPhotosManager { @@ -297,7 +297,7 @@ export class AppPhotosManager {
return isDownloaded;
}
public preloadPhoto(photoId: any, photoSize?: PhotoSize, queueId?: number): CancellablePromise<Blob> {
public preloadPhoto(photoId: any, photoSize?: PhotoSize, queueId?: number, onlyCache?: boolean): CancellablePromise<Blob> {
const photo = this.getPhoto(photoId);
// @ts-ignore
@ -317,7 +317,7 @@ export class AppPhotosManager { @@ -317,7 +317,7 @@ export class AppPhotosManager {
return Promise.resolve() as any;
}
const downloadOptions = this.getPhotoDownloadOptions(photo, photoSize, queueId);
const downloadOptions = this.getPhotoDownloadOptions(photo, photoSize, queueId, onlyCache);
const fileName = getFileNameByLocation(downloadOptions.location);
@ -342,7 +342,7 @@ export class AppPhotosManager { @@ -342,7 +342,7 @@ export class AppPhotosManager {
(photoSize as any).url = url;
return blob;
});
}).catch(() => {});
return download;
}

3
src/lib/mtproto/apiFileManager.ts

@ -25,7 +25,8 @@ export type DownloadOptions = { @@ -25,7 +25,8 @@ export type DownloadOptions = {
fileName?: string,
mimeType?: string,
limitPart?: number,
queueId?: number
queueId?: number,
onlyCache?: boolean,
};
type MyUploadFile = UploadFile.uploadFile;

Loading…
Cancel
Save