Browse Source

Fix sidebar load & photo single objectURL & no raf message render

master
morethanwords 5 years ago
parent
commit
da6a4d2d2e
  1. 8
      src/components/lazyLoadQueue.ts
  2. 10
      src/components/misc.ts
  3. 46
      src/components/wrappers.ts
  4. 7
      src/lib/appManagers/appDialogsManager.ts
  5. 24
      src/lib/appManagers/appDocsManager.ts
  6. 40
      src/lib/appManagers/appImManager.ts
  7. 6
      src/lib/appManagers/appMessagesManager.ts
  8. 30
      src/lib/appManagers/appPhotosManager.ts
  9. 172
      src/lib/appManagers/appSidebarRight.ts
  10. 3
      src/lib/appManagers/appWebPagesManager.ts
  11. 6
      src/lib/appManagers/appWebpManager.ts
  12. 5
      src/lib/lottieLoader.ts
  13. 13
      src/lib/mtproto/apiFileManager.ts
  14. 25
      webpack.common.js

8
src/components/lazyLoadQueue.ts

@ -14,6 +14,8 @@ export default class LazyLoadQueue {
private lockPromise: Promise<void> = null; private lockPromise: Promise<void> = null;
private unlockResolve: () => void = null; private unlockResolve: () => void = null;
private log = console.log.bind(console, '[LL]:');
constructor(private parallelLimit = 5) { constructor(private parallelLimit = 5) {
} }
@ -67,13 +69,13 @@ export default class LazyLoadQueue {
let tempID = this.tempID; let tempID = this.tempID;
console.log('lazyLoadQueue: will load media', this.lockPromise); this.log('will load media', this.lockPromise, item);
try { try {
if(this.lockPromise) { if(this.lockPromise) {
let perf = performance.now(); let perf = performance.now();
await this.lockPromise; await this.lockPromise;
console.log('lazyLoadQueue: waited lock:', performance.now() - perf); this.log('waited lock:', performance.now() - perf);
} }
await new Promise((resolve, reject) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve))); await new Promise((resolve, reject) => window.requestAnimationFrame(() => window.requestAnimationFrame(resolve)));
@ -86,7 +88,7 @@ export default class LazyLoadQueue {
this.loadingMedia--; this.loadingMedia--;
} }
console.log('lazyLoadQueue: loaded media'); this.log('loaded media');
if(this.lazyLoadMedia.length) { if(this.lazyLoadMedia.length) {
this.processQueue(); this.processQueue();

10
src/components/misc.ts

@ -92,6 +92,16 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
}); });
} }
export function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGImageElement, url: string) {
let img = new Image();
img.src = url;
img.onload = () => {
if(elem instanceof HTMLImageElement) elem.src = url;
else if(elem instanceof SVGImageElement) elem.setAttributeNS(null, 'href', url);
else elem.style.backgroundImage = 'url(' + url + ')';
};
}
export function putPreloader(elem: Element, returnDiv = false) { export function putPreloader(elem: Element, returnDiv = false) {
const html = ` const html = `
<svg xmlns="http://www.w3.org/2000/svg" class="preloader-circular" viewBox="25 25 50 50"> <svg xmlns="http://www.w3.org/2000/svg" class="preloader-circular" viewBox="25 25 50 50">

46
src/components/wrappers.ts

@ -12,9 +12,10 @@ import appWebpManager from '../lib/appManagers/appWebpManager';
import {wrapPlayer} from '../lib/ckin'; import {wrapPlayer} from '../lib/ckin';
import { RichTextProcessor } from '../lib/richtextprocessor'; import { RichTextProcessor } from '../lib/richtextprocessor';
import { CancellablePromise } from '../lib/polyfill'; import { CancellablePromise } from '../lib/polyfill';
import { renderImageFromUrl } from './misc';
export type MTDocument = { export type MTDocument = {
_: 'document', _: 'document' | 'documentEmpty',
pFlags: any, pFlags: any,
flags: number, flags: number,
id: string, id: string,
@ -27,12 +28,25 @@ export type MTDocument = {
dc_id: number, dc_id: number,
attributes: any[], attributes: any[],
thumb?: MTPhotoSize,
type?: string, type?: string,
h?: number, h?: number,
w?: number, w?: number,
file_name?: string, file_name?: string,
file?: File, file?: File,
duration?: number duration?: number,
downloaded?: boolean,
version?: any,
audioTitle?: string,
audioPerformer?: string,
sticker?: boolean,
stickerEmoji?: string,
stickerEmojiRaw?: string,
stickerSetInput?: any,
animated?: boolean
}; };
export type MTPhotoSize = { export type MTPhotoSize = {
@ -497,17 +511,13 @@ export async function wrapPhoto(this: AppImManager, photoID: string, message: an
preloader.attach(container, true, promise); preloader.attach(container, true, promise);
} }
return promise.then((blob) => { return promise.then(() => {
if(this.peerID != peerID) { if(this.peerID != peerID) {
this.log.warn('peer changed'); this.log.warn('peer changed');
return; return;
} }
if(withTail) { renderImageFromUrl(image, photo.url);
image.setAttributeNS(null, 'href', URL.createObjectURL(blob));
} else if(image instanceof Image) {
image.src = URL.createObjectURL(blob);
}
}); });
}; };
@ -525,14 +535,15 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
if(!stickerType) { if(!stickerType) {
console.error('wrong doc for wrapSticker!', doc, div); console.error('wrong doc for wrapSticker!', doc, div);
return Promise.resolve();
} }
//////console.log('wrap sticker', doc, onlyThumb); console.log('wrap sticker', doc, div, onlyThumb);
if(doc.thumbs && !div.firstElementChild) { if(doc.thumbs && !div.firstElementChild) {
let thumb = doc.thumbs[0]; let thumb = doc.thumbs[0];
///////console.log('wrap sticker', thumb); console.log('wrap sticker', thumb, div);
if(thumb.bytes) { if(thumb.bytes) {
apiFileManager.saveSmallFile(thumb.location, thumb.bytes); apiFileManager.saveSmallFile(thumb.location, thumb.bytes);
@ -566,14 +577,7 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
return lazyLoadQueue ? (lazyLoadQueue.push({div, load}), Promise.resolve()) : load(); return lazyLoadQueue ? (lazyLoadQueue.push({div, load}), Promise.resolve()) : load();
} }
let load = () => apiFileManager.downloadSmallFile({ let load = () => appDocsManager.downloadDoc(doc.id).then(blob => {
_: 'inputDocumentFileLocation',
access_hash: doc.access_hash,
file_reference: doc.file_reference,
thumb_size: ''/* document.thumbs[0].type */,
id: doc.id,
stickerType: stickerType
}, {mimeType: doc.mime_type, dcID: doc.dc_id}).then(blob => {
//console.log('loaded sticker:', blob, div); //console.log('loaded sticker:', blob, div);
if(middleware && !middleware()) return; if(middleware && !middleware()) return;
@ -666,7 +670,7 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
appStickersManager.saveSticker(doc); appStickersManager.saveSticker(doc);
}); });
return lazyLoadQueue ? (lazyLoadQueue.push({div, load}), Promise.resolve()) : load(); return lazyLoadQueue && (!doc.downloaded || stickerType == 2) ? (lazyLoadQueue.push({div, load, wasSeen: group == 'chat'}), Promise.resolve()) : load();
} }
export function wrapReply(title: string, subtitle: string, media?: any) { export function wrapReply(title: string, subtitle: string, media?: any) {
@ -710,8 +714,8 @@ export function wrapReply(title: string, subtitle: string, media?: any) {
} }
appPhotosManager.preloadPhoto(photo, appPhotosManager.choosePhotoSize(photo, 32, 32)) appPhotosManager.preloadPhoto(photo, appPhotosManager.choosePhotoSize(photo, 32, 32))
.then((blob) => { .then(blob => {
replyMedia.style.backgroundImage = 'url(' + URL.createObjectURL(blob) + ')'; renderImageFromUrl(replyMedia, photo.url || URL.createObjectURL(blob));
}); });
replyContent.append(replyMedia); replyContent.append(replyMedia);

7
src/lib/appManagers/appDialogsManager.ts

@ -6,7 +6,7 @@ import appPeersManager from './appPeersManager';
import appMessagesManager from "./appMessagesManager"; import appMessagesManager from "./appMessagesManager";
import appUsersManager from "./appUsersManager"; import appUsersManager from "./appUsersManager";
import { RichTextProcessor } from "../richtextprocessor"; import { RichTextProcessor } from "../richtextprocessor";
import { ripple } from "../../components/misc"; import { ripple, renderImageFromUrl } from "../../components/misc";
import appSidebarLeft from "./appSidebarLeft"; import appSidebarLeft from "./appSidebarLeft";
import Scrollable from "../../components/scrollable"; import Scrollable from "../../components/scrollable";
@ -219,13 +219,14 @@ export class AppDialogsManager {
let img = new Image(); let img = new Image();
img.src = this.savedAvatarURLs[peerID]; img.src = this.savedAvatarURLs[peerID];
//renderImageFromUrl(img, this.savedAvatarURLs[peerID]);
div.innerHTML = ''; div.innerHTML = '';
//div.style.fontSize = '0'; // need //div.style.fontSize = '0'; // need
//div.style.backgroundColor = ''; //div.style.backgroundColor = '';
window.requestAnimationFrame(() => { //window.requestAnimationFrame(() => {
div.append(img); div.append(img);
}); //});
return true; return true;
} }

24
src/lib/appManagers/appDocsManager.ts

@ -2,12 +2,12 @@ import apiFileManager from '../mtproto/apiFileManager';
import FileManager from '../filemanager'; import FileManager from '../filemanager';
import {RichTextProcessor} from '../richtextprocessor'; import {RichTextProcessor} from '../richtextprocessor';
import { CancellablePromise } from '../polyfill'; import { CancellablePromise } from '../polyfill';
//import { MTDocument } from '../../components/misc'; import { MTDocument } from '../../components/wrappers';
class AppDocsManager { class AppDocsManager {
private docs: any = {}; private docs: any = {};
public saveDoc(apiDoc: /* MTDocument */any, context?: any) { public saveDoc(apiDoc: MTDocument/* any */, context?: any) {
console.log('saveDoc', apiDoc, this.docs[apiDoc.id]); console.log('saveDoc', apiDoc, this.docs[apiDoc.id]);
if(this.docs[apiDoc.id]) return this.docs[apiDoc.id]; if(this.docs[apiDoc.id]) return this.docs[apiDoc.id];
@ -136,15 +136,17 @@ class AppDocsManager {
return this.docs[docID] !== undefined; return this.docs[docID] !== undefined;
} }
public getFileName(doc: any) { public getFileName(doc: MTDocument) {
if (doc.file_name) { if(doc.file_name) {
return doc.file_name return doc.file_name;
} }
var fileExt = '.' + doc.mime_type.split('/')[1]
if (fileExt == '.octet-stream') { var fileExt = '.' + doc.mime_type.split('/')[1];
fileExt = '' if(fileExt == '.octet-stream') {
fileExt = '';
} }
return 't_' + (doc.type || 'file') + doc.id + fileExt
return 't_' + (doc.type || 'file') + doc.id + fileExt;
} }
public updateDocDownloaded(docID: string) { public updateDocDownloaded(docID: string) {
@ -166,8 +168,8 @@ class AppDocsManager {
} }
} }
public downloadDoc(docID: any, toFileEntry?: any): CancellablePromise<Blob> { public downloadDoc(docID: string | MTDocument, toFileEntry?: any): CancellablePromise<Blob> {
let doc: any; let doc: MTDocument;
if(typeof(docID) === 'string') { if(typeof(docID) === 'string') {
doc = this.docs[docID]; doc = this.docs[docID];
} else { } else {

40
src/lib/appManagers/appImManager.ts

@ -1,7 +1,7 @@
import apiManager from '../mtproto/apiManager'; import apiManager from '../mtproto/apiManager';
import { $rootScope, isElementInViewport, numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, calcImageInBox, findUpTag, langPack } from "../utils"; import { $rootScope, isElementInViewport, numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, calcImageInBox, findUpTag, langPack } from "../utils";
import appUsersManager from "./appUsersManager"; import appUsersManager from "./appUsersManager";
import appMessagesManager, { HistoryResult } from "./appMessagesManager"; import appMessagesManager from "./appMessagesManager";
import appPeersManager from "./appPeersManager"; import appPeersManager from "./appPeersManager";
import appProfileManager from "./appProfileManager"; import appProfileManager from "./appProfileManager";
import appDialogsManager from "./appDialogsManager"; import appDialogsManager from "./appDialogsManager";
@ -993,8 +993,11 @@ export class AppImManager {
this.firstTopMsgID = dialog ? dialog.top_message : 0; this.firstTopMsgID = dialog ? dialog.top_message : 0;
window.requestAnimationFrame(() => {
this.chatInner.style.visibility = 'hidden'; this.chatInner.style.visibility = 'hidden';
this.chatInput.style.display = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID) ? 'none' : '';
this.topbar.style.display = '';
window.requestAnimationFrame(() => {
//this.chatInner.style.visibility = 'hidden';
let title = ''; let title = '';
if(this.peerID == this.myID) title = 'Saved Messages'; if(this.peerID == this.myID) title = 'Saved Messages';
@ -1002,9 +1005,10 @@ export class AppImManager {
//this.titleEl.innerHTML = appSidebarRight.profileElements.name.innerHTML = dom.titleSpan.innerHTML; //this.titleEl.innerHTML = appSidebarRight.profileElements.name.innerHTML = dom.titleSpan.innerHTML;
this.titleEl.innerHTML = appSidebarRight.profileElements.name.innerHTML = title; this.titleEl.innerHTML = appSidebarRight.profileElements.name.innerHTML = title;
this.pinnedMessageContainer.style.display = 'none'; this.pinnedMessageContainer.style.display = 'none';
this.topbar.style.display = this.goDownBtn.style.display = ''; this.goDownBtn.style.display = '';
//this.topbar.style.display = this.goDownBtn.style.display = '';
//this.chatInput.style.display = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID) ? 'none' : '';
//appSidebarRight.toggleSidebar(true); //appSidebarRight.toggleSidebar(true);
this.chatInput.style.display = appPeersManager.isChannel(peerID) && !appPeersManager.isMegagroup(peerID) ? 'none' : '';
if(appPeersManager.isAnyGroup(peerID)) this.chatInner.classList.add('is-chat'); if(appPeersManager.isAnyGroup(peerID)) this.chatInner.classList.add('is-chat');
else this.chatInner.classList.remove('is-chat'); else this.chatInner.classList.remove('is-chat');
@ -1454,20 +1458,14 @@ export class AppImManager {
bubbleContainer.style.height = attachmentDiv.style.height; bubbleContainer.style.height = attachmentDiv.style.height;
bubbleContainer.style.width = attachmentDiv.style.width; bubbleContainer.style.width = attachmentDiv.style.width;
//appPhotosManager.setAttachmentSize(doc, bubble); //appPhotosManager.setAttachmentSize(doc, bubble);
let load = () => wrapSticker(doc, attachmentDiv, () => { wrapSticker(doc, attachmentDiv, () => {
if(this.peerID != peerID) { if(this.peerID != peerID) {
this.log.warn('peer changed, canceling sticker attach'); this.log.warn('peer changed, canceling sticker attach');
return false; return false;
} }
return true; return true;
}, null, 'chat', false, !!message.pending || !multipleRender).then(() => { }, this.lazyLoadQueue, 'chat', false, !!message.pending || !multipleRender);
//preloader.detach();
/* attachmentDiv.style.width = '';
attachmentDiv.style.height = ''; */
});
this.lazyLoadQueue.push({div: bubble, load: load, wasSeen: true});
break; break;
} else if(doc.mime_type == 'video/mp4' && doc.size <= 20e6) { } else if(doc.mime_type == 'video/mp4' && doc.size <= 20e6) {
@ -1703,6 +1701,8 @@ export class AppImManager {
} }
} }
//history = history.slice(); // need
if(additionMsgID) { if(additionMsgID) {
history.unshift(additionMsgID); history.unshift(additionMsgID);
} }
@ -1719,6 +1719,8 @@ export class AppImManager {
this.scrollPosition.prepareFor(reverse ? 'up' : 'down'); this.scrollPosition.prepareFor(reverse ? 'up' : 'down');
} }
let firstLoad = !!this.setPeerPromise && false;
let peerID = this.peerID; let peerID = this.peerID;
return new Promise<boolean>((resolve, reject) => { return new Promise<boolean>((resolve, reject) => {
let resolved = false; let resolved = false;
@ -1733,6 +1735,8 @@ export class AppImManager {
//console.timeEnd('appImManager: pre render start'); //console.timeEnd('appImManager: pre render start');
//this.log('start performHistoryResult, scrollTop:', this.scrollable.scrollTop, this.scrollable.scrollHeight, this.scrollable.innerHeight);
let renderedFirstScreen = false; let renderedFirstScreen = false;
let r = () => { let r = () => {
//let bubble = bubbles.shift(); //let bubble = bubbles.shift();
@ -1771,7 +1775,7 @@ export class AppImManager {
if(reverse) { if(reverse) {
this.scrollable.prepend(bubble); this.scrollable.prepend(bubble);
//console.log('innerHeight', innerHeight, this.scrollable.scrollTop); //this.log('performHistoryResult scrollTop', this.scrollable.scrollTop, bubble.scrollHeight);
/* if(innerHeight >= 0) { /* if(innerHeight >= 0) {
let height = bubble.scrollHeight; let height = bubble.scrollHeight;
@ -1816,10 +1820,10 @@ export class AppImManager {
this.scrollable.append(bubble); this.scrollable.append(bubble);
} */ } */
window.requestAnimationFrame(r); firstLoad ? window.requestAnimationFrame(r) : r();
}; };
window.requestAnimationFrame(r); firstLoad ? window.requestAnimationFrame(r) : r();
//r(); //r();
/* method((msgID) => { /* method((msgID) => {
let message = appMessagesManager.getMessage(msgID); let message = appMessagesManager.getMessage(msgID);
@ -1854,7 +1858,7 @@ export class AppImManager {
maxID = dialog.top_message/* + 1 */; maxID = dialog.top_message/* + 1 */;
} }
let loadCount = Object.keys(this.bubbles).length > 0 ? 20 : this.scrollable.container.parentElement.scrollHeight / 30/* * 1.25 */ | 0; let loadCount = Object.keys(this.bubbles).length > 0 ? 20 : this.scrollable.innerHeight / 38/* * 1.25 */ | 0;
/* if(testScroll) { /* if(testScroll) {
loadCount = 5; loadCount = 5;
@ -1901,7 +1905,9 @@ export class AppImManager {
return (reverse ? this.getHistoryTopPromise = promise : this.getHistoryBottomPromise = promise); return (reverse ? this.getHistoryTopPromise = promise : this.getHistoryBottomPromise = promise);
} else { } else {
return this.performHistoryResult(result.history || [], reverse, isBackLimit, additionMsgID, true); let promise = this.performHistoryResult(result.history || [], reverse, isBackLimit, additionMsgID, true);
return (reverse ? this.getHistoryTopPromise = promise : this.getHistoryBottomPromise = promise);
//return this.performHistoryResult(result.history || [], reverse, isBackLimit, additionMsgID, true);
} }
} }

6
src/lib/appManagers/appMessagesManager.ts

@ -1137,7 +1137,8 @@ export class AppMessagesManager {
if(apiMessage.media.ttl_seconds) { if(apiMessage.media.ttl_seconds) {
apiMessage.media = {_: 'messageMediaUnsupportedWeb'}; apiMessage.media = {_: 'messageMediaUnsupportedWeb'};
} else { } else {
appPhotosManager.savePhoto(apiMessage.media.photo, mediaContext); apiMessage.media.photo = appPhotosManager.savePhoto(apiMessage.media.photo, mediaContext);
//appPhotosManager.savePhoto(apiMessage.media.photo, mediaContext);
} }
break break
case 'messageMediaDocument': case 'messageMediaDocument':
@ -1171,7 +1172,8 @@ export class AppMessagesManager {
var migrateTo; var migrateTo;
switch(apiMessage.action._) { switch(apiMessage.action._) {
case 'messageActionChatEditPhoto': case 'messageActionChatEditPhoto':
appPhotosManager.savePhoto(apiMessage.action.photo, mediaContext); apiMessage.action.photo = appPhotosManager.savePhoto(apiMessage.action.photo, mediaContext);
//appPhotosManager.savePhoto(apiMessage.action.photo, mediaContext);
if(isBroadcast) { if(isBroadcast) {
apiMessage.action._ = 'messageActionChannelEditPhoto'; apiMessage.action._ = 'messageActionChannelEditPhoto';
} }

30
src/lib/appManagers/appPhotosManager.ts

@ -7,7 +7,7 @@ import apiFileManager from "../mtproto/apiFileManager";
import apiManager from "../mtproto/apiManager"; import apiManager from "../mtproto/apiManager";
type MTPhoto = { type MTPhoto = {
_: 'photo', _: 'photo' | 'photoEmpty' | string,
pFlags: any, pFlags: any,
flags: number, flags: number,
id: string, id: string,
@ -18,7 +18,8 @@ type MTPhoto = {
dc_id: number, dc_id: number,
user_id: number, user_id: number,
downloaded?: boolean downloaded?: boolean | number,
url?: string
}; };
export class AppPhotosManager { export class AppPhotosManager {
@ -52,7 +53,7 @@ export class AppPhotosManager {
console.warn('no apiPhoto.id', photo); console.warn('no apiPhoto.id', photo);
} else this.photos[photo.id] = photo; } else this.photos[photo.id] = photo;
if(!('sizes' in photo)) return; /* if(!('sizes' in photo)) return;
photo.sizes.forEach((photoSize: any) => { photo.sizes.forEach((photoSize: any) => {
if(photoSize._ == 'photoCachedSize') { if(photoSize._ == 'photoCachedSize') {
@ -65,7 +66,7 @@ export class AppPhotosManager {
delete photoSize.bytes; delete photoSize.bytes;
photoSize._ = 'photoSize'; photoSize._ = 'photoSize';
} }
}); }); */
/* if(!photo.downloaded) { /* if(!photo.downloaded) {
photo.downloaded = apiFileManager.isFileExists({ photo.downloaded = apiFileManager.isFileExists({
@ -141,7 +142,8 @@ export class AppPhotosManager {
var photoIDs = []; var photoIDs = [];
var context = {user_id: userID}; var context = {user_id: userID};
for(var i = 0; i < photosResult.photos.length; i++) { for(var i = 0; i < photosResult.photos.length; i++) {
this.savePhoto(photosResult.photos[i], context); //this.savePhoto(photosResult.photos[i], context);
photosResult.photos[i] = this.savePhoto(photosResult.photos[i], context);
photoIDs.push(photosResult.photos[i].id); photoIDs.push(photosResult.photos[i].id);
} }
@ -237,8 +239,8 @@ export class AppPhotosManager {
return photoSize; return photoSize;
} }
public preloadPhoto(photoID: any, photoSize?: MTPhotoSize): Promise<Blob> { public preloadPhoto(photoID: any, photoSize?: MTPhotoSize): Promise<Blob | string> {
let photo: any = null; let photo: MTPhoto = null;
if(typeof(photoID) === 'string') { if(typeof(photoID) === 'string') {
photo = this.photos[photoID]; photo = this.photos[photoID];
@ -267,6 +269,10 @@ export class AppPhotosManager {
let promise: Promise<Blob>; let promise: Promise<Blob>;
/* if(photo.downloaded == photoSize.size && photo.url) {
return Promise.resolve(photo.url);
} */
if(isPhoto/* && photoSize.size >= 1e6 */) { if(isPhoto/* && photoSize.size >= 1e6 */) {
//console.log('Photos downloadFile exec', photo); //console.log('Photos downloadFile exec', photo);
promise = apiFileManager.downloadFile(photo.dc_id, location, photoSize.size); promise = apiFileManager.downloadFile(photo.dc_id, location, photoSize.size);
@ -276,8 +282,14 @@ export class AppPhotosManager {
} }
if(typeof(photoID) === 'string') { if(typeof(photoID) === 'string') {
promise.then(() => { let photo = this.photos[photoID];
this.photos[photoID].downloaded = true; promise.then(blob => {
if(!photo.downloaded || photo.downloaded < blob.size) {
photo.downloaded = blob.size;
photo.url = URL.createObjectURL(blob);
console.log('wrote photo:', photo, photoSize, blob);
}
}); });
} }

172
src/lib/appManagers/appSidebarRight.ts

@ -1,4 +1,4 @@
import { horizontalMenu, formatPhoneNumber, putPreloader } from "../../components/misc"; import { horizontalMenu, formatPhoneNumber, putPreloader, renderImageFromUrl } from "../../components/misc";
import Scrollable from '../../components/scrollable'; import Scrollable from '../../components/scrollable';
import { $rootScope } from "../utils"; import { $rootScope } from "../utils";
import appMessagesManager from "./appMessagesManager"; import appMessagesManager from "./appMessagesManager";
@ -67,6 +67,9 @@ class AppSidebarRight {
[type: string]: number[] [type: string]: number[]
} }
} = {}; } = {};
public usedFromHistory: {
[type: string]: number
} = {};
private log = logger('SR'); private log = logger('SR');
@ -93,8 +96,8 @@ class AppSidebarRight {
this.scroll = new Scrollable(this.sidebarEl, 'y', 1200, 'SR'); this.scroll = new Scrollable(this.sidebarEl, 'y', 1200, 'SR');
this.scroll.container.addEventListener('scroll', this.onSidebarScroll.bind(this)); this.scroll.container.addEventListener('scroll', this.onSidebarScroll.bind(this));
this.scroll.onScrolledBottom = () => { this.scroll.onScrolledBottom = () => {
if(this.sharedMediaSelected && !this.scroll.hiddenElements.down.length if(this.sharedMediaSelected && !this.scroll.hiddenElements.down.length && this.sharedMediaSelected.childElementCount/* && false */) {
&& this.sharedMediaSelected.childElementCount/* && false */) { this.log('onScrolledBottom will load media');
this.loadSidebarMedia(true); this.loadSidebarMedia(true);
} }
}; };
@ -145,8 +148,7 @@ class AppSidebarRight {
let targets = ids.map(id => ({element: this.mediaDivsByIDs[id], mid: id})); let targets = ids.map(id => ({element: this.mediaDivsByIDs[id], mid: id}));
appMediaViewer.openMedia(message, target, false, this.sidebarEl, appMediaViewer.openMedia(message, target, false, this.sidebarEl, targets.slice(idx + 1).reverse(), targets.slice(0, idx).reverse(), () => this.loadSidebarMedia(true));
targets.slice(idx + 1).reverse(), targets.slice(0, idx).reverse(), () => this.loadSidebarMedia(true));
}); });
this.profileElements.notificationsCheckbox.addEventListener('change', () => { this.profileElements.notificationsCheckbox.addEventListener('change', () => {
@ -154,12 +156,7 @@ class AppSidebarRight {
appImManager.mutePeer(); appImManager.mutePeer();
}); });
window.addEventListener('resize', () => { window.addEventListener('resize', this.onSidebarScroll.bind(this));
setTimeout(() => {
this.scroll.onScroll();
this.onSidebarScroll();
}, 0);
});
if(testScroll) { if(testScroll) {
let div = document.createElement('div'); let div = document.createElement('div');
@ -191,6 +188,7 @@ class AppSidebarRight {
setTimeout(() => this.lazyLoadQueueSidebar.check(), 200); setTimeout(() => this.lazyLoadQueueSidebar.check(), 200);
this.sidebarEl.classList.add('active'); this.sidebarEl.classList.add('active');
} else this.sidebarEl.classList.remove('active'); } else this.sidebarEl.classList.remove('active');
return; return;
} }
@ -201,62 +199,9 @@ class AppSidebarRight {
} }
} }
public loadSidebarMedia(single = false) { public performSearchResult(ids: number[], type: string) {
if(testScroll/* || 1 == 1 */) {
return;
}
//this.log('loadSidebarMedia', single, this.peerID);
let peerID = this.peerID; let peerID = this.peerID;
let typesToLoad = single ? [this.sharedMediaType] : this.sharedMediaTypes;
typesToLoad = typesToLoad.filter(type => !this.loadedAllMedia[type]);
if(!typesToLoad.length) return;
if(!this.historiesStorage[peerID]) this.historiesStorage[peerID] = {};
let historyStorage = this.historiesStorage[peerID];
this.scroll.lock();
let promises = typesToLoad.map(type => {
if(this.loadSidebarMediaPromises[type]) return this.loadSidebarMediaPromises[type];
if(!historyStorage[type]) historyStorage[type] = [];
let history = historyStorage[type];
// заливать новую картинку сюда только после полной отправки!
//let maxID = this.minMediaID[type] || 0;
let maxID = history[history.length - 1] || 0;
let ids = !maxID && appMessagesManager.historiesStorage[peerID]
? appMessagesManager.historiesStorage[peerID].history.slice() : [];
maxID = !maxID && ids.length ? ids[ids.length - 1] : maxID;
//this.log('search house of glass pre', type, ids, maxID);
let loadCount = history.length ? 50 : 15;
return this.loadSidebarMediaPromises[type] = appMessagesManager.getSearch(peerID, '', {_: type}, maxID, loadCount)
.then(value => {
ids = ids.concat(value.history);
history.push(...ids);
this.log('search house of glass', type, value, ids, this.cleared);
if(value.history.length < loadCount) {
this.loadedAllMedia[type] = true;
}
if($rootScope.selectedPeerID != peerID) {
this.log.warn('peer changed');
return;
}
if(this.cleared[type]) {
ids = history;
delete this.cleared[type];
}
let sharedMediaDiv: HTMLDivElement; let sharedMediaDiv: HTMLDivElement;
let messages: any[] = []; let messages: any[] = [];
for(let mid of ids) { for(let mid of ids) {
@ -313,6 +258,9 @@ class AppSidebarRight {
return; return;
} }
if(photo && photo.url) {
renderImageFromUrl(div, photo.url);
} else {
let url = URL.createObjectURL(blob); let url = URL.createObjectURL(blob);
this.urlsToRevoke.push(url); this.urlsToRevoke.push(url);
@ -321,6 +269,7 @@ class AppSidebarRight {
img.onload = () => { img.onload = () => {
div.style.backgroundImage = 'url(' + url + ')'; div.style.backgroundImage = 'url(' + url + ')';
}; };
}
//div.style.backgroundImage = 'url(' + url + ')'; //div.style.backgroundImage = 'url(' + url + ')';
}); });
@ -394,10 +343,12 @@ class AppSidebarRight {
return; return;
} }
let url = URL.createObjectURL(blob); renderImageFromUrl(previewDiv, webpage.photo.url);
/* let url = URL.createObjectURL(blob);
this.urlsToRevoke.push(url); this.urlsToRevoke.push(url);
previewDiv.style.backgroundImage = 'url(' + url + ')'; previewDiv.style.backgroundImage = 'url(' + url + ')'; */
}); });
this.lazyLoadQueueSidebar.push({div: previewDiv, load}); this.lazyLoadQueueSidebar.push({div: previewDiv, load});
@ -471,10 +422,79 @@ class AppSidebarRight {
} }
this.onSidebarScroll(); this.onSidebarScroll();
}).then(() => { }
this.loadSidebarMediaPromises[type] = null;
public loadSidebarMedia(single = false) {
if(testScroll/* || 1 == 1 */) {
return;
}
this.log('loadSidebarMedia', single, this.peerID);
let peerID = this.peerID;
let typesToLoad = single ? [this.sharedMediaType] : this.sharedMediaTypes;
typesToLoad = typesToLoad.filter(type => !this.loadedAllMedia[type]);
if(!typesToLoad.length) return;
let historyStorage = this.historiesStorage[peerID] ?? (this.historiesStorage[peerID] = {});
this.scroll.lock();
let promises = typesToLoad.map(type => {
if(this.loadSidebarMediaPromises[type]) return this.loadSidebarMediaPromises[type];
let history = historyStorage[type] ?? (historyStorage[type] = []);
let loadCount = (appPhotosManager.windowH / 130 | 0) * 3;
// render from cache
if(history.length && this.usedFromHistory[type] < history.length && this.cleared[type]) {
let ids = history.slice(this.usedFromHistory[type], this.usedFromHistory[type] + loadCount);
this.log('will render from cache', this.usedFromHistory[type], history, ids, loadCount);
this.usedFromHistory[type] += ids.length;
this.performSearchResult(ids, type);
return;
}
// заливать новую картинку сюда только после полной отправки!
//let maxID = this.minMediaID[type] || 0;
let maxID = history[history.length - 1] || 0;
let ids = !maxID && appMessagesManager.historiesStorage[peerID]
? appMessagesManager.historiesStorage[peerID].history.slice() : [];
maxID = !maxID && ids.length ? ids[ids.length - 1] : maxID;
this.log('search house of glass pre', type, ids, maxID);
//let loadCount = history.length ? 50 : 15;
return this.loadSidebarMediaPromises[type] = appMessagesManager.getSearch(peerID, '', {_: type}, maxID, loadCount)
.then(value => {
ids = ids.concat(value.history);
history.push(...ids);
this.log('search house of glass', type, value, ids, this.cleared);
if($rootScope.selectedPeerID != peerID) {
this.log.warn('peer changed');
return;
}
if(value.history.length < loadCount) {
this.loadedAllMedia[type] = true;
}
if(this.cleared[type]) {
//ids = history;
delete this.cleared[type];
}
if(ids.length) {
this.performSearchResult(ids, type);
}
}, (err) => { }, (err) => {
this.log.error('load error:', err); this.log.error('load error:', err);
}).then(() => {
this.loadSidebarMediaPromises[type] = null; this.loadSidebarMediaPromises[type] = null;
}); });
}); });
@ -515,6 +535,8 @@ class AppSidebarRight {
this.scroll.setVirtualContainer(null); this.scroll.setVirtualContainer(null);
(this.profileTabs.children[1] as HTMLLIElement).click(); // set media (this.profileTabs.children[1] as HTMLLIElement).click(); // set media
//this.scroll.getScrollTopOffset();
this.loadSidebarMedia(true); this.loadSidebarMedia(true);
}); });
@ -530,6 +552,7 @@ class AppSidebarRight {
this.sharedMediaTypes.forEach(type => { this.sharedMediaTypes.forEach(type => {
//this.minMediaID[type] = 0; //this.minMediaID[type] = 0;
this.cleared[type] = true; this.cleared[type] = true;
this.usedFromHistory[type] = 0;
}); });
let setText = (text: string, el: HTMLDivElement) => { let setText = (text: string, el: HTMLDivElement) => {
@ -543,6 +566,8 @@ class AppSidebarRight {
el.prepend(p); el.prepend(p);
el.style.display = ''; el.style.display = '';
//this.scroll.getScrollTopOffset();
}); });
}; };
@ -564,7 +589,10 @@ class AppSidebarRight {
appImManager.setMutedState(muted); appImManager.setMutedState(muted);
} }
} else { } else {
window.requestAnimationFrame(() => {
this.profileElements.notificationsRow.style.display = 'none'; this.profileElements.notificationsRow.style.display = 'none';
//this.scroll.getScrollTopOffset();
})
} }
if(peerID > 0) { if(peerID > 0) {
@ -590,7 +618,7 @@ class AppSidebarRight {
appMessagesManager.wrapSingleMessage(userFull.pinned_msg_id); appMessagesManager.wrapSingleMessage(userFull.pinned_msg_id);
} }
this.scroll.getScrollTopOffset(); //this.scroll.getScrollTopOffset();
}); });
} else { } else {
let chat = appPeersManager.getPeer(peerID); let chat = appPeersManager.getPeer(peerID);
@ -607,11 +635,11 @@ class AppSidebarRight {
setText(RichTextProcessor.wrapRichText(chatFull.about), this.profileElements.bio); setText(RichTextProcessor.wrapRichText(chatFull.about), this.profileElements.bio);
} }
this.scroll.getScrollTopOffset(); //this.scroll.getScrollTopOffset();
}); });
} }
this.scroll.getScrollTopOffset(); //this.scroll.getScrollTopOffset();
//this.loadSidebarMedia(); //this.loadSidebarMedia();
} }
} }

