Lazy load avatars in channels & members list
This commit is contained in:
parent
0df9aed287
commit
039e238b2f
@ -883,6 +883,7 @@ export default class AppSearchSuper {
|
||||
|
||||
if(!this.membersList) {
|
||||
this.membersList = new SortedUserList();
|
||||
this.membersList.lazyLoadQueue = this.lazyLoadQueue;
|
||||
this.membersList.list.addEventListener('click', (e) => {
|
||||
const li = findUpTag(e.target, 'LI');
|
||||
if(!li) {
|
||||
|
@ -9,10 +9,10 @@ import appProfileManager from "../lib/appManagers/appProfileManager";
|
||||
import rootScope from "../lib/rootScope";
|
||||
import { attachClickEvent, cancelEvent } from "../helpers/dom";
|
||||
import AppMediaViewer, { AppMediaViewerAvatar } from "./appMediaViewer";
|
||||
import { Message, Photo } from "../layer";
|
||||
import { Message } from "../layer";
|
||||
import appPeersManager from "../lib/appManagers/appPeersManager";
|
||||
import appPhotosManager from "../lib/appManagers/appPhotosManager";
|
||||
//import type { LazyLoadQueueIntersector } from "./lazyLoadQueue";
|
||||
import type { LazyLoadQueueIntersector } from "./lazyLoadQueue";
|
||||
|
||||
const onAvatarUpdate = (peerId: number) => {
|
||||
appProfileManager.removeFromAvatarsCache(peerId);
|
||||
@ -98,24 +98,22 @@ export async function openAvatarViewer(target: HTMLElement, peerId: number, midd
|
||||
}
|
||||
}
|
||||
|
||||
const believeMe: Map<number, Set<AvatarElement>> = new Map();
|
||||
const seen: Set<number> = new Set();
|
||||
|
||||
export default class AvatarElement extends HTMLElement {
|
||||
private peerId: number;
|
||||
private isDialog = false;
|
||||
public peerTitle: string;
|
||||
private peerTitle: string;
|
||||
public loadPromises: Promise<any>[];
|
||||
//public lazyLoadQueue: LazyLoadQueueIntersector;
|
||||
//private addedToQueue = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// элемент создан
|
||||
}
|
||||
public lazyLoadQueue: LazyLoadQueueIntersector;
|
||||
private addedToQueue = false;
|
||||
|
||||
connectedCallback() {
|
||||
// браузер вызывает этот метод при добавлении элемента в документ
|
||||
// (может вызываться много раз, если элемент многократно добавляется/удаляется)
|
||||
|
||||
this.isDialog = !!this.getAttribute('dialog');
|
||||
this.isDialog = this.getAttribute('dialog') === '1';
|
||||
if(this.getAttribute('clickable') === '') {
|
||||
this.setAttribute('clickable', 'set');
|
||||
let loading = false;
|
||||
@ -131,13 +129,21 @@ export default class AvatarElement extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
/* disconnectedCallback() {
|
||||
disconnectedCallback() {
|
||||
// браузер вызывает этот метод при удалении элемента из документа
|
||||
// (может вызываться много раз, если элемент многократно добавляется/удаляется)
|
||||
const set = believeMe.get(this.peerId);
|
||||
if(set && set.has(this)) {
|
||||
set.delete(this);
|
||||
if(!set.size) {
|
||||
believeMe.delete(this.peerId);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.lazyLoadQueue) {
|
||||
this.lazyLoadQueue.unobserve(this);
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
static get observedAttributes(): string[] {
|
||||
return ['peer', 'dialog', 'peer-title'/* массив имён атрибутов для отслеживания их изменений */];
|
||||
@ -152,36 +158,88 @@ export default class AvatarElement extends HTMLElement {
|
||||
}
|
||||
|
||||
this.peerId = appPeersManager.getPeerMigratedTo(+newValue) || +newValue;
|
||||
|
||||
const wasPeerId = +oldValue;
|
||||
if(wasPeerId) {
|
||||
const set = believeMe.get(wasPeerId);
|
||||
if(set) {
|
||||
set.delete(this);
|
||||
if(!set.size) {
|
||||
believeMe.delete(wasPeerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.update();
|
||||
} else if(name === 'peer-title') {
|
||||
this.peerTitle = newValue;
|
||||
} else if(name === 'dialog') {
|
||||
this.isDialog = !!+newValue;
|
||||
this.isDialog = newValue === '1';
|
||||
}
|
||||
}
|
||||
|
||||
public update() {
|
||||
/* if(this.lazyLoadQueue) {
|
||||
if(this.addedToQueue) return;
|
||||
this.lazyLoadQueue.push({
|
||||
div: this,
|
||||
load: () => {
|
||||
return appProfileManager.putPhoto(this, this.peerId, this.isDialog, this.peerTitle).finally(() => {
|
||||
this.addedToQueue = false;
|
||||
});
|
||||
if(this.lazyLoadQueue) {
|
||||
if(!seen.has(this.peerId)) {
|
||||
if(this.addedToQueue) return;
|
||||
this.addedToQueue = true;
|
||||
|
||||
let set = believeMe.get(this.peerId);
|
||||
if(!set) {
|
||||
set = new Set();
|
||||
believeMe.set(this.peerId, set);
|
||||
}
|
||||
});
|
||||
this.addedToQueue = true;
|
||||
} else { */
|
||||
const res = appProfileManager.putPhoto(this, this.peerId, this.isDialog, this.peerTitle);
|
||||
if(this.loadPromises && res && res.cached) {
|
||||
this.loadPromises.push(res.loadPromise);
|
||||
res.loadPromise.finally(() => {
|
||||
this.loadPromises = undefined;
|
||||
|
||||
set.add(this);
|
||||
|
||||
this.lazyLoadQueue.push({
|
||||
div: this,
|
||||
load: () => {
|
||||
seen.add(this.peerId);
|
||||
return this.update();
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
} else if(this.addedToQueue) {
|
||||
this.lazyLoadQueue.unobserve(this);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
seen.add(this.peerId);
|
||||
|
||||
const res = appProfileManager.putPhoto(this, this.peerId, this.isDialog, this.peerTitle);
|
||||
const promise = res ? res.loadPromise : Promise.resolve();
|
||||
if(this.loadPromises) {
|
||||
if(res && res.cached) {
|
||||
this.loadPromises.push(promise);
|
||||
}
|
||||
|
||||
promise.finally(() => {
|
||||
this.loadPromises = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
if(this.addedToQueue) {
|
||||
promise.finally(() => {
|
||||
this.addedToQueue = false;
|
||||
});
|
||||
}
|
||||
|
||||
const set = believeMe.get(this.peerId);
|
||||
if(set) {
|
||||
set.delete(this);
|
||||
const arr = Array.from(set);
|
||||
believeMe.delete(this.peerId);
|
||||
|
||||
|
||||
for(let i = 0, length = arr.length; i < length; ++i) {
|
||||
arr[i].update();
|
||||
}
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("avatar-element", AvatarElement);
|
||||
customElements.define('avatar-element', AvatarElement);
|
||||
|
@ -2560,7 +2560,8 @@ export default class ChatBubbles {
|
||||
bubbleContainer,
|
||||
message: messageWithReplies,
|
||||
messageDiv,
|
||||
loadPromises
|
||||
loadPromises,
|
||||
lazyLoadQueue: this.lazyLoadQueue
|
||||
});
|
||||
|
||||
if(isFooter) {
|
||||
|
@ -7,6 +7,7 @@
|
||||
import { getFullDate } from "../../helpers/date";
|
||||
import { formatNumber } from "../../helpers/number";
|
||||
import RichTextProcessor from "../../lib/richtextprocessor";
|
||||
import { LazyLoadQueueIntersector } from "../lazyLoadQueue";
|
||||
import { wrapReply } from "../wrappers";
|
||||
import Chat from "./chat";
|
||||
import RepliesElement from "./replies";
|
||||
@ -65,18 +66,20 @@ export namespace MessageRender {
|
||||
return timeSpan;
|
||||
};
|
||||
|
||||
export const renderReplies = ({bubble, bubbleContainer, message, messageDiv, loadPromises}: {
|
||||
export const renderReplies = ({bubble, bubbleContainer, message, messageDiv, loadPromises, lazyLoadQueue}: {
|
||||
bubble: HTMLElement,
|
||||
bubbleContainer: HTMLElement,
|
||||
message: any,
|
||||
messageDiv: HTMLElement,
|
||||
loadPromises?: Promise<any>[]
|
||||
loadPromises?: Promise<any>[],
|
||||
lazyLoadQueue?: LazyLoadQueueIntersector
|
||||
}) => {
|
||||
const isFooter = !bubble.classList.contains('sticker') && !bubble.classList.contains('emoji-big') && !bubble.classList.contains('round');
|
||||
const repliesFooter = new RepliesElement();
|
||||
repliesFooter.message = message;
|
||||
repliesFooter.type = isFooter ? 'footer' : 'beside';
|
||||
repliesFooter.loadPromises = loadPromises;
|
||||
repliesFooter.lazyLoadQueue = lazyLoadQueue;
|
||||
repliesFooter.init();
|
||||
bubbleContainer.prepend(repliesFooter);
|
||||
return isFooter;
|
||||
|
@ -4,6 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import type { LazyLoadQueueIntersector } from "../lazyLoadQueue";
|
||||
import { formatNumber } from "../../helpers/number";
|
||||
import { Message } from "../../layer";
|
||||
import appMessagesManager from "../../lib/appManagers/appMessagesManager";
|
||||
@ -26,6 +27,7 @@ export default class RepliesElement extends HTMLElement {
|
||||
public message: Message.message;
|
||||
public type: 'footer' | 'beside';
|
||||
public loadPromises: Promise<any>[];
|
||||
public lazyLoadQueue: LazyLoadQueueIntersector;
|
||||
|
||||
private updated = false;
|
||||
|
||||
@ -69,6 +71,7 @@ export default class RepliesElement extends HTMLElement {
|
||||
avatarElem = new AvatarElement();
|
||||
avatarElem.setAttribute('dialog', '0');
|
||||
avatarElem.classList.add('avatar-30');
|
||||
avatarElem.lazyLoadQueue = this.lazyLoadQueue;
|
||||
|
||||
if(this.loadPromises) {
|
||||
avatarElem.loadPromises = this.loadPromises;
|
||||
|
@ -4,6 +4,7 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import type { LazyLoadQueueIntersector } from "./lazyLoadQueue";
|
||||
import appDialogsManager, { DialogDom } from "../lib/appManagers/appDialogsManager";
|
||||
import { isInDOM, positionElementByIndex, replaceContent } from "../helpers/dom";
|
||||
import { getHeavyAnimationPromise } from "../hooks/useHeavyAnimationCheck";
|
||||
@ -20,6 +21,7 @@ export default class SortedUserList {
|
||||
public list: HTMLUListElement;
|
||||
public users: Map<number, SortedUser>;
|
||||
public sorted: Array<SortedUser>;
|
||||
public lazyLoadQueue: LazyLoadQueueIntersector;
|
||||
|
||||
constructor() {
|
||||
this.list = appDialogsManager.createChatList();
|
||||
@ -75,7 +77,8 @@ export default class SortedUserList {
|
||||
avatarSize: 48,
|
||||
autonomous: true,
|
||||
meAsSaved: false,
|
||||
rippleEnabled: false
|
||||
rippleEnabled: false,
|
||||
lazyLoadQueue: this.lazyLoadQueue
|
||||
});
|
||||
|
||||
const sortedUser: SortedUser = {
|
||||
|
@ -596,7 +596,7 @@ export class ApiUpdatesManager {
|
||||
}
|
||||
|
||||
public saveUpdate(update: Update) {
|
||||
this.debug && this.log('saveUpdate', update);
|
||||
//this.debug && this.log('saveUpdate', update);
|
||||
rootScope.dispatchEvent(update._, update as any);
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import appNotificationsManager from "./appNotificationsManager";
|
||||
import PeerTitle from "../../components/peerTitle";
|
||||
import { i18n } from "../langPack";
|
||||
import findUpTag from "../../helpers/dom/findUpTag";
|
||||
import { LazyLoadQueueIntersector } from "../../components/lazyLoadQueue";
|
||||
|
||||
export type DialogDom = {
|
||||
avatarEl: AvatarElement,
|
||||
@ -1213,12 +1214,13 @@ export class AppDialogsManager {
|
||||
meAsSaved?: boolean,
|
||||
append?: boolean,
|
||||
avatarSize?: number,
|
||||
autonomous?: boolean
|
||||
autonomous?: boolean,
|
||||
lazyLoadQueue?: LazyLoadQueueIntersector,
|
||||
}) {
|
||||
return this.addDialog(options.dialog, options.container, options.drawStatus, options.rippleEnabled, options.onlyFirstName, options.meAsSaved, options.append, options.avatarSize, options.autonomous);
|
||||
return this.addDialog(options.dialog, options.container, options.drawStatus, options.rippleEnabled, options.onlyFirstName, options.meAsSaved, options.append, options.avatarSize, options.autonomous, options.lazyLoadQueue);
|
||||
}
|
||||
|
||||
public addDialog(_dialog: Dialog | number, container?: HTMLUListElement | Scrollable | false, drawStatus = true, rippleEnabled = true, onlyFirstName = false, meAsSaved = true, append = true, avatarSize = 54, autonomous = !!container) {
|
||||
public addDialog(_dialog: Dialog | number, container?: HTMLUListElement | Scrollable | false, drawStatus = true, rippleEnabled = true, onlyFirstName = false, meAsSaved = true, append = true, avatarSize = 54, autonomous = !!container, lazyLoadQueue?: LazyLoadQueueIntersector) {
|
||||
let dialog: Dialog;
|
||||
|
||||
if(typeof(_dialog) === 'number') {
|
||||
@ -1248,6 +1250,7 @@ export class AppDialogsManager {
|
||||
}
|
||||
|
||||
const avatarEl = new AvatarElement();
|
||||
avatarEl.lazyLoadQueue = lazyLoadQueue;
|
||||
avatarEl.setAttribute('dialog', meAsSaved ? '1' : '0');
|
||||
avatarEl.setAttribute('peer', '' + peerId);
|
||||
avatarEl.classList.add('dialog-avatar', 'avatar-' + avatarSize);
|
||||
|
Loading…
Reference in New Issue
Block a user