Browse Source

Refactor & refactor

master
Eduard Kuzmenko 4 years ago
parent
commit
5e159f5519
  1. 6
      src/components/chat/bubbles.ts
  2. 4
      src/components/chat/chat.ts
  3. 2
      src/components/chat/contextMenu.ts
  4. 2
      src/components/chat/input.ts
  5. 2
      src/components/chat/topbar.ts
  6. 6
      src/components/dialogsContextMenu.ts
  7. 4
      src/components/lazyLoadQueue.ts
  8. 4
      src/components/scrollable.ts
  9. 2
      src/components/sidebarLeft/index.ts
  10. 10
      src/layer.d.ts
  11. 4
      src/lib/appManagers/apiUpdatesManager.ts
  12. 34
      src/lib/appManagers/appChatsManager.ts
  13. 14
      src/lib/appManagers/appDialogsManager.ts
  14. 2
      src/lib/appManagers/appDraftsManager.ts
  15. 4
      src/lib/appManagers/appImManager.ts
  16. 548
      src/lib/appManagers/appMessagesManager.ts
  17. 8
      src/lib/appManagers/appNotificationsManager.ts
  18. 4
      src/lib/appManagers/appPollsManager.ts
  19. 59
      src/lib/appManagers/appStateManager.ts
  20. 2
      src/lib/appManagers/appStickersManager.ts
  21. 42
      src/lib/appManagers/appUsersManager.ts
  22. 4
      src/lib/crypto/srp.ts
  23. 75
      src/lib/idb.ts
  24. 35
      src/lib/logger.ts
  25. 4
      src/lib/lottieLoader.ts
  26. 4
      src/lib/mtproto/apiFileManager.ts
  27. 4
      src/lib/mtproto/apiManager.ts
  28. 4
      src/lib/mtproto/authorizer.ts
  29. 4
      src/lib/mtproto/mtproto.service.ts
  30. 4
      src/lib/mtproto/networker.ts
  31. 8
      src/lib/mtproto/transports/tcpObfuscated.ts
  32. 8
      src/lib/mtproto/transports/websocket.ts
  33. 4
      src/lib/opusDecodeController.ts
  34. 21
      src/lib/storage.ts
  35. 476
      src/lib/storages/dialogs.ts
  36. 10
      src/scripts/in/schema_additional_params.json

6
src/components/chat/bubbles.ts