3
src/lib/appManagers/appWebPagesManager.ts

@ -21,7 +21,8 @@ class AppWebPagesManager {
saveWebPage(apiWebPage: any, messageID?: number, mediaContext?: any) { saveWebPage(apiWebPage: any, messageID?: number, mediaContext?: any) {
if(apiWebPage.photo && apiWebPage.photo._ === 'photo') { if(apiWebPage.photo && apiWebPage.photo._ === 'photo') {
appPhotosManager.savePhoto(apiWebPage.photo, mediaContext); //appPhotosManager.savePhoto(apiWebPage.photo, mediaContext);
apiWebPage.photo = appPhotosManager.savePhoto(apiWebPage.photo, mediaContext);
} else { } else {
delete apiWebPage.photo; delete apiWebPage.photo;
} }

6
src/lib/appManagers/appWebpManager.ts

@ -65,7 +65,11 @@ class AppWebpManager {
await this.loaded; await this.loaded;
this.busyPromise = this.convert(bytes); this.busyPromise = this.convert(bytes);
img.src = await this.busyPromise; let imgTemp = new Image();
imgTemp.src = await this.busyPromise;
imgTemp.onload = () => {
img.src = imgTemp.src;
};
callback(); callback();
this.busyPromise = null; this.busyPromise = null;

5
src/lib/lottieLoader.ts

@ -61,6 +61,11 @@ class LottieLoader {
if(canvas) { if(canvas) {
let c = container.firstElementChild as HTMLCanvasElement; let c = container.firstElementChild as HTMLCanvasElement;
if(!c) {
console.warn('no canvas element for check!', container, animations[i]);
continue;
}
if(!c.height && !c.width && isElementInViewport(container)) { if(!c.height && !c.width && isElementInViewport(container)) {
//console.log('lottie need resize'); //console.log('lottie need resize');
animation.resize(); animation.resize();

13
src/lib/mtproto/apiFileManager.ts

@ -94,12 +94,6 @@ export class ApiFileManager {
var fileName = (location.file_name as string || '').split('.'); var fileName = (location.file_name as string || '').split('.');
var ext: string = fileName[fileName.length - 1] || ''; var ext: string = fileName[fileName.length - 1] || '';
if(location.stickerType == 1) {
ext += 'webp';
} else if(location.stickerType == 2) {
ext += 'tgs';
}
var versionPart = location.version ? ('v' + location.version) : ''; var versionPart = location.version ? ('v' + location.version) : '';
return (fileName[0] ? fileName[0] + '_' : '') + location.id + versionPart + (ext ? '.' + ext : ext); return (fileName[0] ? fileName[0] + '_' : '') + location.id + versionPart + (ext ? '.' + ext : ext);
@ -108,13 +102,6 @@ export class ApiFileManager {
this.log.trace('Empty location', location); this.log.trace('Empty location', location);
} }
var ext: string = 'jpg';
if(location.stickerType == 1) {
ext = 'webp';
} else if(location.stickerType == 2) {
ext += 'tgs';
}
if(location.volume_id) { if(location.volume_id) {
return location.volume_id + '_' + location.local_id + '.' + ext; return location.volume_id + '_' + location.local_id + '.' + ext;
} else { } else {

25
webpack.common.js

@ -1,6 +1,8 @@
const path = require('path'); const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin');
let allowedIPs = ['195.66.140.39', '192.168.31.144', '127.0.0.1', '192.168.31.1', '192.168.31.192'];
module.exports = { module.exports = {
module: { module: {
rules: [ rules: [
@ -74,7 +76,28 @@ module.exports = {
watchContentBase: true, watchContentBase: true,
compress: true, compress: true,
http2: true, http2: true,
port: 9000 host: '0.0.0.0',
port: 9000,
overlay: true,
useLocalIp: true,
before: function(app, server, compiler) {
app.use((req, res, next) => {
let IP = '';
if(req.headers['cf-connecting-ip']) {
IP = req.headers['cf-connecting-ip'];
} else {
IP = req.connection.remoteAddress.split(':').pop();
}
if(!allowedIPs.includes(IP)) {
console.log('Bad IP connecting: ' + IP, req.url);
res.status(404).send('Nothing interesting here.');
} else {
console.log(req.url, IP);
next();
}
});
}
}, },
plugins: [ plugins: [

Loading…
Cancel
Save