Telegram Web K with changes to work inside I2P https://web.telegram.i2p/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
7.4 KiB

3 years ago
/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
2 years ago
import rootScope from '../lib/rootScope';
import {Message, Photo} from '../layer';
import type LazyLoadQueue from './lazyLoadQueue';
import {attachClickEvent} from '../helpers/dom/clickEvent';
import cancelEvent from '../helpers/dom/cancelEvent';
import AppMediaViewer from './appMediaViewer';
import AppMediaViewerAvatar from './appMediaViewerAvatar';
import isObject from '../helpers/object/isObject';
import {ArgumentTypes} from '../types';
import putPhoto from './putPhoto';
import {recordPromise} from '../helpers/recordPromise';
3 years ago
3 years ago
const onAvatarUpdate = (peerId: PeerId) => {
(Array.from(document.querySelectorAll('avatar-element[data-peer-id="' + peerId + '"]')) as AvatarElement[]).forEach((elem) => {
2 years ago
// console.log('updating avatar:', elem);
3 years ago
elem.update();
});
};
rootScope.addEventListener('avatar_update', onAvatarUpdate);
rootScope.addEventListener('peer_title_edit', async(peerId) => {
if(!(await rootScope.managers.appAvatarsManager.isAvatarCached(peerId))) {
3 years ago
onAvatarUpdate(peerId);
}
});
3 years ago
3 years ago
export async function openAvatarViewer(
2 years ago
target: HTMLElement,
peerId: PeerId,
middleware: () => boolean,
message?: any,
prevTargets?: {element: HTMLElement, item: Photo.photo['id'] | Message.messageService}[],
3 years ago
nextTargets?: typeof prevTargets
) {
3 years ago
let photo = await rootScope.managers.appProfileManager.getFullPhoto(peerId);
3 years ago
if(!middleware() || !photo) {
return;
}
const getTarget = () => {
const good = Array.from(target.querySelectorAll('img')).find((img) => !img.classList.contains('emoji'));
3 years ago
return good ? target : null;
};
3 years ago
if(peerId.isAnyChat()) {
3 years ago
const hadMessage = !!message;
const inputFilter = 'inputMessagesFilterChatPhotos';
if(!message) {
3 years ago
message = await rootScope.managers.appMessagesManager.getSearch({
2 years ago
peerId,
inputFilter: {_: inputFilter},
maxId: 0,
limit: 1
}).then((value) => {
2 years ago
// console.log(lol);
3 years ago
// ! by descend
return value.history[0];
});
if(!middleware()) {
return;
}
}
if(message) {
// ! гений в деле, костылируем (но это гениально)
const messagePhoto = message.action.photo;
if(messagePhoto.id !== photo.id) {
if(!hadMessage) {
3 years ago
message = rootScope.managers.appMessagesManager.generateFakeAvatarMessage(peerId, photo);
3 years ago
} else {
2 years ago
3 years ago
}
}
const f = (arr: typeof prevTargets) => arr.map((el) => ({
3 years ago
element: el.element,
mid: (el.item as Message.messageService).mid,
peerId: (el.item as Message.messageService).peerId
}));
new AppMediaViewer()
.setSearchContext({
peerId,
2 years ago
inputFilter: {_: inputFilter}
3 years ago
})
.openMedia(message, getTarget(), undefined, undefined, prevTargets ? f(prevTargets) : undefined, nextTargets ? f(nextTargets) : undefined);
return;
}
}
if(photo) {
if(!isObject(message) && message) {
photo = await rootScope.managers.appPhotosManager.getPhoto(message);
3 years ago
}
2 years ago
const f = (arr: typeof prevTargets) => arr.map((el) => ({
3 years ago
element: el.element,
photoId: el.item as string
}));
new AppMediaViewerAvatar(peerId).openMedia(
2 years ago
photo.id,
getTarget(),
undefined,
prevTargets ? f(prevTargets) : undefined,
nextTargets ? f(nextTargets) : undefined
);
3 years ago
}
}
3 years ago
const believeMe: Map<PeerId, Set<AvatarElement>> = new Map();
const seen: Set<PeerId> = new Set();
3 years ago
export default class AvatarElement extends HTMLElement {
3 years ago
public peerId: PeerId;
public isDialog: boolean;
public peerTitle: string;
3 years ago
public loadPromises: Promise<any>[];
public lazyLoadQueue: LazyLoadQueue;
public isBig: boolean;
3 years ago
private addedToQueue = false;
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);
}
}
3 years ago
public attachClickEvent() {
let loading = false;
attachClickEvent(this, async(e) => {
cancelEvent(e);
if(loading) return;
2 years ago
// console.log('avatar clicked');
3 years ago
const peerId = this.peerId;
loading = true;
await openAvatarViewer(this, this.peerId, () => this.peerId === peerId);
loading = false;
});
3 years ago
}
3 years ago
public updateOptions(options: Partial<ArgumentTypes<AvatarElement['updateWithOptions']>[0]>) {
2 years ago
for(const i in options) {
3 years ago
// @ts-ignore
this[i] = options[i];
}
}
public updateWithOptions(options: {
peerId: PeerId,
isDialog?: boolean,
isBig?: boolean,
peerTitle?: string,
lazyLoadQueue?: LazyLoadQueue,
3 years ago
loadPromises?: Promise<any>[]
}) {
const wasPeerId = this.peerId;
this.updateOptions(options);
const newPeerId = this.peerId;
if(wasPeerId === newPeerId) {
return;
}
this.peerId = /* rootScope.managers.appPeersManager.getPeerMigratedTo(newPeerId) || */newPeerId;
3 years ago
this.dataset.peerId = '' + newPeerId;
if(wasPeerId) {
const set = believeMe.get(wasPeerId);
if(set) {
set.delete(this);
if(!set.size) {
believeMe.delete(wasPeerId);
3 years ago
}
}
}
3 years ago
return this.update();
3 years ago
}
private r(onlyThumb = false) {
const promise = putPhoto(this, this.peerId, this.isDialog, this.peerTitle, onlyThumb, this.isBig);
// recordPromise(promise, 'avatar putPhoto-' + this.peerId);
3 years ago
if(this.loadPromises) {
this.loadPromises.push(promise);
3 years ago
promise.finally(() => {
this.loadPromises = undefined;
});
}
return promise;
3 years ago
}
public update() {
if(this.lazyLoadQueue) {
if(!seen.has(this.peerId)) {
if(this.addedToQueue) return;
this.addedToQueue = true;
2 years ago
3 years ago
let set = believeMe.get(this.peerId);
if(!set) {
set = new Set();
believeMe.set(this.peerId, set);
}
2 years ago
3 years ago
set.add(this);
this.lazyLoadQueue.push({
2 years ago
div: this,
3 years ago
load: () => {
seen.add(this.peerId);
return this.update();
}
});
return this.r(true);
3 years ago
} else if(this.addedToQueue) {
this.lazyLoadQueue.unobserve(this);
}
2 years ago
}
3 years ago
seen.add(this.peerId);
2 years ago
const promise = this.r();
3 years ago
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);
2 years ago
3 years ago
for(let i = 0, length = arr.length; i < length; ++i) {
arr[i].update();
}
}
return promise;
}
}
customElements.define('avatar-element', AvatarElement);