Refactor & refactor
This commit is contained in:
parent
836ab06faf
commit
5e159f5519
@ -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 {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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<{
|
||||
|
||||
// * 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);
|
||||
|
@ -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'/* ,
|
||||
|
@ -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));
|
||||
|
@ -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');
|
||||
|
@ -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 {
|
||||
};
|
||||
|
||||
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 {
|
||||
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();
|
||||
|
@ -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 {
|
||||
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) {
|
||||
|
@ -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 {
|
||||
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));
|
||||
|
@ -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
10
src/layer.d.ts
vendored
@ -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 {
|
||||
draft?: DraftMessage,
|
||||
folder_id?: number,
|
||||
index?: number,
|
||||
peerId?: number
|
||||
peerId?: number,
|
||||
topMessage?: any
|
||||
};
|
||||
|
||||
export type dialogFolder = {
|
||||
|
@ -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 {
|
||||
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() {
|
||||
|
@ -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
|
||||
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 {
|
||||
|
||||
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 {
|
||||
|
||||
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 {
|
||||
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) {
|
||||
|
@ -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 {
|
||||
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 {
|
||||
|
||||
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 {
|
||||
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 {
|
||||
});
|
||||
|
||||
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 {
|
||||
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 {
|
||||
let dialog: Dialog;
|
||||
|
||||
if(typeof(_dialog) === 'number') {
|
||||
let originalDialog = appMessagesManager.getDialogByPeerId(_dialog)[0];
|
||||
let originalDialog = appMessagesManager.getDialogOnly(_dialog);
|
||||
if(!originalDialog) {
|
||||
originalDialog = {
|
||||
peerId: _dialog,
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
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);
|
||||
|
||||
|
@ -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
|
||||
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 {
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
|
||||
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 {
|
||||
});
|
||||
});
|
||||
|
||||
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 {
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
} */
|
||||
|
||||
if(offsetIndex && dialog.index > offsetIndex) {
|
||||
this.newDialogsToHandle[dialog.peerId] = dialog;
|
||||
this.scheduleHandleNewDialogs(dialog.peerId, dialog);
|
||||
hasPrepend = true;
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
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 {
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
|
||||
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 {
|
||||
}).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 {
|
||||
}
|
||||
|
||||
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 {
|
||||
) && !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 {
|
||||
};
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
}
|
||||
};
|
||||
|
||||
// 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 {
|
||||
|
||||
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 {
|
||||
|
||||
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 {
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
};
|
||||
|
||||
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',
|
||||
|
@ -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 {
|
||||
};
|
||||
|
||||
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 {
|
||||
tag: data.tag || '',
|
||||
silent: data.silent || false
|
||||
});
|
||||
console.log('notify constructed notification');
|
||||
|
||||
//console.log('notify constructed notification');
|
||||
} catch(e) {
|
||||
this.notificationsUiSupport = false;
|
||||
//WebPushApiManager.setLocalNotificationsDisabled();
|
||||
|
@ -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 {
|
||||
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({
|
||||
|
@ -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<{
|
||||
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<{
|
||||
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<{
|
||||
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<{
|
||||
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<{
|
||||
sessionStorage.set(this.state).then(() => {
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
//console.trace('appStateManager include');
|
||||
|
@ -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 {
|
||||
|
@ -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";
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
@ -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});
|
||||
|
||||
|
@ -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 {
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
var request = objectStore.delete(entryName);
|
||||
} catch(error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
this.log.error('delete: request not finished!', entryName, request);
|
||||
resolve();
|
||||
}, 3000);
|
||||
try {
|
||||
//this.log('delete: `' + entryName + '`');
|
||||
const transaction = db.transaction([this.storeName], 'readwrite');
|
||||
const objectStore = transaction.objectStore(this.storeName);
|
||||
|
||||
request.onsuccess = (event) => {
|
||||
//this.log('delete: deleted file', event);
|
||||
resolve();
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
|
||||
request.onerror = (error) => {
|
||||
transaction.onerror = (e) => {
|
||||
reject(transaction.error);
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
|
||||
transaction.oncomplete = (e) => {
|
||||
this.log('delete: transaction complete', entryName);
|
||||
resolve();
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
|
||||
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 {
|
||||
};
|
||||
|
||||
transaction.oncomplete = (e) => {
|
||||
//this.log('save: transaction complete:', entryName);
|
||||
this.log('save: transaction complete:', entryName);
|
||||
resolve();
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
|
@ -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 |
|
||||
}; */
|
||||
|
||||
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 |
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
};
|
||||
|
@ -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 {
|
||||
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) {
|
||||
|
@ -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 {
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
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) {
|
||||
|
@ -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>} = {};
|
||||
|
@ -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 {
|
||||
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
|
||||
|
@ -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 {
|
||||
//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();
|
||||
|
@ -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<{
|
||||
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();
|
||||
|
||||
|
@ -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 {
|
||||
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;
|
||||
|
@ -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
|
||||
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
|
||||
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
|
||||
storage.useStorage = enabled;
|
||||
|
||||
if(!enabled) {
|
||||
storage.updateKeys.clear();
|
||||
storage.keysToSet.clear();
|
||||
return storage.clear();
|
||||
} else {
|
||||
return storage.set(storage.cache);
|
||||
|
@ -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 {
|
||||
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 {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
|
||||
//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 {
|
||||
|
||||
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)));
|
||||
};
|
||||
}
|
||||
|
@ -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 @@
|
||||
"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…
x
Reference in New Issue
Block a user