@ -395,6 +395,10 @@ export default class ChatBubbles { @@ -395,6 +395,10 @@ export default class ChatBubbles {
}
this.listenerSetter.add(this.bubblesContainer, 'dblclick', (e) => {
if(this.chat.selection.isSelecting || !this.appMessagesManager.canWriteToPeer(this.peerId)) {
return;
}
const bubble = (e.target as HTMLElement).classList.contains('bubble') ? e.target as HTMLElement : null;
if(bubble) {
const mid = +bubble.dataset.mid
@ -1633,7 +1637,7 @@ export default class ChatBubbles { @@ -1633,7 +1637,7 @@ export default class ChatBubbles {
}
if(this.chat.type === 'chat') {
const dialog = this.appMessagesManager.getDialogByPeerId(peerId)[0];
const dialog = this.appMessagesManager.getDialogOnly(peerId);
if(dialog?.pFlags.unread_mark) {
this.appMessagesManager.markDialogUnread(peerId, true);
}

4
src/components/chat/chat.ts

@ -22,7 +22,7 @@ import type { AppDraftsManager } from "../../lib/appManagers/appDraftsManager"; @@ -22,7 +22,7 @@ import type { AppDraftsManager } from "../../lib/appManagers/appDraftsManager";
import type { ServerTimeManager } from "../../lib/mtproto/serverTimeManager";
import type sessionStorage from '../../lib/sessionStorage';
import EventListenerBase from "../../helpers/eventListenerBase";
import { logger, LogLevels } from "../../lib/logger";
import { logger, LogTypes } from "../../lib/logger";
import rootScope from "../../lib/rootScope";
import appSidebarRight from "../sidebarRight";
import ChatBubbles from "./bubbles";
@ -75,7 +75,7 @@ export default class Chat extends EventListenerBase<{ @@ -75,7 +75,7 @@ export default class Chat extends EventListenerBase<{
// * constructor end
this.log = logger('CHAT', LogLevels.log | LogLevels.warn | LogLevels.debug | LogLevels.error);
this.log = logger('CHAT', LogTypes.Log | LogTypes.Warn | LogTypes.Debug | LogTypes.Error);
//this.log.error('Chat construction');
this.container.append(this.backgroundEl);

2
src/components/chat/contextMenu.ts

@ -186,7 +186,7 @@ export default class ChatContextMenu { @@ -186,7 +186,7 @@ export default class ChatContextMenu {
icon: 'reply',
text: 'Reply',
onClick: this.onReplyClick,
verify: () => (this.peerId > 0 || this.appChatsManager.hasRights(-this.peerId, 'send_messages')) &&
verify: () => this.appMessagesManager.canWriteToPeer(this.peerId) &&
!this.message.pFlags.is_outgoing &&
!!this.chat.input.messageInput &&
this.chat.type !== 'scheduled'/* ,

2
src/components/chat/input.ts

@ -578,7 +578,7 @@ export default class ChatInput { @@ -578,7 +578,7 @@ export default class ChatInput {
};
public setUnreadCount() {
const dialog = this.appMessagesManager.getDialogByPeerId(this.chat.peerId)[0];
const dialog = this.appMessagesManager.getDialogOnly(this.chat.peerId);
const count = dialog?.unread_count;
this.goDownUnreadBadge.innerText = '' + (count || '');
this.goDownUnreadBadge.classList.toggle('badge-gray', this.appNotificationsManager.isPeerLocalMuted(this.chat.peerId, true));

2
src/components/chat/topbar.ts

@ -229,7 +229,7 @@ export default class ChatTopbar { @@ -229,7 +229,7 @@ export default class ChatTopbar {
onClick: () => {
new PopupDeleteDialog(this.peerId);
},
verify: () => this.chat.type === 'chat' && !!this.appMessagesManager.getDialogByPeerId(this.peerId)[0]
verify: () => this.chat.type === 'chat' && !!this.appMessagesManager.getDialogOnly(this.peerId)
}];
this.btnSearch = ButtonIcon('search');

6
src/components/dialogsContextMenu.ts

@ -94,7 +94,7 @@ export default class DialogsContextMenu { @@ -94,7 +94,7 @@ export default class DialogsContextMenu {
}
private onArchiveClick = () => {
let dialog = appMessagesManager.getDialogByPeerId(this.selectedId)[0];
let dialog = appMessagesManager.getDialogOnly(this.selectedId);
if(dialog) {
appMessagesManager.editPeerFolders([dialog.peerId], +!dialog.folder_id);
}
@ -113,7 +113,7 @@ export default class DialogsContextMenu { @@ -113,7 +113,7 @@ export default class DialogsContextMenu {
};
private onUnreadClick = () => {
const dialog = appMessagesManager.getDialogByPeerId(this.selectedId)[0];
const dialog = appMessagesManager.getDialogOnly(this.selectedId);
if(!dialog) return;
if(dialog.unread_count) {
@ -151,7 +151,7 @@ export default class DialogsContextMenu { @@ -151,7 +151,7 @@ export default class DialogsContextMenu {
this.filterId = appDialogsManager.filterId;
this.selectedId = +li.dataset.peerId;
this.dialog = appMessagesManager.getDialogByPeerId(this.selectedId)[0];
this.dialog = appMessagesManager.getDialogOnly(this.selectedId);
this.buttons.forEach(button => {
const good = button.verify();

4
src/components/lazyLoadQueue.ts

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
*/
import { throttle } from "../helpers/schedulers";
import { logger, LogLevels } from "../lib/logger";
import { logger, LogTypes } from "../lib/logger";
import VisibilityIntersector, { OnVisibilityChange } from "./visibilityIntersector";
import { findAndSpliceAll } from "../helpers/array";
@ -29,7 +29,7 @@ export class LazyLoadQueueBase { @@ -29,7 +29,7 @@ export class LazyLoadQueueBase {
protected lockPromise: Promise<void> = null;
protected unlockResolve: () => void = null;
protected log = logger('LL', LogLevels.error);
protected log = logger('LL', LogTypes.Error);
protected processQueue: () => void;
constructor(protected parallelLimit = PARALLEL_LIMIT) {

4
src/components/scrollable.ts

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
*/
import { isTouchSupported } from "../helpers/touchSupport";
import { logger, LogLevels } from "../lib/logger";
import { logger, LogTypes } from "../lib/logger";
import fastSmoothScroll, { FocusDirection } from "../helpers/fastSmoothScroll";
import useHeavyAnimationCheck from "../hooks/useHeavyAnimationCheck";
import { cancelEvent } from "../helpers/dom";
@ -64,7 +64,7 @@ export class ScrollableBase { @@ -64,7 +64,7 @@ export class ScrollableBase {
constructor(public el: HTMLElement, logPrefix = '', public container: HTMLElement = document.createElement('div')) {
this.container.classList.add('scrollable');
this.log = logger('SCROLL' + (logPrefix ? '-' + logPrefix : ''), LogLevels.error);
this.log = logger('SCROLL' + (logPrefix ? '-' + logPrefix : ''), LogTypes.Error);
if(el) {
Array.from(el.children).forEach(c => this.container.append(c));

2
src/components/sidebarLeft/index.ts

@ -466,7 +466,7 @@ export class AppSidebarLeft extends SidebarSlider { @@ -466,7 +466,7 @@ export class AppSidebarLeft extends SidebarSlider {
appStateManager.pushToState('recentSearch', recentSearch);
for(const peerId of recentSearch) {
appStateManager.setPeer(peerId, appPeersManager.getPeer(peerId));
appStateManager.requestPeer(peerId, 'recentSearch');
}
}
});

10
src/layer.d.ts vendored

@ -508,12 +508,7 @@ export namespace User { @@ -508,12 +508,7 @@ export namespace User {
bot_inline_placeholder?: string,
lang_code?: string,
initials?: string,
rFirstName?: string,
rFullName?: string,
rPhone?: string,
sortName?: string,
sortStatus?: number,
num?: number
sortName?: string
};
}
@ -1225,7 +1220,8 @@ export namespace Dialog { @@ -1225,7 +1220,8 @@ export namespace Dialog {
draft?: DraftMessage,
folder_id?: number,
index?: number,
peerId?: number
peerId?: number,
topMessage?: any
};
export type dialogFolder = {

4
src/lib/appManagers/apiUpdatesManager.ts

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
import DEBUG, { MOUNT_CLASS_TO } from '../../config/debug';
import { copy } from '../../helpers/object';
import { Update } from '../../layer';
import { logger, LogLevels } from '../logger';
import { logger, LogTypes } from '../logger';
import apiManager from '../mtproto/mtprotoworker';
import rootScope from '../rootScope';
//import networkerFactory from '../mtproto/networkerFactory';
@ -51,7 +51,7 @@ export class ApiUpdatesManager { @@ -51,7 +51,7 @@ export class ApiUpdatesManager {
public channelStates: {[channelId: number]: UpdatesState} = {};
private attached = false;
private log = logger('UPDATES', LogLevels.error | LogLevels.log | LogLevels.warn | LogLevels.debug);
private log = logger('UPDATES', LogTypes.Error | LogTypes.Warn/* | LogTypes.Log | LogTypes.Debug */);
private debug = DEBUG;
private popPendingSeqUpdate() {

34
src/lib/appManagers/appChatsManager.ts

@ -18,7 +18,7 @@ import apiManagerProxy from "../mtproto/mtprotoworker"; @@ -18,7 +18,7 @@ import apiManagerProxy from "../mtproto/mtprotoworker";
import apiManager from '../mtproto/mtprotoworker';
import { RichTextProcessor } from "../richtextprocessor";
import rootScope from "../rootScope";
//import AppStorage from "../storage";
import AppStorage from "../storage";
import apiUpdatesManager from "./apiUpdatesManager";
import appMessagesManager from "./appMessagesManager";
import appPeersManager from "./appPeersManager";
@ -33,9 +33,9 @@ export type ChatRights = keyof ChatBannedRights['pFlags'] | keyof ChatAdminRight @@ -33,9 +33,9 @@ export type ChatRights = keyof ChatBannedRights['pFlags'] | keyof ChatAdminRight
export type UserTyping = Partial<{userId: number, action: SendMessageAction, timeout: number}>;
export class AppChatsManager {
/* private storage = new AppStorage<Record<number, Chat>>({
private storage = new AppStorage<Record<number, Chat>>({
storeName: 'chats'
}); */
});
private chats: {[id: number]: Chat.channel | Chat.chat | any} = {};
//private usernames: any = {};
@ -76,6 +76,24 @@ export class AppChatsManager { @@ -76,6 +76,24 @@ export class AppChatsManager {
appStateManager.getState().then((state) => {
this.chats = state.chats;
appStateManager.addEventListener('peerNeeded', (peerId: number) => {
if(peerId > 0 || this.storage.getFromCache(-peerId)) {
return;
}
this.storage.set({
[-peerId]: this.getChat(-peerId)
});
});
appStateManager.addEventListener('peerUnneeded', (peerId: number) => {
if(peerId > 0 || !this.storage.getFromCache(-peerId)) {
return;
}
this.storage.delete(-peerId);
});
});
}
@ -179,8 +197,6 @@ export class AppChatsManager { @@ -179,8 +197,6 @@ export class AppChatsManager {
chat.initials = RichTextProcessor.getAbbreviation(chat.title);
//console.log('im the weatherman', chat.id);
if(chat._ === 'channel' &&
chat.participants_count === undefined &&
oldChat !== undefined &&
@ -219,9 +235,11 @@ export class AppChatsManager { @@ -219,9 +235,11 @@ export class AppChatsManager {
rootScope.broadcast('peer_title_edit', -chat.id);
}
/* this.storage.set({
[chat.id]: chat
}); */
if(appStateManager.isPeerNeeded(-chat.id)) {
this.storage.set({
[chat.id]: chat
});
}
}
public getChat(id: number) {

14
src/lib/appManagers/appDialogsManager.ts

@ -13,7 +13,7 @@ import { ripple } from "../../components/ripple"; @@ -13,7 +13,7 @@ import { ripple } from "../../components/ripple";
import Scrollable, { ScrollableX, SliceSides } from "../../components/scrollable";
import { formatDateAccordingToTodayNew } from "../../helpers/date";
import { isSafari } from "../../helpers/userAgent";
import { logger, LogLevels } from "../logger";
import { logger, LogTypes } from "../logger";
import { RichTextProcessor } from "../richtextprocessor";
import rootScope from "../rootScope";
import { positionElementByIndex, replaceContent } from "../../helpers/dom";
@ -194,7 +194,7 @@ export class AppDialogsManager { @@ -194,7 +194,7 @@ export class AppDialogsManager {
public scroll: Scrollable = null;
public _scroll: Scrollable = null;
private log = logger('DIALOGS', LogLevels.log | LogLevels.error | LogLevels.warn | LogLevels.debug);
private log = logger('DIALOGS', LogTypes.Log | LogTypes.Error | LogTypes.Warn | LogTypes.Debug);
public contextMenu = new DialogsContextMenu();
@ -321,7 +321,7 @@ export class AppDialogsManager { @@ -321,7 +321,7 @@ export class AppDialogsManager {
rootScope.on('dialog_flush', (e) => {
const peerId: number = e.peerId;
const dialog = appMessagesManager.getDialogByPeerId(peerId)[0];
const dialog = appMessagesManager.getDialogOnly(peerId);
if(dialog) {
this.setLastMessage(dialog);
this.validateForFilter();
@ -356,7 +356,7 @@ export class AppDialogsManager { @@ -356,7 +356,7 @@ export class AppDialogsManager {
rootScope.on('dialog_unread', (e) => {
const info = e;
const dialog = appMessagesManager.getDialogByPeerId(info.peerId)[0];
const dialog = appMessagesManager.getDialogOnly(info.peerId);
if(dialog) {
this.setUnreadMessages(dialog);
this.validateForFilter();
@ -369,7 +369,7 @@ export class AppDialogsManager { @@ -369,7 +369,7 @@ export class AppDialogsManager {
});
rootScope.on('dialog_draft', (e) => {
const dialog = appMessagesManager.getDialogByPeerId(e.peerId)[0];
const dialog = appMessagesManager.getDialogOnly(e.peerId);
if(dialog) {
this.updateDialog(dialog);
}
@ -455,7 +455,7 @@ export class AppDialogsManager { @@ -455,7 +455,7 @@ export class AppDialogsManager {
rootScope.on('peer_typings', (e) => {
const {peerId, typings} = e;
const dialog = appMessagesManager.getDialogByPeerId(peerId)[0];
const dialog = appMessagesManager.getDialogOnly(peerId);
if(!dialog) return;
if(typings.length) {
@ -1209,7 +1209,7 @@ export class AppDialogsManager { @@ -1209,7 +1209,7 @@ export class AppDialogsManager {
let dialog: Dialog;
if(typeof(_dialog) === 'number') {
let originalDialog = appMessagesManager.getDialogByPeerId(_dialog)[0];
let originalDialog = appMessagesManager.getDialogOnly(_dialog);
if(!originalDialog) {
originalDialog = {
peerId: _dialog,

2
src/lib/appManagers/appDraftsManager.ts

@ -62,7 +62,7 @@ export class AppDraftsManager { @@ -62,7 +62,7 @@ export class AppDraftsManager {
}
const peerId = +key;
const dialog = appMessagesManager.getDialogByPeerId(peerId)[0];
const dialog = appMessagesManager.getDialogOnly(peerId);
if(!dialog) {
appMessagesManager.reloadConversation(peerId);
/* const dialog = appMessagesManager.generateDialog(peerId);

4
src/lib/appManagers/appImManager.ts

@ -9,7 +9,7 @@ import animationIntersector from '../../components/animationIntersector'; @@ -9,7 +9,7 @@ import animationIntersector from '../../components/animationIntersector';
import appSidebarLeft, { LEFT_COLUMN_ACTIVE_CLASSNAME } from "../../components/sidebarLeft";
import appSidebarRight, { RIGHT_COLUMN_ACTIVE_CLASSNAME } from '../../components/sidebarRight';
import mediaSizes, { ScreenSize } from '../../helpers/mediaSizes';
import { logger, LogLevels } from "../logger";
import { logger, LogTypes } from "../logger";
import apiManager from '../mtproto/mtprotoworker';
import rootScope from '../rootScope';
import apiUpdatesManager from './apiUpdatesManager';
@ -95,7 +95,7 @@ export class AppImManager { @@ -95,7 +95,7 @@ export class AppImManager {
constructor() {
apiUpdatesManager.attach();
this.log = logger('IM', LogLevels.log | LogLevels.warn | LogLevels.debug | LogLevels.error);
this.log = logger('IM', LogTypes.Log | LogTypes.Warn | LogTypes.Debug | LogTypes.Error);
this.selectTab(0);

548
src/lib/appManagers/appMessagesManager.ts

@ -20,7 +20,7 @@ import { splitStringByLength, limitSymbols, escapeRegExp } from "../../helpers/s @@ -20,7 +20,7 @@ import { splitStringByLength, limitSymbols, escapeRegExp } from "../../helpers/s
import { Chat, ChatFull, Dialog as MTDialog, DialogPeer, DocumentAttribute, InputMedia, InputMessage, InputPeerNotifySettings, InputSingleMedia, Message, MessageAction, MessageEntity, MessageFwdHeader, MessageMedia, MessageReplies, MessageReplyHeader, MessagesDialogs, MessagesFilter, MessagesMessages, MessagesPeerDialogs, MethodDeclMap, NotifyPeer, PeerNotifySettings, PhotoSize, SendMessageAction, Update, Photo } from "../../layer";
import { InvokeApiOptions } from "../../types";
import I18n, { i18n, join, langPack, LangPackKey, _i18n } from "../langPack";
import { logger, LogLevels } from "../logger";
import { logger, LogTypes } from "../logger";
import type { ApiFileManager } from '../mtproto/apiFileManager';
//import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
@ -28,7 +28,6 @@ import referenceDatabase, { ReferenceContext } from "../mtproto/referenceDatabas @@ -28,7 +28,6 @@ import referenceDatabase, { ReferenceContext } from "../mtproto/referenceDatabas
import serverTimeManager from "../mtproto/serverTimeManager";
import { RichTextProcessor } from "../richtextprocessor";
import rootScope from "../rootScope";
import searchIndexManager from '../searchIndexManager';
import DialogsStorage from "../storages/dialogs";
import FiltersStorage from "../storages/filters";
//import { telegramMeWebService } from "../mtproto/mtproto";
@ -172,8 +171,8 @@ export class AppMessagesManager { @@ -172,8 +171,8 @@ export class AppMessagesManager {
public newMessagesHandlePromise = 0;
public newMessagesToHandle: {[peerId: string]: Set<number>} = {};
public newDialogsHandlePromise = 0;
public newDialogsToHandle: {[peerId: string]: {reload: true} | Dialog} = {};
public newDialogsHandlePromise: Promise<any>;
public newDialogsToHandle: {[peerId: string]: Dialog} = {};
public newUpdatesAfterReloadToHandle: {[peerId: string]: Set<Update>} = {};
private notificationsHandlePromise = 0;
@ -186,19 +185,7 @@ export class AppMessagesManager { @@ -186,19 +185,7 @@ export class AppMessagesManager {
private reloadConversationsPromise: Promise<void>;
private reloadConversationsPeers: number[] = [];
private cachedResults: {
query: string,
count: number,
dialogs: Dialog[],
folderId: number
} = {
query: '',
count: 0,
dialogs: [],
folderId: 0
};
private log = logger('MESSAGES', LogLevels.error | LogLevels.debug | LogLevels.log | LogLevels.warn);
public log = logger('MESSAGES', LogTypes.Error | LogTypes.Debug | LogTypes.Log | LogTypes.Warn);
public dialogsStorage: DialogsStorage;
public filtersStorage: FiltersStorage;
@ -206,7 +193,7 @@ export class AppMessagesManager { @@ -206,7 +193,7 @@ export class AppMessagesManager {
private groupedTempId = 0;
constructor() {
this.dialogsStorage = new DialogsStorage(this, appChatsManager, appPeersManager, serverTimeManager);
this.dialogsStorage = new DialogsStorage(this, appChatsManager, appPeersManager, appUsersManager, appDraftsManager, appNotificationsManager, appStateManager, apiUpdatesManager, serverTimeManager);
this.filtersStorage = new FiltersStorage(this, appPeersManager, appUsersManager, appNotificationsManager, apiUpdatesManager, /* apiManager, */ rootScope);
rootScope.addMultipleEventsListeners({
@ -218,12 +205,6 @@ export class AppMessagesManager { @@ -218,12 +205,6 @@ export class AppMessagesManager {
updateDialogUnreadMark: this.onUpdateDialogUnreadMark,
updateFolderPeers: this.onUpdateFolderPeers,
updateDialogPinned: this.onUpdateDialogPinned,
updatePinnedDialogs: this.onUpdatePinnedDialogs,
updateEditMessage: this.onUpdateEditMessage,
updateEditChannelMessage: this.onUpdateEditMessage,
@ -277,15 +258,6 @@ export class AppMessagesManager { @@ -277,15 +258,6 @@ export class AppMessagesManager {
});
});
rootScope.on('language_change', (e) => {
const peerId = appUsersManager.getSelf().id;
const dialog = this.getDialogByPeerId(peerId)[0];
if(dialog) {
const peerText = appPeersManager.getPeerSearchText(peerId);
searchIndexManager.indexObject(peerId, peerText, this.dialogsStorage.dialogsIndex);
}
});
rootScope.on('webpage_updated', (e) => {
const eventData = e;
eventData.msgs.forEach((mid) => {
@ -311,7 +283,7 @@ export class AppMessagesManager { @@ -311,7 +283,7 @@ export class AppMessagesManager {
if(threadId) return;
const dialog = this.getDialogByPeerId(peerId)[0];
const dialog = this.getDialogOnly(peerId);
if(dialog && !threadId) {
dialog.draft = draft;
this.dialogsStorage.generateIndexForDialog(dialog);
@ -368,7 +340,7 @@ export class AppMessagesManager { @@ -368,7 +340,7 @@ export class AppMessagesManager {
forEachReverse(state.dialogs, dialog => {
dialog.top_message = this.getServerMessageId(dialog.top_message); // * fix outgoing message to avoid copying dialog
this.saveConversation(dialog);
this.dialogsStorage.saveDialog(dialog);
// ! WARNING, убрать это когда нужно будет делать чтобы pending сообщения сохранялись
const message = this.getMessageByPeer(dialog.peerId, dialog.top_message);
@ -392,37 +364,27 @@ export class AppMessagesManager { @@ -392,37 +364,27 @@ export class AppMessagesManager {
const processDialog = (dialog: MTDialog.dialog) => {
const historyStorage = this.getHistoryStorage(dialog.peerId);
const history = [].concat(historyStorage.history.slice);
//dialog = copy(dialog);
let removeUnread = 0;
for(const mid of history) {
const message = this.getMessageByPeer(dialog.peerId, mid);
if(/* message._ !== 'messageEmpty' && */!message.pFlags.is_outgoing) {
if(!message.pFlags.is_outgoing) {
messages.push(message);
if(message.fromId !== dialog.peerId) {
appStateManager.setPeer(message.fromId, appPeersManager.getPeer(message.fromId));
appStateManager.requestPeer(message.fromId, 'topMessage_' + dialog.peerId, 1);
}
/* dialog.top_message = message.mid;
this.dialogsStorage.generateIndexForDialog(dialog, false, message); */
break;
} else if(message.pFlags && message.pFlags.unread) {
++removeUnread;
}
}
if(removeUnread && dialog.unread_count) dialog.unread_count -= removeUnread;
if(dialog.peerId < 0 && dialog.pts) {
const newPts = apiUpdatesManager.channelStates[-dialog.peerId].pts;
dialog.pts = newPts;
}
dialog.unread_count = Math.max(0, dialog.unread_count);
dialogs.push(dialog);
appStateManager.setPeer(dialog.peerId, appPeersManager.getPeer(dialog.peerId));
appStateManager.requestPeer(dialog.peerId, 'dialog');
};
for(const folderId in this.dialogsStorage.byFolders) {
@ -1627,7 +1589,7 @@ export class AppMessagesManager { @@ -1627,7 +1589,7 @@ export class AppMessagesManager {
return message;
}
public setDialogTopMessage(message: MyMessage, dialog: MTDialog.dialog = this.getDialogByPeerId(message.peerId)[0]) {
public setDialogTopMessage(message: MyMessage, dialog: MTDialog.dialog = this.getDialogOnly(message.peerId)) {
if(dialog) {
dialog.top_message = message.mid;
@ -1636,8 +1598,7 @@ export class AppMessagesManager { @@ -1636,8 +1598,7 @@ export class AppMessagesManager {
this.dialogsStorage.generateIndexForDialog(dialog, false, message);
this.newDialogsToHandle[message.peerId] = dialog;
this.scheduleHandleNewDialogs();
this.scheduleHandleNewDialogs(message.peerId, dialog);
}
}
@ -1729,72 +1690,7 @@ export class AppMessagesManager { @@ -1729,72 +1690,7 @@ export class AppMessagesManager {
}
public getConversations(query = '', offsetIndex?: number, limit = 20, folderId = 0) {
const realFolderId = folderId > 1 ? 0 : folderId;
let curDialogStorage = this.dialogsStorage.getFolder(folderId);
if(query) {
if(!limit || this.cachedResults.query !== query || this.cachedResults.folderId !== folderId) {
this.cachedResults.query = query;
this.cachedResults.folderId = folderId;
const results = searchIndexManager.search(query, this.dialogsStorage.dialogsIndex);
this.cachedResults.dialogs = [];
for(const peerId in this.dialogsStorage.dialogs) {
const dialog = this.dialogsStorage.dialogs[peerId];
if(results[dialog.peerId] && dialog.folder_id === folderId) {
this.cachedResults.dialogs.push(dialog);
}
}
this.cachedResults.dialogs.sort((d1, d2) => d2.index - d1.index);
this.cachedResults.count = this.cachedResults.dialogs.length;
}
curDialogStorage = this.cachedResults.dialogs;
} else {
this.cachedResults.query = '';
}
let offset = 0;
if(offsetIndex > 0) {
for(; offset < curDialogStorage.length; offset++) {
if(offsetIndex > curDialogStorage[offset].index) {
break;
}
}
}
if(query || this.dialogsStorage.allDialogsLoaded[realFolderId] || curDialogStorage.length >= offset + limit) {
return Promise.resolve({
dialogs: curDialogStorage.slice(offset, offset + limit),
count: this.dialogsStorage.allDialogsLoaded[realFolderId] ? curDialogStorage.length : null,
isEnd: this.dialogsStorage.allDialogsLoaded[realFolderId] && (offset + limit) >= curDialogStorage.length
});
}
return this.getTopMessages(limit, realFolderId).then(messagesDialogs => {
//const curDialogStorage = this.dialogsStorage[folderId];
offset = 0;
if(offsetIndex > 0) {
for(; offset < curDialogStorage.length; offset++) {
if(offsetIndex > curDialogStorage[offset].index) {
break;
}
}
}
//this.log.warn(offset, offset + limit, curDialogStorage.dialogs.length, this.dialogsStorage.dialogs.length);
return {
dialogs: curDialogStorage.slice(offset, offset + limit),
count: messagesDialogs._ === 'messages.dialogs' ? messagesDialogs.dialogs.length : messagesDialogs.count,
isEnd: this.dialogsStorage.allDialogsLoaded[realFolderId] && (offset + limit) >= curDialogStorage.length
};
});
return this.dialogsStorage.getDialogs(query, offsetIndex, limit, folderId);
}
public getReadMaxIdIfUnread(peerId: number, threadId?: number) {
@ -1860,7 +1756,7 @@ export class AppMessagesManager { @@ -1860,7 +1756,7 @@ export class AppMessagesManager {
forEachReverse((dialogsResult.dialogs as Dialog[]), dialog => {
//const d = Object.assign({}, dialog);
// ! нужно передавать folderId, так как по папке !== 0 нет свойства folder_id
this.saveConversation(dialog, dialog.folder_id ?? folderId);
this.dialogsStorage.saveDialog(dialog, dialog.folder_id ?? folderId);
if(dialog.peerId === undefined) {
return;
@ -1871,7 +1767,7 @@ export class AppMessagesManager { @@ -1871,7 +1767,7 @@ export class AppMessagesManager {
} */
if(offsetIndex && dialog.index > offsetIndex) {
this.newDialogsToHandle[dialog.peerId] = dialog;
this.scheduleHandleNewDialogs(dialog.peerId, dialog);
hasPrepend = true;
}
@ -2074,6 +1970,10 @@ export class AppMessagesManager { @@ -2074,6 +1970,10 @@ export class AppMessagesManager {
return this.dialogsStorage.getDialog(peerId);
}
public getDialogOnly(peerId: number) {
return this.dialogsStorage.getDialogOnly(peerId);
}
public reloadConversation(peerId: number | number[]) {
[].concat(peerId).forEach(peerId => {
if(!this.reloadConversationsPeers.includes(peerId)) {
@ -2089,7 +1989,7 @@ export class AppMessagesManager { @@ -2089,7 +1989,7 @@ export class AppMessagesManager {
this.reloadConversationsPeers.length = 0;
apiManager.invokeApi('messages.getPeerDialogs', {peers}).then((result) => {
this.applyConversations(result);
this.dialogsStorage.applyDialogs(result);
resolve();
}, reject).finally(() => {
this.reloadConversationsPromise = null;
@ -2288,7 +2188,7 @@ export class AppMessagesManager { @@ -2288,7 +2188,7 @@ export class AppMessagesManager {
}
public generateTempMessageId(peerId: number) {
const dialog = this.getDialogByPeerId(peerId)[0];
const dialog = this.getDialogOnly(peerId);
return this.generateMessageId(dialog?.top_message || 0, true);
}
@ -2369,7 +2269,7 @@ export class AppMessagesManager { @@ -2369,7 +2269,7 @@ export class AppMessagesManager {
storage[mid] = message;
}
const dialog = this.getDialogByPeerId(peerId)[0];
const dialog = this.getDialogOnly(peerId);
if(dialog && mid) {
if(mid > dialog[message.pFlags.out
? 'read_outbox_max_id'
@ -2941,11 +2841,10 @@ export class AppMessagesManager { @@ -2941,11 +2841,10 @@ export class AppMessagesManager {
public toggleDialogPin(peerId: number, filterId?: number) {
if(filterId > 1) {
this.filtersStorage.toggleDialogPin(peerId, filterId);
return;
return this.filtersStorage.toggleDialogPin(peerId, filterId);
}
const dialog = this.getDialogByPeerId(peerId)[0];
const dialog = this.getDialogOnly(peerId);
if(!dialog) return Promise.reject();
const pinned = dialog.pFlags?.pinned ? undefined : true;
@ -2955,7 +2854,7 @@ export class AppMessagesManager { @@ -2955,7 +2854,7 @@ export class AppMessagesManager {
}).then(bool => {
if(bool) {
const pFlags: Update.updateDialogPinned['pFlags'] = pinned ? {pinned} : {};
this.onUpdateDialogPinned({
apiUpdatesManager.saveUpdate({
_: 'updateDialogPinned',
peer: appPeersManager.getDialogPeer(peerId),
folder_id: filterId,
@ -2966,7 +2865,7 @@ export class AppMessagesManager { @@ -2966,7 +2865,7 @@ export class AppMessagesManager {
}
public markDialogUnread(peerId: number, read?: true) {
const dialog = this.getDialogByPeerId(peerId)[0];
const dialog = this.getDialogOnly(peerId);
if(!dialog) return Promise.reject();
const unread = read || dialog.pFlags?.unread_mark ? undefined : true;
@ -3067,191 +2966,6 @@ export class AppMessagesManager { @@ -3067,191 +2966,6 @@ export class AppMessagesManager {
) && !message.pFlags.is_outgoing;
}
public applyConversations(dialogsResult: MessagesPeerDialogs.messagesPeerDialogs) {
// * В эту функцию попадут только те диалоги, в которых есть read_inbox_max_id и read_outbox_max_id, в отличие от тех, что будут в getTopMessages
// ! fix 'dialogFolder', maybe there is better way to do it, this only can happen by 'messages.getPinnedDialogs' by folder_id: 0
forEachReverse(dialogsResult.dialogs, (dialog, idx) => {
if(dialog._ === 'dialogFolder') {
dialogsResult.dialogs.splice(idx, 1);
}
});
appUsersManager.saveApiUsers(dialogsResult.users);
appChatsManager.saveApiChats(dialogsResult.chats);
this.saveMessages(dialogsResult.messages);
this.log('applyConversation', dialogsResult);
const updatedDialogs: {[peerId: number]: Dialog} = {};
(dialogsResult.dialogs as Dialog[]).forEach((dialog) => {
const peerId = appPeersManager.getPeerId(dialog.peer);
let topMessage = dialog.top_message;
const topPendingMessage = this.pendingTopMsgs[peerId];
if(topPendingMessage) {
if(!topMessage
|| (this.getMessageByPeer(peerId, topPendingMessage) as MyMessage).date > (this.getMessageByPeer(peerId, topMessage) as MyMessage).date) {
dialog.top_message = topMessage = topPendingMessage;
this.getHistoryStorage(peerId).maxId = topPendingMessage;
}
}
/* const d = Object.assign({}, dialog);
if(peerId === 239602833) {
this.log.error('applyConversation lun', dialog, d);
} */
if(topMessage || (dialog.draft && dialog.draft._ === 'draftMessage')) {
this.saveConversation(dialog);
updatedDialogs[peerId] = dialog;
} else {
const dropped = this.dialogsStorage.dropDialog(peerId);
if(dropped.length) {
rootScope.broadcast('dialog_drop', {peerId, dialog: dropped[0]});
}
}
if(this.newUpdatesAfterReloadToHandle[peerId] !== undefined) {
for(const update of this.newUpdatesAfterReloadToHandle[peerId]) {
apiUpdatesManager.saveUpdate(update);
}
delete this.newUpdatesAfterReloadToHandle[peerId];
}
});
if(Object.keys(updatedDialogs).length) {
rootScope.broadcast('dialogs_multiupdate', updatedDialogs);
}
}
public generateDialog(peerId: number) {
const dialog: Dialog = {
_: 'dialog',
pFlags: {},
peer: appPeersManager.getOutputPeer(peerId),
top_message: 0,
read_inbox_max_id: 0,
read_outbox_max_id: 0,
unread_count: 0,
unread_mentions_count: 0,
notify_settings: {
_: 'peerNotifySettings',
},
};
return dialog;
}
/**
* Won't save migrated from peer, forbidden peers, left and kicked
*/
public saveConversation(dialog: Dialog, folderId = 0) {
const peerId = appPeersManager.getPeerId(dialog.peer);
if(!peerId) {
console.error('saveConversation no peerId???', dialog, folderId);
return false;
}
if(dialog._ !== 'dialog'/* || peerId === 239602833 */) {
console.error('saveConversation not regular dialog', dialog, Object.assign({}, dialog));
}
const channelId = appPeersManager.isChannel(peerId) ? -peerId : 0;
if(peerId < 0) {
const chat: Chat = appChatsManager.getChat(-peerId);
if(chat._ === 'channelForbidden' || chat._ === 'chatForbidden' || (chat as Chat.chat).pFlags.left || (chat as Chat.chat).pFlags.kicked) {
return false;
}
}
const peerText = appPeersManager.getPeerSearchText(peerId);
searchIndexManager.indexObject(peerId, peerText, this.dialogsStorage.dialogsIndex);
let mid: number, message;
if(dialog.top_message) {
mid = this.generateMessageId(dialog.top_message);//dialog.top_message;
message = this.getMessageByPeer(peerId, mid);
} else {
mid = this.generateTempMessageId(peerId);
message = {
_: 'message',
id: mid,
mid,
from_id: appPeersManager.getOutputPeer(appUsersManager.getSelf().id),
peer_id: appPeersManager.getOutputPeer(peerId),
deleted: true,
pFlags: {out: true},
date: 0,
message: ''
};
this.saveMessages([message], {isOutgoing: true});
}
if(!message?.pFlags) {
this.log.error('saveConversation no message:', dialog, message);
}
if(!channelId && peerId < 0) {
const chat = appChatsManager.getChat(-peerId);
if(chat && chat.migrated_to && chat.pFlags.deactivated) {
const migratedToPeer = appPeersManager.getPeerId(chat.migrated_to);
this.migratedFromTo[peerId] = migratedToPeer;
this.migratedToFrom[migratedToPeer] = peerId;
return;
}
}
const wasDialogBefore = this.getDialogByPeerId(peerId)[0];
dialog.top_message = mid;
dialog.read_inbox_max_id = this.generateMessageId(wasDialogBefore && !dialog.read_inbox_max_id ? wasDialogBefore.read_inbox_max_id : dialog.read_inbox_max_id);
dialog.read_outbox_max_id = this.generateMessageId(wasDialogBefore && !dialog.read_outbox_max_id ? wasDialogBefore.read_outbox_max_id : dialog.read_outbox_max_id);
if(!dialog.hasOwnProperty('folder_id')) {
if(dialog._ === 'dialog') {
// ! СЛОЖНО ! СМОТРИ В getTopMessages
dialog.folder_id = wasDialogBefore ? wasDialogBefore.folder_id : folderId;
}/* else if(dialog._ === 'dialogFolder') {
dialog.folder_id = dialog.folder.id;
} */
}
dialog.draft = appDraftsManager.saveDraft(peerId, 0, dialog.draft);
dialog.peerId = peerId;
// Because we saved message without dialog present
if(message.pFlags.is_outgoing) {
if(mid > dialog[message.pFlags.out ? 'read_outbox_max_id' : 'read_inbox_max_id']) message.pFlags.unread = true;
else delete message.pFlags.unread;
}
let historyStorage = this.getHistoryStorage(peerId);
/* if(historyStorage === undefined) { // warning
historyStorage.history.push(mid);
if(this.mergeReplyKeyboard(historyStorage, message)) {
rootScope.broadcast('history_reply_markup', {peerId});
}
} else */if(!historyStorage.history.slice.length) {
historyStorage.history.unshift(mid);
}
historyStorage.maxId = mid;
historyStorage.readMaxId = dialog.read_inbox_max_id;
historyStorage.readOutboxMaxId = dialog.read_outbox_max_id;
appNotificationsManager.savePeerSettings(peerId, dialog.notify_settings)
if(channelId && dialog.pts) {
apiUpdatesManager.addChannelState(channelId, dialog.pts);
}
this.dialogsStorage.generateIndexForDialog(dialog);
this.dialogsStorage.pushDialog(dialog, message.date);
}
public mergeReplyKeyboard(historyStorage: HistoryStorage, message: any) {
// this.log('merge', message.mid, message.reply_markup, historyStorage.reply_markup)
if(!message.reply_markup &&
@ -3689,15 +3403,13 @@ export class AppMessagesManager { @@ -3689,15 +3403,13 @@ export class AppMessagesManager {
};
handleNewDialogs = () => {
clearTimeout(this.newDialogsHandlePromise);
this.newDialogsHandlePromise = 0;
let newMaxSeenId = 0;
for(const peerId in this.newDialogsToHandle) {
const dialog = this.newDialogsToHandle[peerId];
if('reload' in dialog) {
const obj = this.newDialogsToHandle;
for(const peerId in obj) {
const dialog = obj[peerId];
if(!dialog) {
this.reloadConversation(+peerId);
delete this.newDialogsToHandle[peerId];
delete obj[peerId];
} else {
this.dialogsStorage.pushDialog(dialog);
if(!appPeersManager.isChannel(+peerId)) {
@ -3712,14 +3424,22 @@ export class AppMessagesManager { @@ -3712,14 +3424,22 @@ export class AppMessagesManager {
this.incrementMaxSeenId(newMaxSeenId);
}
rootScope.broadcast('dialogs_multiupdate', this.newDialogsToHandle as any);
rootScope.broadcast('dialogs_multiupdate', obj);
this.newDialogsToHandle = {};
};
public scheduleHandleNewDialogs() {
if(!this.newDialogsHandlePromise) {
this.newDialogsHandlePromise = window.setTimeout(this.handleNewDialogs, 0);
public scheduleHandleNewDialogs(peerId?: number, dialog?: Dialog) {
if(peerId !== undefined) {
this.newDialogsToHandle[peerId] = dialog;
}
if(this.newDialogsHandlePromise) return this.newDialogsHandlePromise;
return this.newDialogsHandlePromise = new Promise((resolve) => {
setTimeout(() => {
this.newDialogsHandlePromise = undefined;
this.handleNewDialogs();
}, 0);
});
}
public deleteMessages(peerId: number, mids: number[], revoke?: true) {
@ -4009,7 +3729,7 @@ export class AppMessagesManager { @@ -4009,7 +3729,7 @@ export class AppMessagesManager {
const message = update.message as MyMessage;
const peerId = this.getMessagePeer(message);
const storage = this.getMessagesStorage(peerId);
const foundDialog = this.getDialogByPeerId(peerId);
const dialog = this.getDialogOnly(peerId);
// * local update
const isLocalThreadUpdate = update._ === 'updateNewDiscussionMessage';
@ -4028,7 +3748,7 @@ export class AppMessagesManager { @@ -4028,7 +3748,7 @@ export class AppMessagesManager {
this.onUpdateNewMessage(update);
}
if(!foundDialog.length && !isLocalThreadUpdate) {
if(!dialog && !isLocalThreadUpdate) {
let good = true;
if(peerId < 0) {
const chat = appChatsManager.getChat(-peerId);
@ -4048,9 +3768,8 @@ export class AppMessagesManager { @@ -4048,9 +3768,8 @@ export class AppMessagesManager {
return;
}
this.newDialogsToHandle[peerId] = {reload: true};
this.scheduleHandleNewDialogs();
this.newUpdatesAfterReloadToHandle[peerId].add(update);
this.scheduleHandleNewDialogs(peerId);
set.add(update);
}
return;
@ -4118,7 +3837,6 @@ export class AppMessagesManager { @@ -4118,7 +3837,6 @@ export class AppMessagesManager {
return;
}
const dialog = foundDialog[0];
const inboxUnread = !message.pFlags.out && message.pFlags.unread;
if(dialog) {
this.setDialogTopMessage(message, dialog);
@ -4157,14 +3875,11 @@ export class AppMessagesManager { @@ -4157,14 +3875,11 @@ export class AppMessagesManager {
private onUpdateDialogUnreadMark = (update: Update.updateDialogUnreadMark) => {
//this.log('updateDialogUnreadMark', update);
const peerId = appPeersManager.getPeerId((update.peer as DialogPeer.dialogPeer).peer);
const foundDialog = this.getDialogByPeerId(peerId);
const dialog = this.getDialogOnly(peerId);
if(!foundDialog.length) {
this.newDialogsToHandle[peerId] = {reload: true};
this.scheduleHandleNewDialogs();
if(!dialog) {
this.scheduleHandleNewDialogs(peerId);
} else {
const dialog = foundDialog[0];
if(!update.pFlags.unread) {
delete dialog.pFlags.unread_mark;
} else {
@ -4175,142 +3890,6 @@ export class AppMessagesManager { @@ -4175,142 +3890,6 @@ export class AppMessagesManager {
}
};
// only 0 and 1 folders
private onUpdateFolderPeers = (update: Update.updateFolderPeers) => {
//this.log('updateFolderPeers', update);
const peers = update.folder_peers;
this.scheduleHandleNewDialogs();
peers.forEach((folderPeer) => {
const {folder_id, peer} = folderPeer;
const peerId = appPeersManager.getPeerId(peer);
const dropped = this.dialogsStorage.dropDialog(peerId);
if(!dropped.length) {
this.newDialogsToHandle[peerId] = {reload: true};
} else {
const dialog = dropped[0];
this.newDialogsToHandle[peerId] = dialog;
if(dialog.pFlags?.pinned) {
delete dialog.pFlags.pinned;
this.dialogsStorage.pinnedOrders[folder_id].findAndSplice(p => p === dialog.peerId);
}
dialog.folder_id = folder_id;
this.dialogsStorage.generateIndexForDialog(dialog);
this.dialogsStorage.pushDialog(dialog); // need for simultaneously updatePinnedDialogs
}
});
};
private onUpdateDialogPinned = (update: Update.updateDialogPinned) => {
const folderId = update.folder_id ?? 0;
//this.log('updateDialogPinned', update);
const peerId = appPeersManager.getPeerId((update.peer as DialogPeer.dialogPeer).peer);
const foundDialog = this.getDialogByPeerId(peerId);
// этот код внизу никогда не сработает, в папках за пиннед отвечает updateDialogFilter
/* if(update.folder_id > 1) {
const filter = this.filtersStorage.filters[update.folder_id];
if(update.pFlags.pinned) {
filter.pinned_peers.unshift(peerId);
} else {
filter.pinned_peers.findAndSplice(p => p === peerId);
}
} */
this.scheduleHandleNewDialogs();
if(!foundDialog.length) {
this.newDialogsToHandle[peerId] = {reload: true};
} else {
const dialog = foundDialog[0];
this.newDialogsToHandle[peerId] = dialog;
if(!update.pFlags.pinned) {
delete dialog.pFlags.pinned;
this.dialogsStorage.pinnedOrders[folderId].findAndSplice(p => p === dialog.peerId);
} else { // means set
dialog.pFlags.pinned = true;
}
this.dialogsStorage.generateIndexForDialog(dialog);
}
};
private onUpdatePinnedDialogs = (update: Update.updatePinnedDialogs) => {
const folderId = update.folder_id ?? 0;
const handleOrder = (order: number[]) => {
this.dialogsStorage.pinnedOrders[folderId].length = 0;
let willHandle = false;
order.reverse(); // index must be higher
order.forEach((peerId) => {
newPinned[peerId] = true;
const foundDialog = this.getDialogByPeerId(peerId);
if(!foundDialog.length) {
this.newDialogsToHandle[peerId] = {reload: true};
willHandle = true;
return;
}
const dialog = foundDialog[0];
dialog.pFlags.pinned = true;
this.dialogsStorage.generateIndexForDialog(dialog);
this.newDialogsToHandle[peerId] = dialog;
willHandle = true;
});
this.dialogsStorage.getFolder(folderId).forEach(dialog => {
const peerId = dialog.peerId;
if(dialog.pFlags.pinned && !newPinned[peerId]) {
this.newDialogsToHandle[peerId] = {reload: true};
willHandle = true;
}
});
if(willHandle) {
this.scheduleHandleNewDialogs();
}
};
//this.log('updatePinnedDialogs', update);
const newPinned: {[peerId: number]: true} = {};
if(!update.order) {
apiManager.invokeApi('messages.getPinnedDialogs', {
folder_id: folderId
}).then((dialogsResult) => {
// * for test reordering and rendering
// dialogsResult.dialogs.reverse();
this.applyConversations(dialogsResult);
handleOrder(dialogsResult.dialogs.map(d => d.peerId));
/* dialogsResult.dialogs.forEach((dialog) => {
newPinned[dialog.peerId] = true;
});
this.dialogsStorage.getFolder(folderId).forEach((dialog) => {
const peerId = dialog.peerId;
if(dialog.pFlags.pinned && !newPinned[peerId]) {
this.newDialogsToHandle[peerId] = {reload: true};
this.scheduleHandleNewDialogs();
}
}); */
});
return;
}
//this.log('before order:', this.dialogsStorage[0].map(d => d.peerId));
handleOrder(update.order.map(peer => appPeersManager.getPeerId((peer as DialogPeer.dialogPeer).peer)));
};
private onUpdateEditMessage = (update: Update.updateEditMessage | Update.updateEditChannelMessage) => {
const message = update.message as MyMessage;
const peerId = this.getMessagePeer(message);
@ -4328,7 +3907,7 @@ export class AppMessagesManager { @@ -4328,7 +3907,7 @@ export class AppMessagesManager {
this.handleEditedMessage(oldMessage, newMessage);
const dialog = this.getDialogByPeerId(peerId)[0];
const dialog = this.getDialogOnly(peerId);
const isTopMessage = dialog && dialog.top_message === mid;
// @ts-ignore
if(message.clear_history) { // that's will never happen
@ -4362,7 +3941,7 @@ export class AppMessagesManager { @@ -4362,7 +3941,7 @@ export class AppMessagesManager {
const storage = this.getMessagesStorage(peerId);
const history = getObjectKeysAndSort(storage, 'desc');
const foundDialog = this.getDialogByPeerId(peerId)[0];
const foundDialog = this.getDialogOnly(peerId);
const stillUnreadCount = (update as Update.updateReadChannelInbox).still_unread_count;
let newUnreadCount = 0;
let foundAffected = false;
@ -4531,7 +4110,7 @@ export class AppMessagesManager { @@ -4531,7 +4110,7 @@ export class AppMessagesManager {
rootScope.broadcast('history_delete', {peerId, msgs: historyUpdated.msgs});
const foundDialog = this.getDialogByPeerId(peerId)[0];
const foundDialog = this.getDialogOnly(peerId);
if(foundDialog) {
if(historyUpdated.unread) {
foundDialog.unread_count -= historyUpdated.unread;
@ -4551,8 +4130,7 @@ export class AppMessagesManager { @@ -4551,8 +4130,7 @@ export class AppMessagesManager {
const channel = appChatsManager.getChat(channelId);
const needDialog = channel._ === 'channel' && (!channel.pFlags.left && !channel.pFlags.kicked);
const foundDialog = this.getDialogByPeerId(peerId);
const hasDialog = foundDialog.length > 0;
const dialog = this.getDialogOnly(peerId);
const canViewHistory = channel._ === 'channel' && (channel.username || !channel.pFlags.left && !channel.pFlags.kicked);
const hasHistory = this.historiesStorage[peerId] !== undefined;
@ -4562,13 +4140,13 @@ export class AppMessagesManager { @@ -4562,13 +4140,13 @@ export class AppMessagesManager {
rootScope.broadcast('history_forbidden', peerId);
}
if(hasDialog !== needDialog) {
if(!!dialog !== needDialog) {
if(needDialog) {
this.reloadConversation(-channelId);
} else {
if(foundDialog[0]) {
if(dialog) {
this.dialogsStorage.dropDialog(peerId);
rootScope.broadcast('dialog_drop', {peerId: peerId, dialog: foundDialog[0]});
rootScope.broadcast('dialog_drop', {peerId, dialog});
}
}
}
@ -4695,7 +4273,7 @@ export class AppMessagesManager { @@ -4695,7 +4273,7 @@ export class AppMessagesManager {
if(peer._ === 'notifyPeer') {
const peerId = appPeersManager.getPeerId((peer as NotifyPeer.notifyPeer).peer);
const dialog = this.getDialogByPeerId(peerId)[0];
const dialog = this.getDialogOnly(peerId);
if(dialog) {
dialog.notify_settings = notify_settings;
rootScope.broadcast('dialog_notify_settings', dialog);
@ -4800,14 +4378,10 @@ export class AppMessagesManager { @@ -4800,14 +4378,10 @@ export class AppMessagesManager {
};
if(mute === undefined) {
mute = false;
const dialog = appMessagesManager.getDialogByPeerId(peerId)[0];
if(dialog && dialog.notify_settings) {
mute = (dialog.notify_settings.mute_until || 0) <= (Date.now() / 1000 | 0);
}
mute = !appNotificationsManager.isPeerLocalMuted(peerId, false);
}
settings.mute_until = mute ? 0xFFFFFFFF : 0;
settings.mute_until = mute ? 0x7FFFFFFF : 0;
return appNotificationsManager.updateNotifySettings({
_: 'inputNotifyPeer',

8
src/lib/appManagers/appNotificationsManager.ts

@ -409,7 +409,7 @@ export class AppNotificationsManager { @@ -409,7 +409,7 @@ export class AppNotificationsManager {
public isMuted(peerNotifySettings: PeerNotifySettings) {
return peerNotifySettings._ === 'peerNotifySettings' &&
(peerNotifySettings.mute_until * 1000) > tsNow();
((peerNotifySettings.mute_until * 1000) > tsNow() || peerNotifySettings.silent);
}
public getPeerMuted(peerId: number) {
@ -488,7 +488,8 @@ export class AppNotificationsManager { @@ -488,7 +488,8 @@ export class AppNotificationsManager {
};
public notify(data: NotifyOptions) {
console.log('notify', data, rootScope.idle.isIDLE, this.notificationsUiSupport, this.stopped);
//console.log('notify', data, rootScope.idle.isIDLE, this.notificationsUiSupport, this.stopped);
if(this.stopped) {
return;
}
@ -566,7 +567,8 @@ export class AppNotificationsManager { @@ -566,7 +567,8 @@ export class AppNotificationsManager {
tag: data.tag || '',
silent: data.silent || false
});
console.log('notify constructed notification');
//console.log('notify constructed notification');
} catch(e) {
this.notificationsUiSupport = false;
//WebPushApiManager.setLocalNotificationsDisabled();

4
src/lib/appManagers/appPollsManager.ts

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
import { MOUNT_CLASS_TO } from "../../config/debug";
import { copy } from "../../helpers/object";
import { InputMedia, MessageEntity } from "../../layer";
import { logger, LogLevels } from "../logger";
import { logger, LogTypes } from "../logger";
import apiManager from "../mtproto/mtprotoworker";
import { RichTextProcessor } from "../richtextprocessor";
import rootScope from "../rootScope";
@ -80,7 +80,7 @@ export class AppPollsManager { @@ -80,7 +80,7 @@ export class AppPollsManager {
public polls: {[id: string]: Poll} = {};
public results: {[id: string]: PollResults} = {};
private log = logger('POLLS', LogLevels.error);
private log = logger('POLLS', LogTypes.Error);
constructor() {
rootScope.addMultipleEventsListeners({

59
src/lib/appManagers/appStateManager.ts

@ -157,7 +157,9 @@ const REFRESH_KEYS = ['dialogs', 'allDialogsLoaded', 'messages', 'contactsList', @@ -157,7 +157,9 @@ const REFRESH_KEYS = ['dialogs', 'allDialogsLoaded', 'messages', 'contactsList',
'updates', 'maxSeenMsgId', 'filters', 'topPeers'] as any as Array<keyof State>;
export class AppStateManager extends EventListenerBase<{
save: (state: State) => Promise<void>
save: (state: State) => Promise<void>,
peerNeeded: (peerId: number) => void,
peerUnneeded: (peerId: number) => void,
}> {
public static STATE_INIT = STATE_INIT;
public loaded: Promise<State>;
@ -167,6 +169,9 @@ export class AppStateManager extends EventListenerBase<{ @@ -167,6 +169,9 @@ export class AppStateManager extends EventListenerBase<{
private savePromise: Promise<void>;
private tempId = 0;
private neededPeers: Map<number, Set<string>> = new Map();
private singlePeerMap: Map<string, number> = new Map();
constructor() {
super();
this.loadSavedState();
@ -266,7 +271,7 @@ export class AppStateManager extends EventListenerBase<{ @@ -266,7 +271,7 @@ export class AppStateManager extends EventListenerBase<{
public saveState() {
if(this.state === undefined || this.savePromise) return;
//return;
return;
const tempId = this.tempId;
this.savePromise = getHeavyAnimationPromise().then(() => {
@ -295,10 +300,18 @@ export class AppStateManager extends EventListenerBase<{ @@ -295,10 +300,18 @@ export class AppStateManager extends EventListenerBase<{
public setByKey(key: string, value: any) {
setDeepProperty(this.state, key, value);
rootScope.broadcast('settings_updated', {key, value});
const first = key.split('.')[0];
// @ts-ignore
this.pushToState(first, this.state[first]);
}
public pushToState<T extends keyof State>(key: T, value: State[T]) {
this.state[key] = value;
sessionStorage.set({
[key]: value
});
}
public setPeer(peerId: number, peer: any) {
@ -307,7 +320,45 @@ export class AppStateManager extends EventListenerBase<{ @@ -307,7 +320,45 @@ export class AppStateManager extends EventListenerBase<{
container[peerId] = peer;
}
public resetState() {
public requestPeer(peerId: number, type: string, limit?: number) {
let set = this.neededPeers.get(peerId);
if(set && set.has(type)) {
return;
}
if(!set) {
set = new Set();
this.neededPeers.set(peerId, set);
}
set.add(type);
this.dispatchEvent('peerNeeded', peerId);
if(limit !== undefined) {
this.keepPeerSingle(peerId, type);
}
}
public isPeerNeeded(peerId: number) {
return this.neededPeers.has(peerId);
}
public keepPeerSingle(peerId: number, type: string) {
const existsPeerId = this.singlePeerMap.get(type);
if(existsPeerId && existsPeerId !== peerId) {
const set = this.neededPeers.get(existsPeerId);
set.delete(type);
if(!set.size) {
this.neededPeers.delete(existsPeerId);
this.dispatchEvent('peerUnneeded', existsPeerId);
}
}
this.singlePeerMap.set(type, peerId);
}
/* public resetState() {
for(let i in this.state) {
// @ts-ignore
this.state[i] = false;
@ -315,7 +366,7 @@ export class AppStateManager extends EventListenerBase<{ @@ -315,7 +366,7 @@ export class AppStateManager extends EventListenerBase<{
sessionStorage.set(this.state).then(() => {
location.reload();
});
}
} */
}
//console.trace('appStateManager include');

2
src/lib/appManagers/appStickersManager.ts

@ -187,7 +187,7 @@ export class AppStickersManager { @@ -187,7 +187,7 @@ export class AppStickersManager {
if(res) {
delete set.installed_date;
rootScope.broadcast('stickers_deleted', set);
this.storage.remove(set.id, true);
this.storage.delete(set.id, true);
return true;
}
} else {

42
src/lib/appManagers/appUsersManager.ts

@ -22,7 +22,7 @@ import serverTimeManager from "../mtproto/serverTimeManager"; @@ -22,7 +22,7 @@ import serverTimeManager from "../mtproto/serverTimeManager";
import { RichTextProcessor } from "../richtextprocessor";
import rootScope from "../rootScope";
import searchIndexManager from "../searchIndexManager";
//import AppStorage from "../storage";
import AppStorage from "../storage";
import apiUpdatesManager from "./apiUpdatesManager";
import appChatsManager from "./appChatsManager";
import appPeersManager from "./appPeersManager";
@ -33,9 +33,9 @@ import appStateManager from "./appStateManager"; @@ -33,9 +33,9 @@ import appStateManager from "./appStateManager";
export type User = MTUser.user;
export class AppUsersManager {
/* private storage = new AppStorage<Record<number, User>>({
private storage = new AppStorage<Record<number, User>>({
storeName: 'users'
}); */
});
private users: {[userId: number]: User} = {};
private usernames: {[username: string]: number} = {};
@ -47,8 +47,6 @@ export class AppUsersManager { @@ -47,8 +47,6 @@ export class AppUsersManager {
private getTopPeersPromise: Promise<number[]>;
constructor() {
//this.users = this.storage.getCache();
setInterval(this.updateUsersStatuses, 60000);
rootScope.on('state_synchronized', this.updateUsersStatuses);
@ -132,11 +130,29 @@ export class AppUsersManager { @@ -132,11 +130,29 @@ export class AppUsersManager {
appStateManager.addEventListener('save', async() => {
const contactsList = [...this.contactsList];
for(const userId of contactsList) {
appStateManager.setPeer(userId, this.getUser(userId));
appStateManager.requestPeer(userId, 'contacts');
}
appStateManager.pushToState('contactsList', contactsList);
});
appStateManager.addEventListener('peerNeeded', (peerId: number) => {
if(peerId < 0 || this.storage.getFromCache(peerId)) {
return;
}
this.storage.set({
[peerId]: this.getUser(peerId)
});
});
appStateManager.addEventListener('peerUnneeded', (peerId: number) => {
if(peerId < 0 || !this.storage.getFromCache(peerId)) {
return;
}
this.storage.delete(peerId);
});
});
}
@ -330,15 +346,15 @@ export class AppUsersManager { @@ -330,15 +346,15 @@ export class AppUsersManager {
rootScope.broadcast('user_update', userId);
}
//console.log('we never give this up');
/* this.storage.set({
[userId]: user
}); */
if(changedTitle) {
rootScope.broadcast('peer_title_edit', user.id);
}
if(appStateManager.isPeerNeeded(userId)) {
this.storage.set({
[userId]: user
});
}
}
public formatUserPhone(phone: string) {
@ -670,7 +686,7 @@ export class AppUsersManager { @@ -670,7 +686,7 @@ export class AppUsersManager {
if(result.categories.length) {
peerIds = result.categories[0].peers.map((topPeer) => {
const peerId = appPeersManager.getPeerId(topPeer.peer);
appStateManager.setPeer(peerId, this.getUser(peerId));
appStateManager.requestPeer(peerId, 'topPeer');
return peerId;
});
}

4
src/lib/crypto/srp.ts

@ -2,12 +2,12 @@ import CryptoWorker from "../crypto/cryptoworker"; @@ -2,12 +2,12 @@ import CryptoWorker from "../crypto/cryptoworker";
import {str2bigInt, isZero,
bigInt2str, powMod, int2bigInt, mult, mod, sub, bitSize, negative, add, greater} from '../../vendor/leemon';
import {logger, LogLevels} from '../logger';
import {logger, LogTypes} from '../logger';
import { AccountPassword, PasswordKdfAlgo } from "../../layer";
import { bufferConcats, bytesToHex, bytesFromHex, bufferConcat, bytesXor } from "../../helpers/bytes";
//import { MOUNT_CLASS_TO } from "../../config/debug";
const log = logger('SRP', LogLevels.error);
const log = logger('SRP', LogTypes.Error);
//MOUNT_CLASS_TO && Object.assign(MOUNT_CLASS_TO, {str2bigInt, bigInt2str, int2bigInt});

75
src/lib/idb.ts

@ -36,21 +36,23 @@ export type IDBOptions = { @@ -36,21 +36,23 @@ export type IDBOptions = {
};
export default class IDBStorage {
//public static STORAGES: IDBStorage[] = [];
public openDbPromise: Promise<IDBDatabase>;
public storageIsAvailable = true;
//private static STORAGES: IDBStorage[] = [];
private openDbPromise: Promise<IDBDatabase>;
private storageIsAvailable = true;
private log: ReturnType<typeof logger> = logger('IDB');
private log: ReturnType<typeof logger>;
public name: string = Database.name;
public version: number = Database.version;
public stores: IDBStore[] = Database.stores;
private name: string = Database.name;
private version: number = Database.version;
private stores: IDBStore[] = Database.stores;
public storeName: string;
private storeName: string;
constructor(options: IDBOptions) {
safeAssign(this, options);
this.log = logger('IDB-' + this.storeName);
this.openDatabase(true);
//IDBStorage.STORAGES.push(this);
@ -161,35 +163,44 @@ export default class IDBStorage { @@ -161,35 +163,44 @@ export default class IDBStorage {
});
}
public delete(entryName: string): Promise<void> {
public delete(entryName: string | string[]): Promise<void> {
//return Promise.resolve();
return this.openDatabase().then((db) => {
try {
//this.log('delete: `' + entryName + '`');
var objectStore = db.transaction([this.storeName], 'readwrite')
.objectStore(this.storeName);
return new Promise((resolve, reject) => {
try {
//this.log('delete: `' + entryName + '`');
const transaction = db.transaction([this.storeName], 'readwrite');
const objectStore = transaction.objectStore(this.storeName);
var request = objectStore.delete(entryName);
} catch(error) {
return Promise.reject(error);
}
transaction.onerror = (e) => {
reject(transaction.error);
clearTimeout(timeout);
};
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
this.log.error('delete: request not finished!', entryName, request);
resolve();
}, 3000);
transaction.oncomplete = (e) => {
this.log('delete: transaction complete', entryName);
resolve();
clearTimeout(timeout);
};
request.onsuccess = (event) => {
//this.log('delete: deleted file', event);
resolve();
clearTimeout(timeout);
};
request.onerror = (error) => {
const timeout = setTimeout(() => {
this.log.error('delete: transaction not finished', entryName, transaction);
}, 10000);
if(!Array.isArray(entryName)) {
entryName = [].concat(entryName);
}
for(let i = 0, length = entryName.length; i < length; ++i) {
const request = objectStore.delete(entryName[i]);
request.onerror = (error) => {
reject(transaction.error);
clearTimeout(timeout);
};
}
} catch(error) {
reject(error);
clearTimeout(timeout);
};
}
});
});
}
@ -251,7 +262,7 @@ export default class IDBStorage { @@ -251,7 +262,7 @@ export default class IDBStorage {
};
transaction.oncomplete = (e) => {
//this.log('save: transaction complete:', entryName);
this.log('save: transaction complete:', entryName);
resolve();
clearTimeout(timeout);
};

35
src/lib/logger.ts

@ -6,43 +6,46 @@ @@ -6,43 +6,46 @@
import DEBUG from "../config/debug";
export enum LogLevels {
log = 1,
warn = 2,
error = 4,
debug = 8
export enum LogTypes {
None = 0,
Error = 1,
Warn = 2,
Log = 4,
Debug = 8
};
export const LOG_LEVELS = [LogTypes.None, LogTypes.Error, LogTypes.Warn, LogTypes.Log, LogTypes.Debug];
const _logTimer = Date.now();
function dT() {
return '[' + ((Date.now() - _logTimer) / 1000).toFixed(3) + ']';
}
export function logger(prefix: string, level = LogLevels.log | LogLevels.warn | LogLevels.error) {
export function logger(prefix: string, type: LogTypes = LogTypes.Log | LogTypes.Warn | LogTypes.Error) {
if(!DEBUG/* || true */) {
level = LogLevels.error;
type = LogTypes.Error;
}
//level = LogLevels.log | LogLevels.warn | LogLevels.error | LogLevels.debug
function Log(...args: any[]) {
return level & LogLevels.log && console.log(dT(), prefix, ...args);
return type & LogTypes.Log && console.log(dT(), prefix, ...args);
}
Log.warn = function(...args: any[]) {
return level & LogLevels.warn && console.warn(dT(), prefix, ...args);
return type & LogTypes.Warn && console.warn(dT(), prefix, ...args);
};
Log.info = function(...args: any[]) {
return level & LogLevels.log && console.info(dT(), prefix, ...args);
return type & LogTypes.Log && console.info(dT(), prefix, ...args);
};
Log.error = function(...args: any[]) {
return level & LogLevels.error && console.error(dT(), prefix, ...args);
return type & LogTypes.Error && console.error(dT(), prefix, ...args);
};
Log.trace = function(...args: any[]) {
return level & LogLevels.log && console.trace(dT(), prefix, ...args);
return type & LogTypes.Log && console.trace(dT(), prefix, ...args);
};
/* Log.debug = function(...args: any[]) {
@ -50,7 +53,7 @@ export function logger(prefix: string, level = LogLevels.log | LogLevels.warn | @@ -50,7 +53,7 @@ export function logger(prefix: string, level = LogLevels.log | LogLevels.warn |
}; */
Log.debug = function(...args: any[]) {
return level & LogLevels.debug && console.debug(dT(), prefix, ...args);
return type & LogTypes.Debug && console.debug(dT(), prefix, ...args);
};
Log.setPrefix = function(_prefix: string) {
@ -58,6 +61,10 @@ export function logger(prefix: string, level = LogLevels.log | LogLevels.warn | @@ -58,6 +61,10 @@ export function logger(prefix: string, level = LogLevels.log | LogLevels.warn |
};
Log.setPrefix(prefix);
Log.setLevel = function(level: 0 | 1 | 2 | 3 | 4) {
type = LOG_LEVELS.slice(0, level + 1).reduce((acc, v) => acc | v, 0) as any;
};
return Log;
};
};

4
src/lib/lottieLoader.ts

@ -12,7 +12,7 @@ import mediaSizes from "../helpers/mediaSizes"; @@ -12,7 +12,7 @@ import mediaSizes from "../helpers/mediaSizes";
import { clamp } from '../helpers/number';
import { pause } from '../helpers/schedulers';
import { isAndroid, isApple, isAppleMobile, isSafari } from "../helpers/userAgent";
import { logger, LogLevels } from "./logger";
import { logger, LogTypes } from "./logger";
import apiManager from "./mtproto/mtprotoworker";
let convert = (value: number) => {
@ -563,7 +563,7 @@ class LottieLoader { @@ -563,7 +563,7 @@ class LottieLoader {
private workers: QueryableWorker[] = [];
private curWorkerNum = 0;
private log = logger('LOTTIE', LogLevels.error);
private log = logger('LOTTIE', LogTypes.Error);
public getAnimation(element: HTMLElement) {
for(const i in this.players) {

4
src/lib/mtproto/apiFileManager.ts

@ -19,7 +19,7 @@ import { FileLocation, InputFile, InputFileLocation, UploadFile } from "../../la @@ -19,7 +19,7 @@ import { FileLocation, InputFile, InputFileLocation, UploadFile } from "../../la
import CacheStorageController from "../cacheStorage";
import cryptoWorker from "../crypto/cryptoworker";
import FileManager from "../filemanager";
import { logger, LogLevels } from "../logger";
import { logger, LogTypes } from "../logger";
import apiManager from "./apiManager";
import { isWebpSupported } from "./mtproto.worker";
@ -71,7 +71,7 @@ export class ApiFileManager { @@ -71,7 +71,7 @@ export class ApiFileManager {
public webpConvertPromises: {[fileName: string]: CancellablePromise<Uint8Array>} = {};
private log: ReturnType<typeof logger> = logger('AFM', LogLevels.error | LogLevels.log);
private log: ReturnType<typeof logger> = logger('AFM', LogTypes.Error | LogTypes.Log);
private tempId = 0;
private queueId = 0;
private debug = Modes.debug;

4
src/lib/mtproto/apiManager.ts

@ -352,8 +352,8 @@ export class ApiManager { @@ -352,8 +352,8 @@ export class ApiManager {
if(error.code === 401 && this.baseDcId === dcId) {
if(error.type !== 'SESSION_PASSWORD_NEEDED') {
sessionStorage.remove('dc')
sessionStorage.remove('user_auth'); // ! возможно тут вообще не нужно это делать, но нужно проверить случай с USER_DEACTIVATED (https://core.telegram.org/api/errors)
sessionStorage.delete('dc')
sessionStorage.delete('user_auth'); // ! возможно тут вообще не нужно это делать, но нужно проверить случай с USER_DEACTIVATED (https://core.telegram.org/api/errors)
//this.telegramMeNotify(false);
}

4
src/lib/mtproto/authorizer.ts

@ -16,7 +16,7 @@ import timeManager from "./timeManager"; @@ -16,7 +16,7 @@ import timeManager from "./timeManager";
import CryptoWorker from "../crypto/cryptoworker";
import { logger, LogLevels } from "../logger";
import { logger, LogTypes } from "../logger";
import { bytesCmp, bytesToHex, bytesFromHex, bytesXor } from "../../helpers/bytes";
import DEBUG from "../../config/debug";
import { cmp, int2bigInt, one, pow, str2bigInt, sub } from "../../vendor/leemon";
@ -74,7 +74,7 @@ export class Authorizer { @@ -74,7 +74,7 @@ export class Authorizer {
private log: ReturnType<typeof logger>;
constructor() {
this.log = logger(`AUTHORIZER`, LogLevels.error | LogLevels.log);
this.log = logger(`AUTHORIZER`, LogTypes.Error | LogTypes.Log);
}
public mtpSendPlainRequest(dcId: number, requestArray: Uint8Array) {

4
src/lib/mtproto/mtproto.service.ts

@ -8,14 +8,14 @@ @@ -8,14 +8,14 @@
import './mtproto.worker';
/// #endif
import { isSafari } from '../../helpers/userAgent';
import { logger, LogLevels } from '../logger';
import { logger, LogTypes } from '../logger';
import type { DownloadOptions } from './apiFileManager';
import type { WorkerTaskTemplate } from '../../types';
import { notifySomeone } from '../../helpers/context';
import type { InputFileLocation, FileLocation, UploadFile } from '../../layer';
import { CancellablePromise, deferredPromise } from '../../helpers/cancellablePromise';
const log = logger('SW', LogLevels.error | LogLevels.debug | LogLevels.log | LogLevels.warn);
const log = logger('SW', LogTypes.Error | LogTypes.Debug | LogTypes.Log | LogTypes.Warn);
const ctx = self as any as ServiceWorkerGlobalScope;
const deferredPromises: {[taskId: number]: CancellablePromise<any>} = {};

4
src/lib/mtproto/networker.ts

@ -16,7 +16,7 @@ import sessionStorage from '../sessionStorage'; @@ -16,7 +16,7 @@ import sessionStorage from '../sessionStorage';
import Schema from './schema';
import timeManager from './timeManager';
import NetworkerFactory from './networkerFactory';
import { logger, LogLevels } from '../logger';
import { logger, LogTypes } from '../logger';
import { InvokeApiOptions } from '../../types';
import { longToBytes } from '../crypto/crypto_utils';
import MTTransport from './transports/transport';
@ -141,7 +141,7 @@ export default class MTPNetworker { @@ -141,7 +141,7 @@ export default class MTPNetworker {
const suffix = this.isFileUpload ? '-U' : this.isFileDownload ? '-D' : '';
this.name = 'NET-' + dcId + suffix;
//this.log = logger(this.name, this.upload && this.dcId === 2 ? LogLevels.debug | LogLevels.warn | LogLevels.log | LogLevels.error : LogLevels.error);
this.log = logger(this.name, LogLevels.log | LogLevels.error | LogLevels.debug | LogLevels.warn);
this.log = logger(this.name, /* LogTypes.Log | LogTypes.Debug | */LogTypes.Error | LogTypes.Warn);
this.log('constructor'/* , this.authKey, this.authKeyID, this.serverSalt */);
// Test resend after bad_server_salt

8
src/lib/mtproto/transports/tcpObfuscated.ts

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
*/
import Modes from "../../../config/modes";
import { logger, LogLevels } from "../../logger";
import { logger, LogTypes } from "../../logger";
import MTPNetworker from "../networker";
import Obfuscation from "./obfuscation";
import MTTransport, { MTConnection, MTConnectionConstructable } from "./transport";
@ -33,9 +33,9 @@ export default class TcpObfuscated implements MTTransport { @@ -33,9 +33,9 @@ export default class TcpObfuscated implements MTTransport {
//private debugPayloads: MTPNetworker['debugRequests'] = [];
constructor(private Connection: MTConnectionConstructable, private dcId: number, private url: string, private logSuffix: string, public retryTimeout: number) {
let logLevel = LogLevels.error | LogLevels.log;
if(this.debug) logLevel |= LogLevels.debug;
this.log = logger(`TCP-${dcId}` + logSuffix, logLevel);
let logTypes = LogTypes.Error | LogTypes.Log;
if(this.debug) logTypes |= LogTypes.Debug;
this.log = logger(`TCP-${dcId}` + logSuffix, logTypes);
this.log('constructor');
this.connect();

8
src/lib/mtproto/transports/websocket.ts

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
import { logger, LogLevels } from '../../logger';
import { logger, LogTypes } from '../../logger';
import Modes from '../../../config/modes';
import EventListenerBase from '../../../helpers/eventListenerBase';
import { MTConnection } from './transport';
@ -21,9 +21,9 @@ export default class Socket extends EventListenerBase<{ @@ -21,9 +21,9 @@ export default class Socket extends EventListenerBase<{
constructor(protected dcId: number, protected url: string, logSuffix: string) {
super();
let logLevel = LogLevels.error | LogLevels.log;
if(this.debug) logLevel |= LogLevels.debug;
this.log = logger(`WS-${dcId}` + logSuffix, logLevel);
let logTypes = LogTypes.Error | LogTypes.Log;
if(this.debug) logTypes |= LogTypes.Debug;
this.log = logger(`WS-${dcId}` + logSuffix, logTypes);
this.log('constructor');
this.connect();

4
src/lib/opusDecodeController.ts

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
import { MOUNT_CLASS_TO } from "../config/debug";
import { isSafari } from "../helpers/userAgent";
import { logger, LogLevels } from "./logger";
import { logger, LogTypes } from "./logger";
type Result = {
bytes: Uint8Array,
@ -28,7 +28,7 @@ export class OpusDecodeController { @@ -28,7 +28,7 @@ export class OpusDecodeController {
private tasks: Array<Task> = [];
private keepAlive = false;
private isPlaySupportedResult: boolean;
private log = logger('OPUS', LogLevels.error);
private log = logger('OPUS', LogTypes.Error);
public isPlaySupported() {
if(this.isPlaySupportedResult !== undefined) return this.isPlaySupportedResult;

21
src/lib/storage.ts

@ -20,7 +20,7 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex @@ -20,7 +20,7 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
//private cache: Partial<{[key: string]: Storage[typeof key]}> = {};
private cache: Partial<Storage> = {};
private useStorage = true;
private updateKeys: Set<keyof Storage> = new Set();
private keysToSet: Set<keyof Storage> = new Set();
private saveThrottled: () => void;
constructor(storageOptions: Omit<IDBOptions, 'storeName' | 'stores'> & {stores?: DatabaseStore[], storeName: DatabaseStoreName}) {
@ -29,8 +29,12 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex @@ -29,8 +29,12 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
AppStorage.STORAGES.push(this);
this.saveThrottled = throttle(async() => {
const keys = Array.from(this.updateKeys.values()) as string[];
this.updateKeys.clear();
if(!this.keysToSet.size) {
return;
}
const keys = Array.from(this.keysToSet.values()) as string[];
this.keysToSet.clear();
try {
//console.log('setItem: will set', key/* , value */);
@ -102,23 +106,28 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex @@ -102,23 +106,28 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
console.log('LocalStorage set: stringify time by own stringify:', performance.now() - perf); */
if(this.useStorage && !onlyLocal) {
this.updateKeys.add(key);
this.keysToSet.add(key);
this.saveThrottled();
}
}
}
}
public async remove(key: keyof Storage, saveLocal = false) {
public async delete(key: keyof Storage, saveLocal = false) {
/* if(!this.cache.hasOwnProperty(key)) {
return;
} */
// ! it is needed here
key = '' + key;
if(!saveLocal) {
delete this.cache[key];
}
if(this.useStorage) {
this.keysToSet.delete(key);
try {
await this.storage.delete(key as string);
} catch(e) {
@ -137,7 +146,7 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex @@ -137,7 +146,7 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
storage.useStorage = enabled;
if(!enabled) {
storage.updateKeys.clear();
storage.keysToSet.clear();
return storage.clear();
} else {
return storage.set(storage.cache);

476
src/lib/storages/dialogs.ts

@ -10,27 +10,80 @@ @@ -10,27 +10,80 @@
*/
import { tsNow } from "../../helpers/date";
import type { Message } from "../../layer";
import type { Chat, DialogPeer, Message, MessagesPeerDialogs, Update } from "../../layer";
import type { AppChatsManager } from "../appManagers/appChatsManager";
import type { AppMessagesManager, Dialog, MyMessage } from "../appManagers/appMessagesManager";
import type { AppPeersManager } from "../appManagers/appPeersManager";
import type { AppUsersManager } from "../appManagers/appUsersManager";
import type { AppDraftsManager } from "../appManagers/appDraftsManager";
import type { AppNotificationsManager } from "../appManagers/appNotificationsManager";
import type { ApiUpdatesManager } from "../appManagers/apiUpdatesManager";
import type { ServerTimeManager } from "../mtproto/serverTimeManager";
import apiManager from "../mtproto/mtprotoworker";
import searchIndexManager from "../searchIndexManager";
import { insertInDescendSortedArray } from "../../helpers/array";
import { forEachReverse, insertInDescendSortedArray } from "../../helpers/array";
import rootScope from "../rootScope";
import AppStorage from "../storage";
import { safeReplaceObject } from "../../helpers/object";
import { AppStateManager } from "../appManagers/appStateManager";
export default class DialogsStorage {
public dialogs: {[peerId: string]: Dialog} = {};
private storage = new AppStorage<Record<number, Dialog>>({
storeName: 'dialogs'
});
private dialogs: {[peerId: string]: Dialog} = {};
public byFolders: {[folderId: number]: Dialog[]} = {};
public allDialogsLoaded: {[folder_id: number]: boolean};
private dialogsOffsetDate: {[folder_id: number]: number};
public pinnedOrders: {[folder_id: number]: number[]};
private pinnedOrders: {[folder_id: number]: number[]};
private dialogsNum: number;
public dialogsIndex = searchIndexManager.createIndex();
private dialogsIndex = searchIndexManager.createIndex();
private cachedResults: {
query: string,
count: number,
dialogs: Dialog[],
folderId: number
} = {
query: '',
count: 0,
dialogs: [],
folderId: 0
};
constructor(private appMessagesManager: AppMessagesManager,
private appChatsManager: AppChatsManager,
private appPeersManager: AppPeersManager,
private appUsersManager: AppUsersManager,
private appDraftsManager: AppDraftsManager,
private appNotificationsManager: AppNotificationsManager,
private appStateManager: AppStateManager,
private apiUpdatesManager: ApiUpdatesManager,
private serverTimeManager: ServerTimeManager
) {
this.dialogs = this.storage.getCache();
constructor(private appMessagesManager: AppMessagesManager, private appChatsManager: AppChatsManager, private appPeersManager: AppPeersManager, private serverTimeManager: ServerTimeManager) {
this.reset();
rootScope.on('language_change', (e) => {
const peerId = appUsersManager.getSelf().id;
const dialog = this.getDialogOnly(peerId);
if(dialog) {
const peerText = appPeersManager.getPeerSearchText(peerId);
searchIndexManager.indexObject(peerId, peerText, this.dialogsIndex);
}
});
rootScope.addMultipleEventsListeners({
updateFolderPeers: this.onUpdateFolderPeers,
updateDialogPinned: this.onUpdateDialogPinned,
updatePinnedDialogs: this.onUpdatePinnedDialogs,
});
}
public reset() {
@ -99,6 +152,10 @@ export default class DialogsStorage { @@ -99,6 +152,10 @@ export default class DialogsStorage {
return [];
}
public getDialogOnly(peerId: number) {
return this.dialogs[peerId];
}
/*
var date = Date.now() / 1000 | 0;
var m = date * 0x10000;
@ -134,7 +191,7 @@ export default class DialogsStorage { @@ -134,7 +191,7 @@ export default class DialogsStorage {
}
}
if(dialog.draft && dialog.draft._ === 'draftMessage' && dialog.draft.date > topDate) {
if(dialog.draft?._ === 'draftMessage' && dialog.draft.date > topDate) {
topDate = dialog.draft.date;
}
}
@ -161,6 +218,24 @@ export default class DialogsStorage { @@ -161,6 +218,24 @@ export default class DialogsStorage {
return this.generateDialogPinnedDateByIndex(pinnedIndex);
}
public generateDialog(peerId: number) {
const dialog: Dialog = {
_: 'dialog',
pFlags: {},
peer: this.appPeersManager.getOutputPeer(peerId),
top_message: 0,
read_inbox_max_id: 0,
read_outbox_max_id: 0,
unread_count: 0,
unread_mentions_count: 0,
notify_settings: {
_: 'peerNotifySettings',
},
};
return dialog;
}
public pushDialog(dialog: Dialog, offsetDate?: number) {
const dialogs = this.getFolder(dialog.folder_id);
const pos = dialogs.findIndex(d => d.peerId === dialog.peerId);
@ -170,6 +245,35 @@ export default class DialogsStorage { @@ -170,6 +245,35 @@ export default class DialogsStorage {
//if(!this.dialogs[dialog.peerId]) {
this.dialogs[dialog.peerId] = dialog;
const historyStorage = this.appMessagesManager.getHistoryStorage(dialog.peerId);
const history = [].concat(historyStorage.history.slice);
let incomingMessage: any;
for(const mid of history) {
const message = this.appMessagesManager.getMessageByPeer(dialog.peerId, mid);
if(!message.pFlags.is_outgoing) {
incomingMessage = message;
if(message.fromId !== dialog.peerId) {
this.appStateManager.requestPeer(message.fromId, 'topMessage_' + dialog.peerId, 1);
}
break;
}
}
dialog.topMessage = incomingMessage;
if(dialog.peerId < 0 && dialog.pts) {
const newPts = this.apiUpdatesManager.channelStates[-dialog.peerId].pts;
dialog.pts = newPts;
}
this.storage.set({
[dialog.peerId]: dialog
});
this.appStateManager.requestPeer(dialog.peerId, 'dialog');
//}
if(offsetDate &&
@ -195,4 +299,362 @@ export default class DialogsStorage { @@ -195,4 +299,362 @@ export default class DialogsStorage {
return foundDialog;
}
public applyDialogs(dialogsResult: MessagesPeerDialogs.messagesPeerDialogs) {
// * В эту функцию попадут только те диалоги, в которых есть read_inbox_max_id и read_outbox_max_id, в отличие от тех, что будут в getTopMessages
// ! fix 'dialogFolder', maybe there is better way to do it, this only can happen by 'messages.getPinnedDialogs' by folder_id: 0
forEachReverse(dialogsResult.dialogs, (dialog, idx) => {
if(dialog._ === 'dialogFolder') {
dialogsResult.dialogs.splice(idx, 1);
}
});
this.appUsersManager.saveApiUsers(dialogsResult.users);
this.appChatsManager.saveApiChats(dialogsResult.chats);
this.appMessagesManager.saveMessages(dialogsResult.messages);
this.appMessagesManager.log('applyConversation', dialogsResult);
const updatedDialogs: {[peerId: number]: Dialog} = {};
(dialogsResult.dialogs as Dialog[]).forEach((dialog) => {
const peerId = this.appPeersManager.getPeerId(dialog.peer);
let topMessage = dialog.top_message;
const topPendingMessage = this.appMessagesManager.pendingTopMsgs[peerId];
if(topPendingMessage) {
if(!topMessage
|| (this.appMessagesManager.getMessageByPeer(peerId, topPendingMessage) as MyMessage).date > (this.appMessagesManager.getMessageByPeer(peerId, topMessage) as MyMessage).date) {
dialog.top_message = topMessage = topPendingMessage;
this.appMessagesManager.getHistoryStorage(peerId).maxId = topPendingMessage;
}
}
/* const d = Object.assign({}, dialog);
if(peerId === 239602833) {
this.log.error('applyConversation lun', dialog, d);
} */
if(topMessage || (dialog.draft && dialog.draft._ === 'draftMessage')) {
this.saveDialog(dialog);
updatedDialogs[peerId] = dialog;
} else {
const dropped = this.dropDialog(peerId);
if(dropped.length) {
rootScope.broadcast('dialog_drop', {peerId, dialog: dropped[0]});
}
}
const updates = this.appMessagesManager.newUpdatesAfterReloadToHandle[peerId];
if(updates !== undefined) {
for(const update of updates) {
this.apiUpdatesManager.saveUpdate(update);
}
delete this.appMessagesManager.newUpdatesAfterReloadToHandle[peerId];
}
});
if(Object.keys(updatedDialogs).length) {
rootScope.broadcast('dialogs_multiupdate', updatedDialogs);
}
}
/**
* Won't save migrated from peer, forbidden peers, left and kicked
*/
public saveDialog(dialog: Dialog, folderId = 0) {
const peerId = this.appPeersManager.getPeerId(dialog.peer);
if(!peerId) {
console.error('saveConversation no peerId???', dialog, folderId);
return false;
}
if(dialog._ !== 'dialog'/* || peerId === 239602833 */) {
console.error('saveConversation not regular dialog', dialog, Object.assign({}, dialog));
}
const channelId = this.appPeersManager.isChannel(peerId) ? -peerId : 0;
if(peerId < 0) {
const chat: Chat = this.appChatsManager.getChat(-peerId);
if(chat._ === 'channelForbidden' || chat._ === 'chatForbidden' || (chat as Chat.chat).pFlags.left || (chat as Chat.chat).pFlags.kicked) {
return false;
}
}
const peerText = this.appPeersManager.getPeerSearchText(peerId);
searchIndexManager.indexObject(peerId, peerText, this.dialogsIndex);
let mid: number, message;
if(dialog.top_message) {
mid = this.appMessagesManager.generateMessageId(dialog.top_message);//dialog.top_message;
message = this.appMessagesManager.getMessageByPeer(peerId, mid);
} else {
mid = this.appMessagesManager.generateTempMessageId(peerId);
message = {
_: 'message',
id: mid,
mid,
from_id: this.appPeersManager.getOutputPeer(this.appUsersManager.getSelf().id),
peer_id: this.appPeersManager.getOutputPeer(peerId),
deleted: true,
pFlags: {out: true},
date: 0,
message: ''
};
this.appMessagesManager.saveMessages([message], {isOutgoing: true});
}
if(!message?.pFlags) {
this.appMessagesManager.log.error('saveConversation no message:', dialog, message);
}
if(!channelId && peerId < 0) {
const chat = this.appChatsManager.getChat(-peerId);
if(chat && chat.migrated_to && chat.pFlags.deactivated) {
const migratedToPeer = this.appPeersManager.getPeerId(chat.migrated_to);
this.appMessagesManager.migratedFromTo[peerId] = migratedToPeer;
this.appMessagesManager.migratedToFrom[migratedToPeer] = peerId;
return;
}
}
const wasDialogBefore = this.getDialogOnly(peerId);
dialog.top_message = mid;
dialog.read_inbox_max_id = this.appMessagesManager.generateMessageId(wasDialogBefore && !dialog.read_inbox_max_id ? wasDialogBefore.read_inbox_max_id : dialog.read_inbox_max_id);
dialog.read_outbox_max_id = this.appMessagesManager.generateMessageId(wasDialogBefore && !dialog.read_outbox_max_id ? wasDialogBefore.read_outbox_max_id : dialog.read_outbox_max_id);
if(!dialog.hasOwnProperty('folder_id')) {
if(dialog._ === 'dialog') {
// ! СЛОЖНО ! СМОТРИ В getTopMessages
dialog.folder_id = wasDialogBefore ? wasDialogBefore.folder_id : folderId;
}/* else if(dialog._ === 'dialogFolder') {
dialog.folder_id = dialog.folder.id;
} */
}
dialog.draft = this.appDraftsManager.saveDraft(peerId, 0, dialog.draft);
dialog.peerId = peerId;
// Because we saved message without dialog present
if(message.pFlags.is_outgoing) {
if(mid > dialog[message.pFlags.out ? 'read_outbox_max_id' : 'read_inbox_max_id']) message.pFlags.unread = true;
else delete message.pFlags.unread;
}
const historyStorage = this.appMessagesManager.getHistoryStorage(peerId);
/* if(historyStorage === undefined) { // warning
historyStorage.history.push(mid);
if(this.mergeReplyKeyboard(historyStorage, message)) {
rootScope.broadcast('history_reply_markup', {peerId});
}
} else */if(!historyStorage.history.slice.length) {
historyStorage.history.unshift(mid);
}
historyStorage.maxId = mid;
historyStorage.readMaxId = dialog.read_inbox_max_id;
historyStorage.readOutboxMaxId = dialog.read_outbox_max_id;
this.appNotificationsManager.savePeerSettings(peerId, dialog.notify_settings);
if(channelId && dialog.pts) {
this.apiUpdatesManager.addChannelState(channelId, dialog.pts);
}
this.generateIndexForDialog(dialog);
if(wasDialogBefore) {
safeReplaceObject(wasDialogBefore, dialog);
}
this.pushDialog(dialog, message.date);
}
public getDialogs(query = '', offsetIndex?: number, limit = 20, folderId = 0) {
const realFolderId = folderId > 1 ? 0 : folderId;
let curDialogStorage = this.getFolder(folderId);
if(query) {
if(!limit || this.cachedResults.query !== query || this.cachedResults.folderId !== folderId) {
this.cachedResults.query = query;
this.cachedResults.folderId = folderId;
const results = searchIndexManager.search(query, this.dialogsIndex);
this.cachedResults.dialogs = [];
for(const peerId in this.dialogs) {
const dialog = this.dialogs[peerId];
if(results[dialog.peerId] && dialog.folder_id === folderId) {
this.cachedResults.dialogs.push(dialog);
}
}
this.cachedResults.dialogs.sort((d1, d2) => d2.index - d1.index);
this.cachedResults.count = this.cachedResults.dialogs.length;
}
curDialogStorage = this.cachedResults.dialogs;
} else {
this.cachedResults.query = '';
}
let offset = 0;
if(offsetIndex > 0) {
for(; offset < curDialogStorage.length; offset++) {
if(offsetIndex > curDialogStorage[offset].index) {
break;
}
}
}
if(query || this.allDialogsLoaded[realFolderId] || curDialogStorage.length >= offset + limit) {
return Promise.resolve({
dialogs: curDialogStorage.slice(offset, offset + limit),
count: this.allDialogsLoaded[realFolderId] ? curDialogStorage.length : null,
isEnd: this.allDialogsLoaded[realFolderId] && (offset + limit) >= curDialogStorage.length
});
}
return this.appMessagesManager.getTopMessages(limit, realFolderId).then(messagesDialogs => {
//const curDialogStorage = this[folderId];
offset = 0;
if(offsetIndex > 0) {
for(; offset < curDialogStorage.length; offset++) {
if(offsetIndex > curDialogStorage[offset].index) {
break;
}
}
}
//this.log.warn(offset, offset + limit, curDialogStorage.dialogs.length, this.dialogs.length);
return {
dialogs: curDialogStorage.slice(offset, offset + limit),
count: messagesDialogs._ === 'messages.dialogs' ? messagesDialogs.dialogs.length : messagesDialogs.count,
isEnd: this.allDialogsLoaded[realFolderId] && (offset + limit) >= curDialogStorage.length
};
});
}
// only 0 and 1 folders
private onUpdateFolderPeers = (update: Update.updateFolderPeers) => {
//this.log('updateFolderPeers', update);
const peers = update.folder_peers;
peers.forEach((folderPeer) => {
const {folder_id, peer} = folderPeer;
const peerId = this.appPeersManager.getPeerId(peer);
const dialog = this.dropDialog(peerId)[0];
if(dialog) {
if(dialog.pFlags?.pinned) {
delete dialog.pFlags.pinned;
this.pinnedOrders[folder_id].findAndSplice(p => p === dialog.peerId);
}
dialog.folder_id = folder_id;
this.generateIndexForDialog(dialog);
this.pushDialog(dialog); // need for simultaneously updatePinnedDialogs
}
this.appMessagesManager.scheduleHandleNewDialogs(peerId, dialog);
});
};
private onUpdateDialogPinned = (update: Update.updateDialogPinned) => {
const folderId = update.folder_id ?? 0;
//this.log('updateDialogPinned', update);
const peerId = this.appPeersManager.getPeerId((update.peer as DialogPeer.dialogPeer).peer);
const dialog = this.getDialogOnly(peerId);
// этот код внизу никогда не сработает, в папках за пиннед отвечает updateDialogFilter
/* if(update.folder_id > 1) {
const filter = this.filtersStorage.filters[update.folder_id];
if(update.pFlags.pinned) {
filter.pinned_peers.unshift(peerId);
} else {
filter.pinned_peers.findAndSplice(p => p === peerId);
}
} */
if(dialog) {
if(!update.pFlags.pinned) {
delete dialog.pFlags.pinned;
this.pinnedOrders[folderId].findAndSplice(p => p === dialog.peerId);
} else { // means set
dialog.pFlags.pinned = true;
}
this.generateIndexForDialog(dialog);
}
this.appMessagesManager.scheduleHandleNewDialogs(peerId, dialog);
};
private onUpdatePinnedDialogs = (update: Update.updatePinnedDialogs) => {
const folderId = update.folder_id ?? 0;
const handleOrder = (order: number[]) => {
this.pinnedOrders[folderId].length = 0;
order.reverse(); // index must be higher
order.forEach((peerId) => {
newPinned[peerId] = true;
const dialog = this.getDialogOnly(peerId);
this.appMessagesManager.scheduleHandleNewDialogs(peerId, dialog);
if(!dialog) {
return;
}
dialog.pFlags.pinned = true;
this.generateIndexForDialog(dialog);
});
this.getFolder(folderId).forEach(dialog => {
const peerId = dialog.peerId;
if(dialog.pFlags.pinned && !newPinned[peerId]) {
this.appMessagesManager.scheduleHandleNewDialogs(peerId);
}
});
};
//this.log('updatePinnedDialogs', update);
const newPinned: {[peerId: number]: true} = {};
if(!update.order) {
apiManager.invokeApi('messages.getPinnedDialogs', {
folder_id: folderId
}).then((dialogsResult) => {
// * for test reordering and rendering
// dialogsResult.dialogs.reverse();
this.applyDialogs(dialogsResult);
handleOrder(dialogsResult.dialogs.map(d => d.peerId));
/* dialogsResult.dialogs.forEach((dialog) => {
newPinned[dialog.peerId] = true;
});
this.dialogsStorage.getFolder(folderId).forEach((dialog) => {
const peerId = dialog.peerId;
if(dialog.pFlags.pinned && !newPinned[peerId]) {
this.newDialogsToHandle[peerId] = {reload: true};
this.scheduleHandleNewDialogs();
}
}); */
});
return;
}
//this.log('before order:', this.dialogsStorage[0].map(d => d.peerId));
handleOrder(update.order.map(peer => this.appPeersManager.getPeerId((peer as DialogPeer.dialogPeer).peer)));
};
}

10
src/scripts/in/schema_additional_params.json

@ -52,7 +52,8 @@ @@ -52,7 +52,8 @@
"predicate": "dialog",
"params": [
{"name": "index", "type": "number"},
{"name": "peerId", "type": "number"}
{"name": "peerId", "type": "number"},
{"name": "topMessage", "type": "any"}
]
}, {
"predicate": "dialogFolder",
@ -121,12 +122,7 @@ @@ -121,12 +122,7 @@
"predicate": "user",
"params": [
{"name": "initials", "type": "string"},
{"name": "rFirstName", "type": "string"},
{"name": "rFullName", "type": "string"},
{"name": "rPhone", "type": "string"},
{"name": "sortName", "type": "string"},
{"name": "sortStatus", "type": "number"},
{"name": "num", "type": "number"}
{"name": "sortName", "type": "string"}
]
}, {
"predicate": "auth.sentCode",

Loading…
Cancel
Save