Fix import order
This commit is contained in:
parent
4d2523d810
commit
6b3b2c343d
@ -718,7 +718,7 @@ export default class AppSearchSuper {
|
|||||||
if(showMembersCount && (peer.participants_count || peer.participants)) {
|
if(showMembersCount && (peer.participants_count || peer.participants)) {
|
||||||
const regExp = new RegExp(`(${escapeRegExp(query)}|${escapeRegExp(cleanSearchText(query))})`, 'gi');
|
const regExp = new RegExp(`(${escapeRegExp(query)}|${escapeRegExp(cleanSearchText(query))})`, 'gi');
|
||||||
dom.titleSpan.innerHTML = dom.titleSpan.innerHTML.replace(regExp, '<i>$1</i>');
|
dom.titleSpan.innerHTML = dom.titleSpan.innerHTML.replace(regExp, '<i>$1</i>');
|
||||||
dom.lastMessageSpan.append(appChatsManager.getChatMembersString(-peerId));
|
dom.lastMessageSpan.append(appProfileManager.getChatMembersString(-peerId));
|
||||||
} else if(peerId === rootScope.myId) {
|
} else if(peerId === rootScope.myId) {
|
||||||
dom.lastMessageSpan.append(i18n('Presence.YourChat'));
|
dom.lastMessageSpan.append(i18n('Presence.YourChat'));
|
||||||
} else {
|
} else {
|
||||||
@ -811,7 +811,7 @@ export default class AppSearchSuper {
|
|||||||
autonomous: true
|
autonomous: true
|
||||||
});
|
});
|
||||||
|
|
||||||
dom.lastMessageSpan.append(peerId > 0 ? appUsersManager.getUserStatusString(peerId) : appChatsManager.getChatMembersString(peerId));
|
dom.lastMessageSpan.append(peerId > 0 ? appUsersManager.getUserStatusString(peerId) : appProfileManager.getChatMembersString(-peerId));
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!state.recentSearch.length) {
|
if(!state.recentSearch.length) {
|
||||||
|
@ -447,7 +447,7 @@ export default class AppSelectPeers {
|
|||||||
|
|
||||||
let subtitleEl: HTMLElement;
|
let subtitleEl: HTMLElement;
|
||||||
if(peerId < 0) {
|
if(peerId < 0) {
|
||||||
subtitleEl = appChatsManager.getChatMembersString(-peerId);
|
subtitleEl = appProfileManager.getChatMembersString(-peerId);
|
||||||
} else if(peerId === rootScope.myId) {
|
} else if(peerId === rootScope.myId) {
|
||||||
subtitleEl = i18n('Presence.YourChat');
|
subtitleEl = i18n('Presence.YourChat');
|
||||||
} else {
|
} else {
|
||||||
|
@ -14,9 +14,10 @@ import appPhotosManager from "../lib/appManagers/appPhotosManager";
|
|||||||
import type { LazyLoadQueueIntersector } from "./lazyLoadQueue";
|
import type { LazyLoadQueueIntersector } from "./lazyLoadQueue";
|
||||||
import { attachClickEvent } from "../helpers/dom/clickEvent";
|
import { attachClickEvent } from "../helpers/dom/clickEvent";
|
||||||
import { cancelEvent } from "../helpers/dom/cancelEvent";
|
import { cancelEvent } from "../helpers/dom/cancelEvent";
|
||||||
|
import appAvatarsManager from "../lib/appManagers/appAvatarsManager";
|
||||||
|
|
||||||
const onAvatarUpdate = (peerId: number) => {
|
const onAvatarUpdate = (peerId: number) => {
|
||||||
appProfileManager.removeFromAvatarsCache(peerId);
|
appAvatarsManager.removeFromAvatarsCache(peerId);
|
||||||
(Array.from(document.querySelectorAll('avatar-element[peer="' + peerId + '"]')) as AvatarElement[]).forEach(elem => {
|
(Array.from(document.querySelectorAll('avatar-element[peer="' + peerId + '"]')) as AvatarElement[]).forEach(elem => {
|
||||||
//console.log('updating avatar:', elem);
|
//console.log('updating avatar:', elem);
|
||||||
elem.update();
|
elem.update();
|
||||||
@ -180,7 +181,7 @@ export default class AvatarElement extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private r(onlyThumb = false) {
|
private r(onlyThumb = false) {
|
||||||
const res = appProfileManager.putPhoto(this, this.peerId, this.isDialog, this.peerTitle, onlyThumb);
|
const res = appAvatarsManager.putPhoto(this, this.peerId, this.isDialog, this.peerTitle, onlyThumb);
|
||||||
const promise = res ? res.loadPromise : Promise.resolve();
|
const promise = res ? res.loadPromise : Promise.resolve();
|
||||||
if(this.loadPromises) {
|
if(this.loadPromises) {
|
||||||
if(res && res.cached) {
|
if(res && res.cached) {
|
||||||
|
@ -48,6 +48,7 @@ import ButtonCorner from "../../buttonCorner";
|
|||||||
import { cancelEvent } from "../../../helpers/dom/cancelEvent";
|
import { cancelEvent } from "../../../helpers/dom/cancelEvent";
|
||||||
import { attachClickEvent } from "../../../helpers/dom/clickEvent";
|
import { attachClickEvent } from "../../../helpers/dom/clickEvent";
|
||||||
import replaceContent from "../../../helpers/dom/replaceContent";
|
import replaceContent from "../../../helpers/dom/replaceContent";
|
||||||
|
import appAvatarsManager from "../../../lib/appManagers/appAvatarsManager";
|
||||||
|
|
||||||
let setText = (text: string, row: Row) => {
|
let setText = (text: string, row: Row) => {
|
||||||
//fastRaf(() => {
|
//fastRaf(() => {
|
||||||
@ -437,7 +438,7 @@ class PeerProfileAvatars {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const photo = appPeersManager.getPeerPhoto(this.peerId);
|
const photo = appPeersManager.getPeerPhoto(this.peerId);
|
||||||
appProfileManager.putAvatar(avatar, this.peerId, photo, 'photo_big', img);
|
appAvatarsManager.putAvatar(avatar, this.peerId, photo, 'photo_big', img);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.avatars.append(avatar);
|
this.avatars.append(avatar);
|
||||||
|
202
src/lib/appManagers/appAvatarsManager.ts
Normal file
202
src/lib/appManagers/appAvatarsManager.ts
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import renderImageFromUrl from "../../helpers/dom/renderImageFromUrl";
|
||||||
|
import replaceContent from "../../helpers/dom/replaceContent";
|
||||||
|
import sequentialDom from "../../helpers/sequentialDom";
|
||||||
|
import { UserProfilePhoto, ChatPhoto, InputFileLocation } from "../../layer";
|
||||||
|
import RichTextProcessor from "../richtextprocessor";
|
||||||
|
import rootScope from "../rootScope";
|
||||||
|
import appDownloadManager from "./appDownloadManager";
|
||||||
|
import appPeersManager from "./appPeersManager";
|
||||||
|
import appPhotosManager from "./appPhotosManager";
|
||||||
|
import appUsersManager from "./appUsersManager";
|
||||||
|
|
||||||
|
type PeerPhotoSize = 'photo_small' | 'photo_big';
|
||||||
|
|
||||||
|
export class AppAvatarsManager {
|
||||||
|
private savedAvatarURLs: {
|
||||||
|
[peerId: number]: {
|
||||||
|
[size in PeerPhotoSize]?: string | Promise<string>
|
||||||
|
}
|
||||||
|
} = {};
|
||||||
|
|
||||||
|
public removeFromAvatarsCache(peerId: number) {
|
||||||
|
if(this.savedAvatarURLs[peerId]) {
|
||||||
|
delete this.savedAvatarURLs[peerId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public loadAvatar(peerId: number, photo: UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto, size: PeerPhotoSize) {
|
||||||
|
const inputPeer = appPeersManager.getInputPeerById(peerId);
|
||||||
|
|
||||||
|
let cached = false;
|
||||||
|
let getAvatarPromise: Promise<string>;
|
||||||
|
let saved = this.savedAvatarURLs[peerId];
|
||||||
|
if(!saved || !saved[size]) {
|
||||||
|
if(!saved) {
|
||||||
|
saved = this.savedAvatarURLs[peerId] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.warn('will invoke downloadSmallFile:', peerId);
|
||||||
|
const peerPhotoFileLocation: InputFileLocation.inputPeerPhotoFileLocation = {
|
||||||
|
_: 'inputPeerPhotoFileLocation',
|
||||||
|
pFlags: {},
|
||||||
|
peer: inputPeer,
|
||||||
|
photo_id: photo.photo_id
|
||||||
|
};
|
||||||
|
|
||||||
|
if(size === 'photo_big') {
|
||||||
|
peerPhotoFileLocation.pFlags.big = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadOptions = {dcId: photo.dc_id, location: peerPhotoFileLocation};
|
||||||
|
|
||||||
|
/* let str: string;
|
||||||
|
const time = Date.now();
|
||||||
|
if(peerId === 0) {
|
||||||
|
str = `download avatar ${peerId}`;
|
||||||
|
} */
|
||||||
|
|
||||||
|
const promise = appDownloadManager.download(downloadOptions);
|
||||||
|
getAvatarPromise = saved[size] = promise.then(blob => {
|
||||||
|
return saved[size] = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
/* if(str) {
|
||||||
|
console.log(str, Date.now() / 1000, Date.now() - time);
|
||||||
|
} */
|
||||||
|
});
|
||||||
|
} else if(typeof(saved[size]) !== 'string') {
|
||||||
|
getAvatarPromise = saved[size] as Promise<any>;
|
||||||
|
} else {
|
||||||
|
getAvatarPromise = Promise.resolve(saved[size]);
|
||||||
|
cached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {cached, loadPromise: getAvatarPromise};
|
||||||
|
}
|
||||||
|
|
||||||
|
public putAvatar(div: HTMLElement, peerId: number, photo: UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto, size: PeerPhotoSize, img = new Image(), onlyThumb = false) {
|
||||||
|
let {cached, loadPromise} = this.loadAvatar(peerId, photo, size);
|
||||||
|
|
||||||
|
let renderThumbPromise: Promise<void>;
|
||||||
|
let callback: () => void;
|
||||||
|
if(cached) {
|
||||||
|
// смотри в misc.ts: renderImageFromUrl
|
||||||
|
callback = () => {
|
||||||
|
replaceContent(div, img);
|
||||||
|
div.dataset.color = '';
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const animate = rootScope.settings.animationsEnabled;
|
||||||
|
if(animate) {
|
||||||
|
img.classList.add('fade-in');
|
||||||
|
}
|
||||||
|
|
||||||
|
let thumbImage: HTMLImageElement;
|
||||||
|
if(photo.stripped_thumb) {
|
||||||
|
thumbImage = new Image();
|
||||||
|
div.classList.add('avatar-relative');
|
||||||
|
thumbImage.classList.add('avatar-photo', 'avatar-photo-thumbnail');
|
||||||
|
img.classList.add('avatar-photo');
|
||||||
|
const url = appPhotosManager.getPreviewURLFromBytes(photo.stripped_thumb);
|
||||||
|
renderThumbPromise = renderImageFromUrl(thumbImage, url).then(() => {
|
||||||
|
replaceContent(div, thumbImage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
callback = () => {
|
||||||
|
if(photo.stripped_thumb) {
|
||||||
|
div.append(img);
|
||||||
|
} else {
|
||||||
|
replaceContent(div, img);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if(div.childElementCount) {
|
||||||
|
sequentialDom.mutateElement(img, () => {
|
||||||
|
div.dataset.color = '';
|
||||||
|
|
||||||
|
if(animate) {
|
||||||
|
img.classList.remove('fade-in');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(thumbImage) {
|
||||||
|
thumbImage.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, animate ? 200 : 0);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderPromise = loadPromise
|
||||||
|
.then((url) => renderImageFromUrl(img, url/* , false */))
|
||||||
|
.then(() => callback());
|
||||||
|
|
||||||
|
return {cached, loadPromise: renderThumbPromise || renderPromise};
|
||||||
|
}
|
||||||
|
|
||||||
|
// peerId === peerId || title
|
||||||
|
public putPhoto(div: HTMLElement, peerId: number, isDialog = false, title = '', onlyThumb = false) {
|
||||||
|
const photo = appPeersManager.getPeerPhoto(peerId);
|
||||||
|
|
||||||
|
const size: PeerPhotoSize = 'photo_small';
|
||||||
|
const avatarAvailable = !!photo;
|
||||||
|
const avatarRendered = div.firstElementChild && !(div.firstElementChild as HTMLElement).classList.contains('emoji');
|
||||||
|
|
||||||
|
const myId = rootScope.myId;
|
||||||
|
|
||||||
|
//console.log('loadDialogPhoto location:', location, inputPeer);
|
||||||
|
if(peerId === myId && isDialog) {
|
||||||
|
div.innerText = '';
|
||||||
|
div.dataset.color = '';
|
||||||
|
div.classList.add('tgico-saved');
|
||||||
|
div.classList.remove('tgico-deletedaccount');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(peerId > 0) {
|
||||||
|
const user = appUsersManager.getUser(peerId);
|
||||||
|
if(user && user.pFlags && user.pFlags.deleted) {
|
||||||
|
div.innerText = '';
|
||||||
|
div.dataset.color = appPeersManager.getPeerColorById(peerId);
|
||||||
|
div.classList.add('tgico-deletedaccount');
|
||||||
|
div.classList.remove('tgico-saved');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!avatarAvailable || !avatarRendered || !this.savedAvatarURLs[peerId]) {
|
||||||
|
let color = '';
|
||||||
|
if(peerId && (peerId !== myId || !isDialog)) {
|
||||||
|
color = appPeersManager.getPeerColorById(peerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.innerText = '';
|
||||||
|
div.classList.remove('tgico-saved', 'tgico-deletedaccount');
|
||||||
|
div.dataset.color = color;
|
||||||
|
|
||||||
|
let abbr: string;
|
||||||
|
if(!title) {
|
||||||
|
const peer = appPeersManager.getPeer(peerId);
|
||||||
|
abbr = peer.initials ?? '';
|
||||||
|
} else {
|
||||||
|
abbr = RichTextProcessor.getAbbreviation(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.innerHTML = abbr;
|
||||||
|
//return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(avatarAvailable/* && false */) {
|
||||||
|
return this.putAvatar(div, peerId, photo, size, undefined, onlyThumb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const appAvatarsManager = new AppAvatarsManager();
|
||||||
|
export default appAvatarsManager;
|
@ -10,17 +10,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { MOUNT_CLASS_TO } from "../../config/debug";
|
import { MOUNT_CLASS_TO } from "../../config/debug";
|
||||||
import { numberThousandSplitter } from "../../helpers/number";
|
|
||||||
import { isObject, safeReplaceObject, copy, deepEqual } from "../../helpers/object";
|
import { isObject, safeReplaceObject, copy, deepEqual } from "../../helpers/object";
|
||||||
import { ChannelParticipant, Chat, ChatAdminRights, ChatBannedRights, ChatFull, ChatParticipant, ChatParticipants, ChatPhoto, InputChannel, InputChatPhoto, InputFile, InputPeer, SendMessageAction, Update, Updates } from "../../layer";
|
import { ChannelParticipant, Chat, ChatAdminRights, ChatBannedRights, ChatParticipant, ChatPhoto, InputChannel, InputChatPhoto, InputFile, InputPeer, Update, Updates } from "../../layer";
|
||||||
import { i18n, LangPackKey } from "../langPack";
|
|
||||||
import apiManagerProxy from "../mtproto/mtprotoworker";
|
import apiManagerProxy from "../mtproto/mtprotoworker";
|
||||||
import apiManager from '../mtproto/mtprotoworker';
|
import apiManager from '../mtproto/mtprotoworker';
|
||||||
import { RichTextProcessor } from "../richtextprocessor";
|
import { RichTextProcessor } from "../richtextprocessor";
|
||||||
import rootScope from "../rootScope";
|
import rootScope from "../rootScope";
|
||||||
import apiUpdatesManager from "./apiUpdatesManager";
|
import apiUpdatesManager from "./apiUpdatesManager";
|
||||||
import appPeersManager from "./appPeersManager";
|
import appPeersManager from "./appPeersManager";
|
||||||
import appProfileManager from "./appProfileManager";
|
|
||||||
import appStateManager from "./appStateManager";
|
import appStateManager from "./appStateManager";
|
||||||
import appUsersManager from "./appUsersManager";
|
import appUsersManager from "./appUsersManager";
|
||||||
|
|
||||||
@ -28,8 +25,6 @@ export type Channel = Chat.channel;
|
|||||||
|
|
||||||
export type ChatRights = keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags'] | 'change_type' | 'change_permissions' | 'delete_chat' | 'view_participants';
|
export type ChatRights = keyof ChatBannedRights['pFlags'] | keyof ChatAdminRights['pFlags'] | 'change_type' | 'change_permissions' | 'delete_chat' | 'view_participants';
|
||||||
|
|
||||||
export type UserTyping = Partial<{userId: number, action: SendMessageAction, timeout: number}>;
|
|
||||||
|
|
||||||
export class AppChatsManager {
|
export class AppChatsManager {
|
||||||
private storage = appStateManager.storages.chats;
|
private storage = appStateManager.storages.chats;
|
||||||
|
|
||||||
@ -38,10 +33,6 @@ export class AppChatsManager {
|
|||||||
//private channelAccess: any;
|
//private channelAccess: any;
|
||||||
//private megagroups: {[id: number]: true};
|
//private megagroups: {[id: number]: true};
|
||||||
|
|
||||||
private megagroupOnlines: {[id: number]: {timestamp: number, onlines: number}};
|
|
||||||
|
|
||||||
private typingsInPeer: {[peerId: number]: UserTyping[]};
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.clear();
|
this.clear();
|
||||||
|
|
||||||
@ -65,11 +56,7 @@ export class AppChatsManager {
|
|||||||
chat.default_banned_rights = update.default_banned_rights;
|
chat.default_banned_rights = update.default_banned_rights;
|
||||||
rootScope.dispatchEvent('chat_update', chatId);
|
rootScope.dispatchEvent('chat_update', chatId);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
updateUserTyping: this.onUpdateUserTyping,
|
|
||||||
updateChatUserTyping: this.onUpdateUserTyping,
|
|
||||||
updateChannelUserTyping: this.onUpdateUserTyping
|
|
||||||
});
|
});
|
||||||
|
|
||||||
appStateManager.getState().then((state) => {
|
appStateManager.getState().then((state) => {
|
||||||
@ -119,81 +106,6 @@ export class AppChatsManager {
|
|||||||
} else {
|
} else {
|
||||||
this.chats = {};
|
this.chats = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.megagroupOnlines = {};
|
|
||||||
this.typingsInPeer = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
private onUpdateUserTyping = (update: Update.updateUserTyping | Update.updateChatUserTyping | Update.updateChannelUserTyping) => {
|
|
||||||
const fromId = (update as Update.updateUserTyping).user_id || appPeersManager.getPeerId((update as Update.updateChatUserTyping).from_id);
|
|
||||||
if(rootScope.myId === fromId || update.action._ === 'speakingInGroupCallAction') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const peerId = update._ === 'updateUserTyping' ?
|
|
||||||
fromId :
|
|
||||||
-((update as Update.updateChatUserTyping).chat_id || (update as Update.updateChannelUserTyping).channel_id);
|
|
||||||
const typings = this.typingsInPeer[peerId] ?? (this.typingsInPeer[peerId] = []);
|
|
||||||
let typing = typings.find(t => t.userId === fromId);
|
|
||||||
|
|
||||||
const cancelAction = () => {
|
|
||||||
delete typing.timeout;
|
|
||||||
//typings.findAndSplice(t => t === typing);
|
|
||||||
const idx = typings.indexOf(typing);
|
|
||||||
if(idx !== -1) {
|
|
||||||
typings.splice(idx, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
rootScope.dispatchEvent('peer_typings', {peerId, typings});
|
|
||||||
|
|
||||||
if(!typings.length) {
|
|
||||||
delete this.typingsInPeer[peerId];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(typing && typing.timeout !== undefined) {
|
|
||||||
clearTimeout(typing.timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(update.action._ === 'sendMessageCancelAction') {
|
|
||||||
if(!typing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelAction();
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if(!typing) {
|
|
||||||
typing = {
|
|
||||||
userId: fromId
|
|
||||||
};
|
|
||||||
|
|
||||||
typings.push(typing);
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log('updateChatUserTyping', update, typings);
|
|
||||||
|
|
||||||
typing.action = update.action;
|
|
||||||
|
|
||||||
if(!appUsersManager.hasUser(fromId)) {
|
|
||||||
if(update._ === 'updateChatUserTyping') {
|
|
||||||
if(update.chat_id && appChatsManager.hasChat(update.chat_id) && !appChatsManager.isChannel(update.chat_id)) {
|
|
||||||
appProfileManager.getChatFull(update.chat_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//return;
|
|
||||||
}
|
|
||||||
|
|
||||||
appUsersManager.forceUserOnline(fromId);
|
|
||||||
|
|
||||||
typing.timeout = window.setTimeout(cancelAction, 6000);
|
|
||||||
rootScope.dispatchEvent('peer_typings', {peerId, typings});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public getPeerTypings(peerId: number) {
|
|
||||||
return this.typingsInPeer[peerId];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public saveApiChats(apiChats: any[], override?: boolean) {
|
public saveApiChats(apiChats: any[], override?: boolean) {
|
||||||
@ -486,27 +398,6 @@ export class AppChatsManager {
|
|||||||
return 'g' + id;
|
return 'g' + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getChatMembersString(id: number) {
|
|
||||||
const chat = this.getChat(id);
|
|
||||||
const chatFull = appProfileManager.chatsFull[id];
|
|
||||||
let count: number;
|
|
||||||
if(chatFull) {
|
|
||||||
if(chatFull._ === 'channelFull') {
|
|
||||||
count = chatFull.participants_count;
|
|
||||||
} else {
|
|
||||||
count = (chatFull.participants as ChatParticipants.chatParticipants).participants?.length;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
count = chat.participants_count || chat.participants?.participants.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isChannel = this.isBroadcast(id);
|
|
||||||
count = count || 1;
|
|
||||||
|
|
||||||
let key: LangPackKey = isChannel ? 'Peer.Status.Subscribers' : 'Peer.Status.Member';
|
|
||||||
return i18n(key, [numberThousandSplitter(count)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* public wrapForFull(id: number, fullChat: any) {
|
/* public wrapForFull(id: number, fullChat: any) {
|
||||||
const chatFull = copy(fullChat);
|
const chatFull = copy(fullChat);
|
||||||
const chat = this.getChat(id);
|
const chat = this.getChat(id);
|
||||||
@ -600,45 +491,6 @@ export class AppChatsManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getOnlines(id: number): Promise<number> {
|
|
||||||
if(this.isMegagroup(id)) {
|
|
||||||
const timestamp = Date.now() / 1000 | 0;
|
|
||||||
const cached = this.megagroupOnlines[id] ?? (this.megagroupOnlines[id] = {timestamp: 0, onlines: 1});
|
|
||||||
if((timestamp - cached.timestamp) < 60) {
|
|
||||||
return cached.onlines;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await apiManager.invokeApi('messages.getOnlines', {
|
|
||||||
peer: this.getChannelInputPeer(id)
|
|
||||||
});
|
|
||||||
|
|
||||||
const onlines = res.onlines ?? 1;
|
|
||||||
cached.timestamp = timestamp;
|
|
||||||
cached.onlines = onlines;
|
|
||||||
|
|
||||||
return onlines;
|
|
||||||
} else if(this.isBroadcast(id)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const chatInfo = await appProfileManager.getChatFull(id);
|
|
||||||
const _participants = (chatInfo as ChatFull.chatFull).participants as ChatParticipants.chatParticipants;
|
|
||||||
if(_participants && _participants.participants) {
|
|
||||||
const participants = _participants.participants;
|
|
||||||
|
|
||||||
return participants.reduce((acc: number, participant) => {
|
|
||||||
const user = appUsersManager.getUser(participant.user_id);
|
|
||||||
if(user && user.status && user.status._ === 'userStatusOnline') {
|
|
||||||
return acc + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, 0);
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private onChatUpdated = (chatId: number, updates: any) => {
|
private onChatUpdated = (chatId: number, updates: any) => {
|
||||||
//console.log('onChatUpdated', chatId, updates);
|
//console.log('onChatUpdated', chatId, updates);
|
||||||
|
|
||||||
@ -647,7 +499,7 @@ export class AppChatsManager {
|
|||||||
/* updates.updates &&
|
/* updates.updates &&
|
||||||
updates.updates.length && */
|
updates.updates.length && */
|
||||||
this.isChannel(chatId)) {
|
this.isChannel(chatId)) {
|
||||||
appProfileManager.invalidateChannelParticipants(chatId);
|
rootScope.dispatchEvent('invalidate_participants', chatId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,6 +103,7 @@ export class AppImManager {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
apiUpdatesManager.attach();
|
apiUpdatesManager.attach();
|
||||||
|
appNotificationsManager.start();
|
||||||
|
|
||||||
this.log = logger('IM', LogTypes.Log | LogTypes.Warn | LogTypes.Debug | LogTypes.Error);
|
this.log = logger('IM', LogTypes.Log | LogTypes.Warn | LogTypes.Debug | LogTypes.Error);
|
||||||
|
|
||||||
@ -1035,7 +1036,7 @@ export class AppImManager {
|
|||||||
|
|
||||||
public getPeerTyping(peerId: number, container?: HTMLElement) {
|
public getPeerTyping(peerId: number, container?: HTMLElement) {
|
||||||
if(!appUsersManager.isBot(peerId)) {
|
if(!appUsersManager.isBot(peerId)) {
|
||||||
const typings = appChatsManager.getPeerTypings(peerId);
|
const typings = appProfileManager.getPeerTypings(peerId);
|
||||||
if(!typings || !typings.length) {
|
if(!typings || !typings.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1152,7 +1153,7 @@ export class AppImManager {
|
|||||||
|
|
||||||
const participants_count = chatInfo.participants_count || (chatInfo.participants && chatInfo.participants.participants && chatInfo.participants.participants.length) || 1;
|
const participants_count = chatInfo.participants_count || (chatInfo.participants && chatInfo.participants.participants && chatInfo.participants.participants.length) || 1;
|
||||||
//if(participants_count) {
|
//if(participants_count) {
|
||||||
subtitle = appChatsManager.getChatMembersString(-peerId);
|
subtitle = appProfileManager.getChatMembersString(-peerId);
|
||||||
|
|
||||||
if(participants_count < 2) return subtitle;
|
if(participants_count < 2) return subtitle;
|
||||||
/* const onlines = await appChatsManager.getOnlines(chat.id);
|
/* const onlines = await appChatsManager.getOnlines(chat.id);
|
||||||
|
@ -53,6 +53,7 @@ import htmlToDocumentFragment from "../../helpers/dom/htmlToDocumentFragment";
|
|||||||
import htmlToSpan from "../../helpers/dom/htmlToSpan";
|
import htmlToSpan from "../../helpers/dom/htmlToSpan";
|
||||||
import { REPLIES_PEER_ID } from "../mtproto/mtproto_config";
|
import { REPLIES_PEER_ID } from "../mtproto/mtproto_config";
|
||||||
import formatCallDuration from "../../helpers/formatCallDuration";
|
import formatCallDuration from "../../helpers/formatCallDuration";
|
||||||
|
import appAvatarsManager from "./appAvatarsManager";
|
||||||
|
|
||||||
//console.trace('include');
|
//console.trace('include');
|
||||||
// TODO: если удалить сообщение в непрогруженном диалоге, то при обновлении, из-за стейта, последнего сообщения в чатлисте не будет
|
// TODO: если удалить сообщение в непрогруженном диалоге, то при обновлении, из-за стейта, последнего сообщения в чатлисте не будет
|
||||||
@ -304,8 +305,6 @@ export class AppMessagesManager {
|
|||||||
this.maxSeenId = state.maxSeenMsgId;
|
this.maxSeenId = state.maxSeenMsgId;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
appNotificationsManager.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public construct() {
|
public construct() {
|
||||||
@ -4546,7 +4545,7 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
const peerPhoto = appPeersManager.getPeerPhoto(peerId);
|
const peerPhoto = appPeersManager.getPeerPhoto(peerId);
|
||||||
if(peerPhoto) {
|
if(peerPhoto) {
|
||||||
appProfileManager.loadAvatar(peerId, peerPhoto, 'photo_small').loadPromise.then(url => {
|
appAvatarsManager.loadAvatar(peerId, peerPhoto, 'photo_small').loadPromise.then(url => {
|
||||||
if(message.pFlags.unread) {
|
if(message.pFlags.unread) {
|
||||||
notification.image = url;
|
notification.image = url;
|
||||||
appNotificationsManager.notify(notification);
|
appNotificationsManager.notify(notification);
|
||||||
|
@ -706,7 +706,6 @@ export class AppNotificationsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private registerDevice(tokenData: PushSubscriptionNotify) {
|
private registerDevice(tokenData: PushSubscriptionNotify) {
|
||||||
return;
|
|
||||||
if(this.registeredDevice && deepEqual(this.registeredDevice, tokenData)) {
|
if(this.registeredDevice && deepEqual(this.registeredDevice, tokenData)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -725,7 +724,6 @@ export class AppNotificationsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private unregisterDevice(tokenData: PushSubscriptionNotify) {
|
private unregisterDevice(tokenData: PushSubscriptionNotify) {
|
||||||
return;
|
|
||||||
if(!this.registeredDevice) {
|
if(!this.registeredDevice) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,9 @@
|
|||||||
|
|
||||||
import { MOUNT_CLASS_TO } from "../../config/debug";
|
import { MOUNT_CLASS_TO } from "../../config/debug";
|
||||||
import { tsNow } from "../../helpers/date";
|
import { tsNow } from "../../helpers/date";
|
||||||
import renderImageFromUrl from "../../helpers/dom/renderImageFromUrl";
|
import { numberThousandSplitter } from "../../helpers/number";
|
||||||
import replaceContent from "../../helpers/dom/replaceContent";
|
import { ChannelParticipantsFilter, ChannelsChannelParticipants, Chat, ChatFull, ChatParticipants, ChatPhoto, ExportedChatInvite, InputChannel, InputFile, InputFileLocation, PhotoSize, SendMessageAction, Update, UserFull, UserProfilePhoto } from "../../layer";
|
||||||
import sequentialDom from "../../helpers/sequentialDom";
|
import { LangPackKey, i18n } from "../langPack";
|
||||||
import { ChannelParticipantsFilter, ChannelsChannelParticipants, Chat, ChatFull, ChatParticipants, ChatPhoto, ExportedChatInvite, InputChannel, InputFile, InputFileLocation, PhotoSize, Update, UserFull, UserProfilePhoto } from "../../layer";
|
|
||||||
//import apiManager from '../mtproto/apiManager';
|
//import apiManager from '../mtproto/apiManager';
|
||||||
import apiManager from '../mtproto/mtprotoworker';
|
import apiManager from '../mtproto/mtprotoworker';
|
||||||
import { RichTextProcessor } from "../richtextprocessor";
|
import { RichTextProcessor } from "../richtextprocessor";
|
||||||
@ -22,13 +21,12 @@ import rootScope from "../rootScope";
|
|||||||
import SearchIndex from "../searchIndex";
|
import SearchIndex from "../searchIndex";
|
||||||
import apiUpdatesManager from "./apiUpdatesManager";
|
import apiUpdatesManager from "./apiUpdatesManager";
|
||||||
import appChatsManager from "./appChatsManager";
|
import appChatsManager from "./appChatsManager";
|
||||||
import appDownloadManager from "./appDownloadManager";
|
|
||||||
import appNotificationsManager from "./appNotificationsManager";
|
import appNotificationsManager from "./appNotificationsManager";
|
||||||
import appPeersManager from "./appPeersManager";
|
import appPeersManager from "./appPeersManager";
|
||||||
import appPhotosManager, { MyPhoto } from "./appPhotosManager";
|
import appPhotosManager from "./appPhotosManager";
|
||||||
import appUsersManager, { User } from "./appUsersManager";
|
import appUsersManager, { User } from "./appUsersManager";
|
||||||
|
|
||||||
type PeerPhotoSize = 'photo_small' | 'photo_big';
|
export type UserTyping = Partial<{userId: number, action: SendMessageAction, timeout: number}>;
|
||||||
|
|
||||||
export class AppProfileManager {
|
export class AppProfileManager {
|
||||||
//private botInfos: any = {};
|
//private botInfos: any = {};
|
||||||
@ -36,11 +34,9 @@ export class AppProfileManager {
|
|||||||
public chatsFull: {[id: string]: ChatFull} = {};
|
public chatsFull: {[id: string]: ChatFull} = {};
|
||||||
private fullPromises: {[peerId: string]: Promise<ChatFull.chatFull | ChatFull.channelFull | UserFull>} = {};
|
private fullPromises: {[peerId: string]: Promise<ChatFull.chatFull | ChatFull.channelFull | UserFull>} = {};
|
||||||
|
|
||||||
private savedAvatarURLs: {
|
private megagroupOnlines: {[id: number]: {timestamp: number, onlines: number}};
|
||||||
[peerId: number]: {
|
|
||||||
[size in PeerPhotoSize]?: string | Promise<string>
|
private typingsInPeer: {[peerId: number]: UserTyping[]};
|
||||||
}
|
|
||||||
} = {};
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
rootScope.addMultipleEventsListeners({
|
rootScope.addMultipleEventsListeners({
|
||||||
@ -93,7 +89,11 @@ export class AppProfileManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
updateUserTyping: this.onUpdateUserTyping,
|
||||||
|
updateChatUserTyping: this.onUpdateUserTyping,
|
||||||
|
updateChannelUserTyping: this.onUpdateUserTyping
|
||||||
});
|
});
|
||||||
|
|
||||||
rootScope.addEventListener('chat_update', (chatId) => {
|
rootScope.addEventListener('chat_update', (chatId) => {
|
||||||
@ -121,6 +121,13 @@ export class AppProfileManager {
|
|||||||
rootScope.dispatchEvent('chat_full_update', chatId);
|
rootScope.dispatchEvent('chat_full_update', chatId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
rootScope.addEventListener('invalidate_participants', chatId => {
|
||||||
|
this.invalidateChannelParticipants(chatId);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.megagroupOnlines = {};
|
||||||
|
this.typingsInPeer = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* public saveBotInfo(botInfo: any) {
|
/* public saveBotInfo(botInfo: any) {
|
||||||
@ -457,177 +464,144 @@ export class AppProfileManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeFromAvatarsCache(peerId: number) {
|
public getChatMembersString(id: number) {
|
||||||
if(this.savedAvatarURLs[peerId]) {
|
const chat = appChatsManager.getChat(id);
|
||||||
delete this.savedAvatarURLs[peerId];
|
const chatFull = this.chatsFull[id];
|
||||||
|
let count: number;
|
||||||
|
if(chatFull) {
|
||||||
|
if(chatFull._ === 'channelFull') {
|
||||||
|
count = chatFull.participants_count;
|
||||||
|
} else {
|
||||||
|
count = (chatFull.participants as ChatParticipants.chatParticipants).participants?.length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count = chat.participants_count || chat.participants?.participants.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isChannel = appChatsManager.isBroadcast(id);
|
||||||
|
count = count || 1;
|
||||||
|
|
||||||
|
let key: LangPackKey = isChannel ? 'Peer.Status.Subscribers' : 'Peer.Status.Member';
|
||||||
|
return i18n(key, [numberThousandSplitter(count)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadAvatar(peerId: number, photo: UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto, size: PeerPhotoSize) {
|
public async getOnlines(id: number): Promise<number> {
|
||||||
const inputPeer = appPeersManager.getInputPeerById(peerId);
|
if(appChatsManager.isMegagroup(id)) {
|
||||||
|
const timestamp = Date.now() / 1000 | 0;
|
||||||
let cached = false;
|
const cached = this.megagroupOnlines[id] ?? (this.megagroupOnlines[id] = {timestamp: 0, onlines: 1});
|
||||||
let getAvatarPromise: Promise<string>;
|
if((timestamp - cached.timestamp) < 60) {
|
||||||
let saved = this.savedAvatarURLs[peerId];
|
return cached.onlines;
|
||||||
if(!saved || !saved[size]) {
|
|
||||||
if(!saved) {
|
|
||||||
saved = this.savedAvatarURLs[peerId] = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.warn('will invoke downloadSmallFile:', peerId);
|
const res = await apiManager.invokeApi('messages.getOnlines', {
|
||||||
const peerPhotoFileLocation: InputFileLocation.inputPeerPhotoFileLocation = {
|
peer: appChatsManager.getChannelInputPeer(id)
|
||||||
_: 'inputPeerPhotoFileLocation',
|
|
||||||
pFlags: {},
|
|
||||||
peer: inputPeer,
|
|
||||||
photo_id: photo.photo_id
|
|
||||||
};
|
|
||||||
|
|
||||||
if(size === 'photo_big') {
|
|
||||||
peerPhotoFileLocation.pFlags.big = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const downloadOptions = {dcId: photo.dc_id, location: peerPhotoFileLocation};
|
|
||||||
|
|
||||||
/* let str: string;
|
|
||||||
const time = Date.now();
|
|
||||||
if(peerId === 0) {
|
|
||||||
str = `download avatar ${peerId}`;
|
|
||||||
} */
|
|
||||||
|
|
||||||
const promise = appDownloadManager.download(downloadOptions);
|
|
||||||
getAvatarPromise = saved[size] = promise.then(blob => {
|
|
||||||
return saved[size] = URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
/* if(str) {
|
|
||||||
console.log(str, Date.now() / 1000, Date.now() - time);
|
|
||||||
} */
|
|
||||||
});
|
});
|
||||||
} else if(typeof(saved[size]) !== 'string') {
|
|
||||||
getAvatarPromise = saved[size] as Promise<any>;
|
const onlines = res.onlines ?? 1;
|
||||||
} else {
|
cached.timestamp = timestamp;
|
||||||
getAvatarPromise = Promise.resolve(saved[size]);
|
cached.onlines = onlines;
|
||||||
cached = true;
|
|
||||||
|
return onlines;
|
||||||
|
} else if(appChatsManager.isBroadcast(id)) {
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {cached, loadPromise: getAvatarPromise};
|
const chatInfo = await this.getChatFull(id);
|
||||||
}
|
const _participants = (chatInfo as ChatFull.chatFull).participants as ChatParticipants.chatParticipants;
|
||||||
|
if(_participants && _participants.participants) {
|
||||||
|
const participants = _participants.participants;
|
||||||
|
|
||||||
public putAvatar(div: HTMLElement, peerId: number, photo: UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto, size: PeerPhotoSize, img = new Image(), onlyThumb = false) {
|
return participants.reduce((acc: number, participant) => {
|
||||||
let {cached, loadPromise} = this.loadAvatar(peerId, photo, size);
|
const user = appUsersManager.getUser(participant.user_id);
|
||||||
|
if(user && user.status && user.status._ === 'userStatusOnline') {
|
||||||
let renderThumbPromise: Promise<void>;
|
return acc + 1;
|
||||||
let callback: () => void;
|
|
||||||
if(cached) {
|
|
||||||
// смотри в misc.ts: renderImageFromUrl
|
|
||||||
callback = () => {
|
|
||||||
replaceContent(div, img);
|
|
||||||
div.dataset.color = '';
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const animate = rootScope.settings.animationsEnabled;
|
|
||||||
if(animate) {
|
|
||||||
img.classList.add('fade-in');
|
|
||||||
}
|
|
||||||
|
|
||||||
let thumbImage: HTMLImageElement;
|
|
||||||
if(photo.stripped_thumb) {
|
|
||||||
thumbImage = new Image();
|
|
||||||
div.classList.add('avatar-relative');
|
|
||||||
thumbImage.classList.add('avatar-photo', 'avatar-photo-thumbnail');
|
|
||||||
img.classList.add('avatar-photo');
|
|
||||||
const url = appPhotosManager.getPreviewURLFromBytes(photo.stripped_thumb);
|
|
||||||
renderThumbPromise = renderImageFromUrl(thumbImage, url).then(() => {
|
|
||||||
replaceContent(div, thumbImage);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
callback = () => {
|
|
||||||
if(photo.stripped_thumb) {
|
|
||||||
div.append(img);
|
|
||||||
} else {
|
|
||||||
replaceContent(div, img);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
return acc;
|
||||||
if(div.childElementCount) {
|
}, 0);
|
||||||
sequentialDom.mutateElement(img, () => {
|
} else {
|
||||||
div.dataset.color = '';
|
return 1;
|
||||||
|
|
||||||
if(animate) {
|
|
||||||
img.classList.remove('fade-in');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(thumbImage) {
|
|
||||||
thumbImage.remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, animate ? 200 : 0);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderPromise = loadPromise
|
|
||||||
.then((url) => renderImageFromUrl(img, url/* , false */))
|
|
||||||
.then(() => callback());
|
|
||||||
|
|
||||||
return {cached, loadPromise: renderThumbPromise || renderPromise};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// peerId === peerId || title
|
private onUpdateUserTyping = (update: Update.updateUserTyping | Update.updateChatUserTyping | Update.updateChannelUserTyping) => {
|
||||||
public putPhoto(div: HTMLElement, peerId: number, isDialog = false, title = '', onlyThumb = false) {
|
const fromId = (update as Update.updateUserTyping).user_id || appPeersManager.getPeerId((update as Update.updateChatUserTyping).from_id);
|
||||||
const photo = appPeersManager.getPeerPhoto(peerId);
|
if(rootScope.myId === fromId || update.action._ === 'speakingInGroupCallAction') {
|
||||||
|
|
||||||
const size: PeerPhotoSize = 'photo_small';
|
|
||||||
const avatarAvailable = !!photo;
|
|
||||||
const avatarRendered = div.firstElementChild && !(div.firstElementChild as HTMLElement).classList.contains('emoji');
|
|
||||||
|
|
||||||
const myId = rootScope.myId;
|
|
||||||
|
|
||||||
//console.log('loadDialogPhoto location:', location, inputPeer);
|
|
||||||
if(peerId === myId && isDialog) {
|
|
||||||
div.innerText = '';
|
|
||||||
div.dataset.color = '';
|
|
||||||
div.classList.add('tgico-saved');
|
|
||||||
div.classList.remove('tgico-deletedaccount');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(peerId > 0) {
|
const peerId = update._ === 'updateUserTyping' ?
|
||||||
const user = appUsersManager.getUser(peerId);
|
fromId :
|
||||||
if(user && user.pFlags && user.pFlags.deleted) {
|
-((update as Update.updateChatUserTyping).chat_id || (update as Update.updateChannelUserTyping).channel_id);
|
||||||
div.innerText = '';
|
const typings = this.typingsInPeer[peerId] ?? (this.typingsInPeer[peerId] = []);
|
||||||
div.dataset.color = appPeersManager.getPeerColorById(peerId);
|
let typing = typings.find(t => t.userId === fromId);
|
||||||
div.classList.add('tgico-deletedaccount');
|
|
||||||
div.classList.remove('tgico-saved');
|
const cancelAction = () => {
|
||||||
|
delete typing.timeout;
|
||||||
|
//typings.findAndSplice(t => t === typing);
|
||||||
|
const idx = typings.indexOf(typing);
|
||||||
|
if(idx !== -1) {
|
||||||
|
typings.splice(idx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rootScope.dispatchEvent('peer_typings', {peerId, typings});
|
||||||
|
|
||||||
|
if(!typings.length) {
|
||||||
|
delete this.typingsInPeer[peerId];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(typing && typing.timeout !== undefined) {
|
||||||
|
clearTimeout(typing.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(update.action._ === 'sendMessageCancelAction') {
|
||||||
|
if(!typing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancelAction();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!avatarAvailable || !avatarRendered || !this.savedAvatarURLs[peerId]) {
|
if(!typing) {
|
||||||
let color = '';
|
typing = {
|
||||||
if(peerId && (peerId !== myId || !isDialog)) {
|
userId: fromId
|
||||||
color = appPeersManager.getPeerColorById(peerId);
|
};
|
||||||
|
|
||||||
|
typings.push(typing);
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log('updateChatUserTyping', update, typings);
|
||||||
|
|
||||||
|
typing.action = update.action;
|
||||||
|
|
||||||
|
const hasUser = appUsersManager.hasUser(fromId);
|
||||||
|
if(!hasUser) {
|
||||||
|
// let's load user here
|
||||||
|
if(update._ === 'updateChatUserTyping') {
|
||||||
|
if(update.chat_id && appChatsManager.hasChat(update.chat_id) && !appChatsManager.isChannel(update.chat_id)) {
|
||||||
|
appProfileManager.getChatFull(update.chat_id).then(() => {
|
||||||
|
if(typing.timeout !== undefined && appUsersManager.hasUser(fromId)) {
|
||||||
|
rootScope.dispatchEvent('peer_typings', {peerId, typings});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.innerText = '';
|
//return;
|
||||||
div.classList.remove('tgico-saved', 'tgico-deletedaccount');
|
} else {
|
||||||
div.dataset.color = color;
|
appUsersManager.forceUserOnline(fromId);
|
||||||
|
|
||||||
let abbr: string;
|
|
||||||
if(!title) {
|
|
||||||
const peer = appPeersManager.getPeer(peerId);
|
|
||||||
abbr = peer.initials ?? '';
|
|
||||||
} else {
|
|
||||||
abbr = RichTextProcessor.getAbbreviation(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
div.innerHTML = abbr;
|
|
||||||
//return Promise.resolve(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(avatarAvailable/* && false */) {
|
typing.timeout = window.setTimeout(cancelAction, 6000);
|
||||||
return this.putAvatar(div, peerId, photo, size, undefined, onlyThumb);
|
if(hasUser) {
|
||||||
|
rootScope.dispatchEvent('peer_typings', {peerId, typings});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public getPeerTypings(peerId: number) {
|
||||||
|
return this.typingsInPeer[peerId];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import type { AppMessagesManager, Dialog, MessagesStorage } from "./appManagers/
|
|||||||
import type { Poll, PollResults } from "./appManagers/appPollsManager";
|
import type { Poll, PollResults } from "./appManagers/appPollsManager";
|
||||||
import type { MyDialogFilter } from "./storages/filters";
|
import type { MyDialogFilter } from "./storages/filters";
|
||||||
import type { ConnectionStatusChange } from "../types";
|
import type { ConnectionStatusChange } from "../types";
|
||||||
import type { UserTyping } from "./appManagers/appChatsManager";
|
import type { UserTyping } from "./appManagers/appProfileManager";
|
||||||
import type Chat from "../components/chat/chat";
|
import type Chat from "../components/chat/chat";
|
||||||
import type { UserAuth } from "./mtproto/mtproto_config";
|
import type { UserAuth } from "./mtproto/mtproto_config";
|
||||||
import type { State, Theme } from "./appManagers/appStateManager";
|
import type { State, Theme } from "./appManagers/appStateManager";
|
||||||
@ -86,6 +86,7 @@ export type BroadcastEvents = {
|
|||||||
'chat_full_update': number,
|
'chat_full_update': number,
|
||||||
'poll_update': {poll: Poll, results: PollResults},
|
'poll_update': {poll: Poll, results: PollResults},
|
||||||
'chat_update': number,
|
'chat_update': number,
|
||||||
|
'invalidate_participants': number,
|
||||||
//'channel_settings': {channelId: number},
|
//'channel_settings': {channelId: number},
|
||||||
'webpage_updated': {id: string, msgs: number[]},
|
'webpage_updated': {id: string, msgs: number[]},
|
||||||
|
|
||||||
|
@ -9,10 +9,7 @@ import { AuthSentCode, AuthSentCodeType, AuthSignIn } from '../layer';
|
|||||||
import appStateManager from '../lib/appManagers/appStateManager';
|
import appStateManager from '../lib/appManagers/appStateManager';
|
||||||
import apiManager from '../lib/mtproto/mtprotoworker';
|
import apiManager from '../lib/mtproto/mtprotoworker';
|
||||||
import Page from './page';
|
import Page from './page';
|
||||||
import pageIm from './pageIm';
|
|
||||||
import pagePassword from './pagePassword';
|
|
||||||
import pageSignIn from './pageSignIn';
|
import pageSignIn from './pageSignIn';
|
||||||
import pageSignUp from './pageSignUp';
|
|
||||||
import TrackingMonkey from '../components/monkeys/tracking';
|
import TrackingMonkey from '../components/monkeys/tracking';
|
||||||
import CodeInputField from '../components/codeInputField';
|
import CodeInputField from '../components/codeInputField';
|
||||||
import { i18n, LangPackKey } from '../lib/langPack';
|
import { i18n, LangPackKey } from '../lib/langPack';
|
||||||
@ -72,15 +69,19 @@ let onFirstMount = (): Promise<any> => {
|
|||||||
case 'auth.authorization':
|
case 'auth.authorization':
|
||||||
apiManager.setUserAuth(response.user.id);
|
apiManager.setUserAuth(response.user.id);
|
||||||
|
|
||||||
pageIm.mount();
|
import('./pageIm').then(m => {
|
||||||
|
m.default.mount();
|
||||||
|
});
|
||||||
cleanup();
|
cleanup();
|
||||||
break;
|
break;
|
||||||
case 'auth.authorizationSignUpRequired':
|
case 'auth.authorizationSignUpRequired':
|
||||||
//console.log('Registration needed!');
|
//console.log('Registration needed!');
|
||||||
|
|
||||||
pageSignUp.mount({
|
import('./pageSignUp').then(m => {
|
||||||
'phone_number': authCode.phone_number,
|
m.default.mount({
|
||||||
'phone_code_hash': authCode.phone_code_hash
|
'phone_number': authCode.phone_number,
|
||||||
|
'phone_code_hash': authCode.phone_code_hash
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
@ -96,7 +97,7 @@ let onFirstMount = (): Promise<any> => {
|
|||||||
//console.warn('pageAuthCode: SESSION_PASSWORD_NEEDED');
|
//console.warn('pageAuthCode: SESSION_PASSWORD_NEEDED');
|
||||||
good = true;
|
good = true;
|
||||||
err.handled = true;
|
err.handled = true;
|
||||||
await pagePassword.mount();
|
await (await import('./pagePassword')).default.mount(); // lol
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
codeInput.value = '';
|
codeInput.value = '';
|
||||||
}, 300);
|
}, 300);
|
||||||
|
@ -10,7 +10,6 @@ import { AccountPassword } from '../layer';
|
|||||||
import appStateManager from '../lib/appManagers/appStateManager';
|
import appStateManager from '../lib/appManagers/appStateManager';
|
||||||
import passwordManager from '../lib/mtproto/passwordManager';
|
import passwordManager from '../lib/mtproto/passwordManager';
|
||||||
import Page from './page';
|
import Page from './page';
|
||||||
import pageIm from './pageIm';
|
|
||||||
import Button from '../components/button';
|
import Button from '../components/button';
|
||||||
import PasswordInputField from '../components/passwordInputField';
|
import PasswordInputField from '../components/passwordInputField';
|
||||||
import PasswordMonkey from '../components/monkeys/password';
|
import PasswordMonkey from '../components/monkeys/password';
|
||||||
@ -91,7 +90,9 @@ let onFirstMount = (): Promise<any> => {
|
|||||||
switch(response._) {
|
switch(response._) {
|
||||||
case 'auth.authorization':
|
case 'auth.authorization':
|
||||||
clearInterval(getStateInterval);
|
clearInterval(getStateInterval);
|
||||||
pageIm.mount();
|
import('./pageIm').then(m => {
|
||||||
|
m.default.mount();
|
||||||
|
});
|
||||||
if(monkey) monkey.remove();
|
if(monkey) monkey.remove();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -18,7 +18,6 @@ import apiManager from '../lib/mtproto/mtprotoworker';
|
|||||||
import RichTextProcessor from '../lib/richtextprocessor';
|
import RichTextProcessor from '../lib/richtextprocessor';
|
||||||
import LoginPage from './loginPage';
|
import LoginPage from './loginPage';
|
||||||
import Page from './page';
|
import Page from './page';
|
||||||
import pageIm from './pageIm';
|
|
||||||
import blurActiveElement from '../helpers/dom/blurActiveElement';
|
import blurActiveElement from '../helpers/dom/blurActiveElement';
|
||||||
import replaceContent from '../helpers/dom/replaceContent';
|
import replaceContent from '../helpers/dom/replaceContent';
|
||||||
|
|
||||||
@ -135,7 +134,9 @@ const onFirstMount = () => import('../lib/appManagers/appProfileManager').then(i
|
|||||||
apiManager.setUserAuth(response.user.id);
|
apiManager.setUserAuth(response.user.id);
|
||||||
|
|
||||||
sendAvatar().finally(() => {
|
sendAvatar().finally(() => {
|
||||||
pageIm.mount();
|
import('./pageIm').then(m => {
|
||||||
|
m.default.mount();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user