Improve state save performance
This commit is contained in:
parent
1c6e90efa6
commit
2289fbff07
@ -24,9 +24,12 @@
|
||||
// parse('{"file_reference": {"type": "bytes", "value": [1,2,3]}, "file_reference2": {"type": "bytes", "value": [3,2,1]}}');
|
||||
// -> {file_reference: Uint8Array}
|
||||
|
||||
export function stringify(value: any) {
|
||||
// TOO SLOW TOO
|
||||
/* export function stringify(value: any) {
|
||||
return JSON.stringify(value, (key, value) => {
|
||||
if(key == 'downloaded' || (key == 'url' && value.indexOf('blob:') === 0)) return undefined;
|
||||
return value;
|
||||
});
|
||||
}
|
||||
} */
|
||||
|
||||
export {};
|
9
src/layer.d.ts
vendored
9
src/layer.d.ts
vendored
@ -493,7 +493,14 @@ export namespace User {
|
||||
bot_info_version?: number,
|
||||
restriction_reason?: Array<RestrictionReason>,
|
||||
bot_inline_placeholder?: string,
|
||||
lang_code?: string
|
||||
lang_code?: string,
|
||||
initials?: string,
|
||||
rFirstName?: string,
|
||||
rFullName?: string,
|
||||
rPhone?: string,
|
||||
sortName?: string,
|
||||
sortStatus?: number,
|
||||
num?: number
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ import apiManager from '../mtproto/mtprotoworker';
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import $rootScope from "../rootScope";
|
||||
import searchIndexManager from "../searchIndexManager";
|
||||
import { copy, getAbbreviation, isObject, numberWithCommas, safeReplaceObject } from "../utils";
|
||||
import { copy, defineNotNumerableProperties, getAbbreviation, isObject, numberWithCommas, safeReplaceObject } from "../utils";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import appProfileManager from "./appProfileManager";
|
||||
@ -89,61 +89,64 @@ export class AppChatsManager {
|
||||
apiChats.forEach(chat => this.saveApiChat(chat));
|
||||
}
|
||||
|
||||
public saveApiChat(apiChat: any) {
|
||||
if(!isObject(apiChat)) {
|
||||
public saveApiChat(chat: any) {
|
||||
if(!isObject(chat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// * exclude from state
|
||||
defineNotNumerableProperties(chat, ['rTitle', 'initials']);
|
||||
|
||||
apiChat.rTitle = apiChat.title || 'chat_title_deleted';
|
||||
apiChat.rTitle = RichTextProcessor.wrapRichText(apiChat.title, {noLinks: true, noLinebreaks: true}) || 'chat_title_deleted';
|
||||
//chat.rTitle = chat.title || 'chat_title_deleted';
|
||||
chat.rTitle = RichTextProcessor.wrapRichText(chat.title, {noLinks: true, noLinebreaks: true}) || 'chat_title_deleted';
|
||||
|
||||
let oldChat = this.chats[apiChat.id];
|
||||
const oldChat = this.chats[chat.id];
|
||||
|
||||
apiChat.initials = getAbbreviation(apiChat.title);
|
||||
chat.initials = getAbbreviation(chat.title);
|
||||
|
||||
if(apiChat.pFlags === undefined) {
|
||||
apiChat.pFlags = {};
|
||||
if(chat.pFlags === undefined) {
|
||||
chat.pFlags = {};
|
||||
}
|
||||
|
||||
if(apiChat.pFlags.min) {
|
||||
if(chat.pFlags.min) {
|
||||
if(oldChat !== undefined) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(apiChat._ == 'channel' &&
|
||||
apiChat.participants_count === undefined &&
|
||||
if(chat._ == 'channel' &&
|
||||
chat.participants_count === undefined &&
|
||||
oldChat !== undefined &&
|
||||
oldChat.participants_count) {
|
||||
apiChat.participants_count = oldChat.participants_count;
|
||||
chat.participants_count = oldChat.participants_count;
|
||||
}
|
||||
|
||||
if(apiChat.username) {
|
||||
let searchUsername = searchIndexManager.cleanUsername(apiChat.username);
|
||||
this.usernames[searchUsername] = apiChat.id;
|
||||
if(chat.username) {
|
||||
let searchUsername = searchIndexManager.cleanUsername(chat.username);
|
||||
this.usernames[searchUsername] = chat.id;
|
||||
}
|
||||
|
||||
let changedPhoto = false;
|
||||
if(oldChat === undefined) {
|
||||
oldChat = this.chats[apiChat.id] = apiChat;
|
||||
this.chats[chat.id] = chat;
|
||||
} else {
|
||||
let oldPhoto = oldChat.photo && oldChat.photo.photo_small;
|
||||
let newPhoto = apiChat.photo && apiChat.photo.photo_small;
|
||||
let newPhoto = chat.photo && chat.photo.photo_small;
|
||||
if(JSON.stringify(oldPhoto) !== JSON.stringify(newPhoto)) {
|
||||
changedPhoto = true;
|
||||
}
|
||||
|
||||
safeReplaceObject(oldChat, apiChat);
|
||||
$rootScope.$broadcast('chat_update', apiChat.id);
|
||||
safeReplaceObject(oldChat, chat);
|
||||
$rootScope.$broadcast('chat_update', chat.id);
|
||||
}
|
||||
|
||||
if(this.cachedPhotoLocations[apiChat.id] !== undefined) {
|
||||
safeReplaceObject(this.cachedPhotoLocations[apiChat.id], apiChat &&
|
||||
apiChat.photo ? apiChat.photo : {empty: true});
|
||||
if(this.cachedPhotoLocations[chat.id] !== undefined) {
|
||||
safeReplaceObject(this.cachedPhotoLocations[chat.id], chat &&
|
||||
chat.photo ? chat.photo : {empty: true});
|
||||
}
|
||||
|
||||
if(changedPhoto) {
|
||||
$rootScope.$broadcast('avatar_update', -apiChat.id);
|
||||
$rootScope.$broadcast('avatar_update', -chat.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { MOUNT_CLASS_TO } from '../mtproto/mtproto_config';
|
||||
import referenceDatabase, { ReferenceContext } from '../mtproto/referenceDatabase';
|
||||
import opusDecodeController from '../opusDecodeController';
|
||||
import { RichTextProcessor } from '../richtextprocessor';
|
||||
import { FileURLType, getFileURL, isObject, safeReplaceArrayInObject } from '../utils';
|
||||
import { defineNotNumerableProperties, FileURLType, getFileURL, isObject, safeReplaceArrayInObject } from '../utils';
|
||||
import appDownloadManager, { DownloadBlob } from './appDownloadManager';
|
||||
import appPhotosManager from './appPhotosManager';
|
||||
|
||||
@ -48,6 +48,12 @@ class AppDocsManager {
|
||||
}
|
||||
|
||||
this.docs[doc.id] = doc;
|
||||
|
||||
// * exclude from state
|
||||
defineNotNumerableProperties(doc, [/* 'thumbs', */'type', 'h', 'w', 'file_name',
|
||||
'file', 'duration', 'downloaded', 'url', 'audioTitle',
|
||||
'audioPerformer', 'sticker', 'stickerEmoji', 'stickerEmojiRaw',
|
||||
'stickerSetInput', 'stickerThumbConverted', 'animated', 'supportsStreaming']);
|
||||
|
||||
doc.attributes.forEach(attribute => {
|
||||
switch(attribute._) {
|
||||
@ -277,6 +283,7 @@ class AppDocsManager {
|
||||
const originalPromise = download;
|
||||
originalPromise.then((blob) => {
|
||||
if(thumb) {
|
||||
defineNotNumerableProperties(thumb, ['url']);
|
||||
thumb.url = URL.createObjectURL(blob);
|
||||
return;
|
||||
} else if(!doc.supportsStreaming) {
|
||||
|
@ -13,7 +13,7 @@ import { RichTextProcessor } from "../richtextprocessor";
|
||||
import $rootScope from "../rootScope";
|
||||
import searchIndexManager from '../searchIndexManager';
|
||||
import AppStorage from '../storage';
|
||||
import { copy, deepEqual, getObjectKeysAndSort, langPack, limitSymbols, listMergeSorted, safeReplaceObject, splitStringByLength, tsNow } from "../utils";
|
||||
import { copy, deepEqual, defineNotNumerableProperties, getObjectKeysAndSort, langPack, limitSymbols, listMergeSorted, safeReplaceObject, splitStringByLength, tsNow } from "../utils";
|
||||
//import { telegramMeWebService } from "../mtproto/mtproto";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
@ -2195,78 +2195,81 @@ export class AppMessagesManager {
|
||||
});
|
||||
}
|
||||
|
||||
public saveMessages(apiMessages: any[], options: {
|
||||
public saveMessages(messages: any[], options: {
|
||||
isEdited?: boolean
|
||||
} = {}) {
|
||||
apiMessages.forEach((apiMessage) => {
|
||||
if(apiMessage.pFlags === undefined) {
|
||||
apiMessage.pFlags = {};
|
||||
messages.forEach((message) => {
|
||||
if(message.pFlags === undefined) {
|
||||
message.pFlags = {};
|
||||
}
|
||||
|
||||
if(apiMessage._ == 'messageEmpty') {
|
||||
if(message._ == 'messageEmpty') {
|
||||
return;
|
||||
}
|
||||
|
||||
const peerID = this.getMessagePeer(apiMessage);
|
||||
const isChannel = apiMessage.peer_id._ == 'peerChannel';
|
||||
// * exclude from state
|
||||
defineNotNumerableProperties(message, ['rReply', 'mid', 'savedFrom', 'fwdFromID', 'fromID', 'peerID', 'reply_to_mid', 'viaBotID']);
|
||||
|
||||
const peerID = this.getMessagePeer(message);
|
||||
const isChannel = message.peer_id._ == 'peerChannel';
|
||||
const channelID = isChannel ? -peerID : 0;
|
||||
const isBroadcast = isChannel && appChatsManager.isBroadcast(channelID);
|
||||
|
||||
const mid = appMessagesIDsManager.getFullMessageID(apiMessage.id, channelID);
|
||||
apiMessage.mid = mid;
|
||||
const mid = appMessagesIDsManager.getFullMessageID(message.id, channelID);
|
||||
message.mid = mid;
|
||||
|
||||
if(apiMessage.grouped_id) {
|
||||
const storage = this.groupedMessagesStorage[apiMessage.grouped_id] ?? (this.groupedMessagesStorage[apiMessage.grouped_id] = {});
|
||||
storage[mid] = apiMessage;
|
||||
if(message.grouped_id) {
|
||||
const storage = this.groupedMessagesStorage[message.grouped_id] ?? (this.groupedMessagesStorage[message.grouped_id] = {});
|
||||
storage[mid] = message;
|
||||
}
|
||||
|
||||
const dialog = this.getDialogByPeerID(peerID)[0];
|
||||
if(dialog && mid > 0) {
|
||||
if(mid > dialog[apiMessage.pFlags.out
|
||||
if(mid > dialog[message.pFlags.out
|
||||
? 'read_outbox_max_id'
|
||||
: 'read_inbox_max_id']) {
|
||||
apiMessage.pFlags.unread = true;
|
||||
message.pFlags.unread = true;
|
||||
}
|
||||
}
|
||||
// this.log(dT(), 'msg unread', mid, apiMessage.pFlags.out, dialog && dialog[apiMessage.pFlags.out ? 'read_outbox_max_id' : 'read_inbox_max_id'])
|
||||
|
||||
if(apiMessage.reply_to && apiMessage.reply_to.reply_to_msg_id) {
|
||||
apiMessage.reply_to_mid = appMessagesIDsManager.getFullMessageID(apiMessage.reply_to.reply_to_msg_id, channelID);
|
||||
if(message.reply_to && message.reply_to.reply_to_msg_id) {
|
||||
message.reply_to_mid = appMessagesIDsManager.getFullMessageID(message.reply_to.reply_to_msg_id, channelID);
|
||||
}
|
||||
|
||||
apiMessage.date -= serverTimeManager.serverTimeOffset;
|
||||
message.date -= serverTimeManager.serverTimeOffset;
|
||||
|
||||
const myID = appUsersManager.getSelf().id;
|
||||
|
||||
apiMessage.peerID = peerID;
|
||||
if(apiMessage.peerID == myID && !apiMessage.from_id && !apiMessage.fwd_from) {
|
||||
apiMessage.fromID = myID;
|
||||
message.peerID = peerID;
|
||||
if(message.peerID == myID && !message.from_id && !message.fwd_from) {
|
||||
message.fromID = myID;
|
||||
} else {
|
||||
apiMessage.fromID = apiMessage.pFlags.post || (!apiMessage.pFlags.out && !apiMessage.from_id) ? peerID : appPeersManager.getPeerID(apiMessage.from_id);
|
||||
message.fromID = message.pFlags.post || (!message.pFlags.out && !message.from_id) ? peerID : appPeersManager.getPeerID(message.from_id);
|
||||
}
|
||||
|
||||
const fwdHeader = apiMessage.fwd_from;
|
||||
const fwdHeader = message.fwd_from;
|
||||
if(fwdHeader) {
|
||||
//if(peerID == myID) {
|
||||
if(fwdHeader.saved_from_peer && fwdHeader.saved_from_msg_id) {
|
||||
const savedFromPeerID = appPeersManager.getPeerID(fwdHeader.saved_from_peer);
|
||||
const savedFromMid = appMessagesIDsManager.getFullMessageID(fwdHeader.saved_from_msg_id,
|
||||
appPeersManager.isChannel(savedFromPeerID) ? -savedFromPeerID : 0);
|
||||
apiMessage.savedFrom = savedFromPeerID + '_' + savedFromMid;
|
||||
message.savedFrom = savedFromPeerID + '_' + savedFromMid;
|
||||
}
|
||||
|
||||
apiMessage.fromID = appPeersManager.getPeerID(deepEqual(apiMessage.from_id, fwdHeader.from_id) ? fwdHeader.from_id : apiMessage.from_id);
|
||||
message.fromID = appPeersManager.getPeerID(deepEqual(message.from_id, fwdHeader.from_id) ? fwdHeader.from_id : message.from_id);
|
||||
/* } else {
|
||||
apiMessage.fwdPostID = fwdHeader.channel_post;
|
||||
} */
|
||||
|
||||
apiMessage.fwdFromID = appPeersManager.getPeerID(fwdHeader.from_id);
|
||||
message.fwdFromID = appPeersManager.getPeerID(fwdHeader.from_id);
|
||||
|
||||
fwdHeader.date -= serverTimeManager.serverTimeOffset;
|
||||
}
|
||||
|
||||
if(apiMessage.via_bot_id > 0) {
|
||||
apiMessage.viaBotID = apiMessage.via_bot_id;
|
||||
if(message.via_bot_id > 0) {
|
||||
message.viaBotID = message.via_bot_id;
|
||||
}
|
||||
|
||||
const mediaContext: ReferenceContext = {
|
||||
@ -2274,27 +2277,27 @@ export class AppMessagesManager {
|
||||
messageID: mid
|
||||
};
|
||||
|
||||
if(apiMessage.media) {
|
||||
switch(apiMessage.media._) {
|
||||
if(message.media) {
|
||||
switch(message.media._) {
|
||||
case 'messageMediaEmpty':
|
||||
delete apiMessage.media;
|
||||
delete message.media;
|
||||
break;
|
||||
case 'messageMediaPhoto':
|
||||
if(apiMessage.media.ttl_seconds) {
|
||||
apiMessage.media = {_: 'messageMediaUnsupportedWeb'};
|
||||
if(message.media.ttl_seconds) {
|
||||
message.media = {_: 'messageMediaUnsupportedWeb'};
|
||||
} else {
|
||||
apiMessage.media.photo = appPhotosManager.savePhoto(apiMessage.media.photo, mediaContext);
|
||||
message.media.photo = appPhotosManager.savePhoto(message.media.photo, mediaContext);
|
||||
//appPhotosManager.savePhoto(apiMessage.media.photo, mediaContext);
|
||||
}
|
||||
break;
|
||||
case 'messageMediaPoll':
|
||||
apiMessage.media.poll = appPollsManager.savePoll(apiMessage.media.poll, apiMessage.media.results);
|
||||
message.media.poll = appPollsManager.savePoll(message.media.poll, message.media.results);
|
||||
break;
|
||||
case 'messageMediaDocument':
|
||||
if(apiMessage.media.ttl_seconds) {
|
||||
apiMessage.media = {_: 'messageMediaUnsupportedWeb'};
|
||||
if(message.media.ttl_seconds) {
|
||||
message.media = {_: 'messageMediaUnsupportedWeb'};
|
||||
} else {
|
||||
apiMessage.media.document = appDocsManager.saveDoc(apiMessage.media.document, mediaContext); // 11.04.2020 warning
|
||||
message.media.document = appDocsManager.saveDoc(message.media.document, mediaContext); // 11.04.2020 warning
|
||||
}
|
||||
|
||||
|
||||
@ -2303,91 +2306,91 @@ export class AppMessagesManager {
|
||||
/* if(apiMessage.media.webpage.document) {
|
||||
appDocsManager.saveDoc(apiMessage.media.webpage.document, mediaContext);
|
||||
} */
|
||||
appWebPagesManager.saveWebPage(apiMessage.media.webpage, apiMessage.mid, mediaContext);
|
||||
appWebPagesManager.saveWebPage(message.media.webpage, message.mid, mediaContext);
|
||||
break;
|
||||
/*case 'messageMediaGame':
|
||||
AppGamesManager.saveGame(apiMessage.media.game, apiMessage.mid, mediaContext);
|
||||
apiMessage.media.handleMessage = true;
|
||||
break; */
|
||||
case 'messageMediaInvoice':
|
||||
apiMessage.media = {_: 'messageMediaUnsupportedWeb'};
|
||||
message.media = {_: 'messageMediaUnsupportedWeb'};
|
||||
break;
|
||||
case 'messageMediaGeoLive':
|
||||
apiMessage.media._ = 'messageMediaGeo';
|
||||
message.media._ = 'messageMediaGeo';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(apiMessage.action) {
|
||||
if(message.action) {
|
||||
let migrateFrom: number;
|
||||
let migrateTo: number;
|
||||
switch(apiMessage.action._) {
|
||||
switch(message.action._) {
|
||||
//case 'messageActionChannelEditPhoto':
|
||||
case 'messageActionChatEditPhoto':
|
||||
apiMessage.action.photo = appPhotosManager.savePhoto(apiMessage.action.photo, mediaContext);
|
||||
message.action.photo = appPhotosManager.savePhoto(message.action.photo, mediaContext);
|
||||
//appPhotosManager.savePhoto(apiMessage.action.photo, mediaContext);
|
||||
if(isBroadcast) { // ! messageActionChannelEditPhoto не существует в принципе, это используется для перевода.
|
||||
apiMessage.action._ = 'messageActionChannelEditPhoto';
|
||||
message.action._ = 'messageActionChannelEditPhoto';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'messageActionChatEditTitle':
|
||||
if(isBroadcast) {
|
||||
apiMessage.action._ = 'messageActionChannelEditTitle';
|
||||
message.action._ = 'messageActionChannelEditTitle';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'messageActionChatDeletePhoto':
|
||||
if(isBroadcast) {
|
||||
apiMessage.action._ = 'messageActionChannelDeletePhoto';
|
||||
message.action._ = 'messageActionChannelDeletePhoto';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'messageActionChatAddUser':
|
||||
if(apiMessage.action.users.length == 1) {
|
||||
apiMessage.action.user_id = apiMessage.action.users[0];
|
||||
if(apiMessage.fromID == apiMessage.action.user_id) {
|
||||
if(message.action.users.length == 1) {
|
||||
message.action.user_id = message.action.users[0];
|
||||
if(message.fromID == message.action.user_id) {
|
||||
if(isChannel) {
|
||||
apiMessage.action._ = 'messageActionChatJoined';
|
||||
message.action._ = 'messageActionChatJoined';
|
||||
} else {
|
||||
apiMessage.action._ = 'messageActionChatReturn';
|
||||
message.action._ = 'messageActionChatReturn';
|
||||
}
|
||||
}
|
||||
} else if(apiMessage.action.users.length > 1) {
|
||||
apiMessage.action._ = 'messageActionChatAddUsers';
|
||||
} else if(message.action.users.length > 1) {
|
||||
message.action._ = 'messageActionChatAddUsers';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'messageActionChatDeleteUser':
|
||||
if(apiMessage.fromID == apiMessage.action.user_id) {
|
||||
apiMessage.action._ = 'messageActionChatLeave';
|
||||
if(message.fromID == message.action.user_id) {
|
||||
message.action._ = 'messageActionChatLeave';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'messageActionChannelMigrateFrom':
|
||||
migrateFrom = -apiMessage.action.chat_id;
|
||||
migrateFrom = -message.action.chat_id;
|
||||
migrateTo = -channelID;
|
||||
break
|
||||
|
||||
case 'messageActionChatMigrateTo':
|
||||
migrateFrom = -channelID;
|
||||
migrateTo = -apiMessage.action.channel_id;
|
||||
migrateTo = -message.action.channel_id;
|
||||
break;
|
||||
|
||||
case 'messageActionHistoryClear':
|
||||
//apiMessage.deleted = true;
|
||||
apiMessage.clear_history = true;
|
||||
delete apiMessage.pFlags.out;
|
||||
delete apiMessage.pFlags.unread;
|
||||
message.clear_history = true;
|
||||
delete message.pFlags.out;
|
||||
delete message.pFlags.unread;
|
||||
break;
|
||||
|
||||
case 'messageActionPhoneCall':
|
||||
delete apiMessage.fromID;
|
||||
apiMessage.action.type =
|
||||
(apiMessage.pFlags.out ? 'out_' : 'in_') +
|
||||
delete message.fromID;
|
||||
message.action.type =
|
||||
(message.pFlags.out ? 'out_' : 'in_') +
|
||||
(
|
||||
apiMessage.action.reason._ == 'phoneCallDiscardReasonMissed' ||
|
||||
apiMessage.action.reason._ == 'phoneCallDiscardReasonBusy'
|
||||
message.action.reason._ == 'phoneCallDiscardReasonMissed' ||
|
||||
message.action.reason._ == 'phoneCallDiscardReasonBusy'
|
||||
? 'missed'
|
||||
: 'ok'
|
||||
);
|
||||
@ -2402,17 +2405,17 @@ export class AppMessagesManager {
|
||||
}
|
||||
}
|
||||
|
||||
apiMessage.rReply = this.getRichReplyText(apiMessage);
|
||||
message.rReply = this.getRichReplyText(message);
|
||||
|
||||
if(apiMessage.message && apiMessage.message.length && !apiMessage.totalEntities) {
|
||||
const myEntities = RichTextProcessor.parseEntities(apiMessage.message);
|
||||
const apiEntities = apiMessage.entities || [];
|
||||
apiMessage.totalEntities = RichTextProcessor.mergeEntities(myEntities, apiEntities, !apiMessage.pending);
|
||||
if(message.message && message.message.length && !message.totalEntities) {
|
||||
const myEntities = RichTextProcessor.parseEntities(message.message);
|
||||
const apiEntities = message.entities || [];
|
||||
message.totalEntities = RichTextProcessor.mergeEntities(myEntities, apiEntities, !message.pending);
|
||||
}
|
||||
|
||||
if(!options.isEdited) {
|
||||
this.messagesStorage[mid] = apiMessage;
|
||||
(this.messagesStorageByPeerID[peerID] ?? (this.messagesStorageByPeerID[peerID] = {}))[mid] = apiMessage;
|
||||
this.messagesStorage[mid] = message;
|
||||
(this.messagesStorageByPeerID[peerID] ?? (this.messagesStorageByPeerID[peerID] = {}))[mid] = message;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { bytesFromHex, getFileNameByLocation } from "../bin_utils";
|
||||
import { DownloadOptions } from "../mtproto/apiFileManager";
|
||||
import apiManager from "../mtproto/mtprotoworker";
|
||||
import referenceDatabase, { ReferenceContext } from "../mtproto/referenceDatabase";
|
||||
import { calcImageInBox, isObject, safeReplaceArrayInObject } from "../utils";
|
||||
import { calcImageInBox, defineNotNumerableProperties, isObject, safeReplaceArrayInObject } from "../utils";
|
||||
import { MyDocument } from "./appDocsManager";
|
||||
import appDownloadManager from "./appDownloadManager";
|
||||
import appUsersManager from "./appUsersManager";
|
||||
@ -280,6 +280,8 @@ export class AppPhotosManager {
|
||||
download = appDownloadManager.download(downloadOptions);
|
||||
download.then(blob => {
|
||||
if(!cacheContext.downloaded || cacheContext.downloaded < blob.size) {
|
||||
defineNotNumerableProperties(cacheContext, ['downloaded', 'url']);
|
||||
|
||||
cacheContext.downloaded = blob.size;
|
||||
cacheContext.url = URL.createObjectURL(blob);
|
||||
|
||||
|
@ -96,13 +96,17 @@ export class AppStateManager extends EventListenerBase<{
|
||||
public saveState() {
|
||||
if(this.state === undefined) return;
|
||||
|
||||
//let perf = performance.now();
|
||||
this.setListenerResult('save', this.state);
|
||||
//this.log('saveState: event time:', performance.now() - perf);
|
||||
|
||||
//const pinnedOrders = appMessagesManager.dialogsStorage.pinnedOrders;
|
||||
|
||||
//perf = performance.now();
|
||||
AppStorage.set({
|
||||
state: this.state
|
||||
});
|
||||
//this.log('saveState: storage set time:', performance.now() - perf);
|
||||
}
|
||||
|
||||
public pushToState<T extends keyof State>(key: T, value: State[T]) {
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { formatPhoneNumber } from "../../components/misc";
|
||||
import { InputUser, Update, User as MTUser } from "../../layer";
|
||||
import { InputUser, Update, User as MTUser, UserStatus } from "../../layer";
|
||||
//import apiManager from '../mtproto/apiManager';
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import serverTimeManager from "../mtproto/serverTimeManager";
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import $rootScope from "../rootScope";
|
||||
import searchIndexManager from "../searchIndexManager";
|
||||
import { getAbbreviation, isObject, safeReplaceObject, tsNow } from "../utils";
|
||||
import { defineNotNumerableProperties, getAbbreviation, isObject, safeReplaceObject, tsNow } from "../utils";
|
||||
import appChatsManager from "./appChatsManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
import appStateManager from "./appStateManager";
|
||||
@ -40,15 +40,7 @@ import appStateManager from "./appStateManager";
|
||||
sortName?: string,
|
||||
sortStatus?: number,
|
||||
}; */
|
||||
export interface User extends MTUser.user {
|
||||
initials?: string,
|
||||
num?: number,
|
||||
rFirstName?: string,
|
||||
rFullName?: string,
|
||||
rPhone?: string,
|
||||
sortName?: string,
|
||||
sortStatus?: number,
|
||||
}
|
||||
export type User = MTUser.user;
|
||||
|
||||
export class AppUsersManager {
|
||||
public users: {[userID: number]: User} = {};
|
||||
@ -172,7 +164,7 @@ export class AppUsersManager {
|
||||
}
|
||||
|
||||
return await apiManager.invokeApi('contacts.resolveUsername', {username}).then(resolvedPeer => {
|
||||
this.saveApiUser(resolvedPeer.users[0]);
|
||||
this.saveApiUser(resolvedPeer.users[0] as User);
|
||||
appChatsManager.saveApiChats(resolvedPeer.chats);
|
||||
|
||||
return this.users[this.usernames[username]];
|
||||
@ -237,75 +229,80 @@ export class AppUsersManager {
|
||||
apiUsers.forEach((user) => this.saveApiUser(user));
|
||||
}
|
||||
|
||||
public saveApiUser(apiUser: any, noReplace?: boolean) {
|
||||
if(!isObject(apiUser) ||
|
||||
noReplace && isObject(this.users[apiUser.id]) && this.users[apiUser.id].first_name) {
|
||||
public saveApiUser(_user: MTUser, noReplace?: boolean) {
|
||||
if(_user._ == 'userEmpty') return;
|
||||
|
||||
const user = _user;
|
||||
if(noReplace && isObject(this.users[user.id]) && this.users[user.id].first_name) {
|
||||
return;
|
||||
}
|
||||
|
||||
var userID = apiUser.id;
|
||||
var userID = user.id;
|
||||
var result = this.users[userID];
|
||||
|
||||
if(apiUser.pFlags === undefined) {
|
||||
apiUser.pFlags = {};
|
||||
if(user.pFlags === undefined) {
|
||||
user.pFlags = {};
|
||||
}
|
||||
|
||||
if(apiUser.pFlags.min) {
|
||||
if(user.pFlags.min) {
|
||||
if(result !== undefined) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(apiUser.phone) {
|
||||
apiUser.rPhone = '+' + formatPhoneNumber(apiUser.phone).formatted;
|
||||
// * exclude from state
|
||||
defineNotNumerableProperties(user, ['initials', 'num', 'rFirstName', 'rFullName', 'rPhone', 'sortName', 'sortStatus']);
|
||||
|
||||
if(user.phone) {
|
||||
user.rPhone = '+' + formatPhoneNumber(user.phone).formatted;
|
||||
}
|
||||
|
||||
const fullName = apiUser.first_name + ' ' + (apiUser.last_name || '');
|
||||
if(apiUser.first_name) {
|
||||
apiUser.rFirstName = RichTextProcessor.wrapRichText(apiUser.first_name, {noLinks: true, noLinebreaks: true})
|
||||
apiUser.rFullName = apiUser.last_name ? RichTextProcessor.wrapRichText(fullName, {noLinks: true, noLinebreaks: true}) : apiUser.rFirstName;
|
||||
const fullName = user.first_name + ' ' + (user.last_name || '');
|
||||
if(user.first_name) {
|
||||
user.rFirstName = RichTextProcessor.wrapRichText(user.first_name, {noLinks: true, noLinebreaks: true})
|
||||
user.rFullName = user.last_name ? RichTextProcessor.wrapRichText(fullName, {noLinks: true, noLinebreaks: true}) : user.rFirstName;
|
||||
} else {
|
||||
apiUser.rFirstName = RichTextProcessor.wrapRichText(apiUser.last_name, {noLinks: true, noLinebreaks: true}) || apiUser.rPhone || 'user_first_name_deleted';
|
||||
apiUser.rFullName = RichTextProcessor.wrapRichText(apiUser.last_name, {noLinks: true, noLinebreaks: true}) || apiUser.rPhone || 'user_name_deleted';
|
||||
user.rFirstName = RichTextProcessor.wrapRichText(user.last_name, {noLinks: true, noLinebreaks: true}) || user.rPhone || 'user_first_name_deleted';
|
||||
user.rFullName = RichTextProcessor.wrapRichText(user.last_name, {noLinks: true, noLinebreaks: true}) || user.rPhone || 'user_name_deleted';
|
||||
}
|
||||
|
||||
if(apiUser.username) {
|
||||
var searchUsername = searchIndexManager.cleanUsername(apiUser.username);
|
||||
if(user.username) {
|
||||
var searchUsername = searchIndexManager.cleanUsername(user.username);
|
||||
this.usernames[searchUsername] = userID;
|
||||
}
|
||||
|
||||
apiUser.sortName = apiUser.pFlags.deleted ? '' : searchIndexManager.cleanSearchText(fullName, false);
|
||||
user.sortName = user.pFlags.deleted ? '' : searchIndexManager.cleanSearchText(fullName, false);
|
||||
|
||||
apiUser.initials = getAbbreviation(fullName);
|
||||
user.initials = getAbbreviation(fullName);
|
||||
|
||||
if(apiUser.status) {
|
||||
if(apiUser.status.expires) {
|
||||
apiUser.status.expires -= serverTimeManager.serverTimeOffset
|
||||
if(user.status) {
|
||||
if((user.status as UserStatus.userStatusOnline).expires) {
|
||||
(user.status as UserStatus.userStatusOnline).expires -= serverTimeManager.serverTimeOffset
|
||||
}
|
||||
|
||||
if(apiUser.status.was_online) {
|
||||
apiUser.status.was_online -= serverTimeManager.serverTimeOffset
|
||||
if((user.status as UserStatus.userStatusOffline).was_online) {
|
||||
(user.status as UserStatus.userStatusOffline).was_online -= serverTimeManager.serverTimeOffset
|
||||
}
|
||||
}
|
||||
|
||||
if(apiUser.pFlags.bot) {
|
||||
apiUser.sortStatus = -1;
|
||||
if(user.pFlags.bot) {
|
||||
user.sortStatus = -1;
|
||||
} else {
|
||||
apiUser.sortStatus = this.getUserStatusForSort(apiUser.status);
|
||||
user.sortStatus = this.getUserStatusForSort(user.status);
|
||||
}
|
||||
|
||||
var result = this.users[userID];
|
||||
if(result === undefined) {
|
||||
result = this.users[userID] = apiUser;
|
||||
result = this.users[userID] = user;
|
||||
} else {
|
||||
safeReplaceObject(result, apiUser);
|
||||
safeReplaceObject(result, user);
|
||||
}
|
||||
|
||||
$rootScope.$broadcast('user_update', userID);
|
||||
|
||||
if(this.cachedPhotoLocations[userID] !== undefined) {
|
||||
safeReplaceObject(this.cachedPhotoLocations[userID], apiUser &&
|
||||
apiUser.photo ? apiUser.photo : {empty: true});
|
||||
safeReplaceObject(this.cachedPhotoLocations[userID], user &&
|
||||
user.photo ? user.photo : {empty: true});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Modes } from './mtproto/mtproto_config';
|
||||
import { notifySomeone, isWorker } from '../helpers/context';
|
||||
import { stringify } from '../helpers/json';
|
||||
//import { stringify } from '../helpers/json';
|
||||
|
||||
class ConfigStorage {
|
||||
public keyPrefix = '';
|
||||
@ -72,7 +72,15 @@ class ConfigStorage {
|
||||
value = obj[key];
|
||||
key = prefix + key;
|
||||
this.cache[key] = value;
|
||||
|
||||
value = JSON.stringify(value);
|
||||
/* let perf = performance.now();
|
||||
let value2 = JSON.stringify(value);
|
||||
console.log('LocalStorage set: stringify time by JSON.stringify:', performance.now() - perf, value2);
|
||||
|
||||
perf = performance.now();
|
||||
value = stringify(value);
|
||||
console.log('LocalStorage set: stringify time by own stringify:', performance.now() - perf); */
|
||||
|
||||
if(this.useLs) {
|
||||
try {
|
||||
|
@ -580,4 +580,17 @@ export function splitStringByLength(str: string, maxLength: number) {
|
||||
return out;
|
||||
}
|
||||
|
||||
(window as any).splitStringByLength = splitStringByLength;
|
||||
export function defineNotNumerableProperties(obj: {[key: string]: any}, names: string[]) {
|
||||
//const perf = performance.now();
|
||||
const props = {writable: true, configurable: true};
|
||||
const out: {[name: string]: typeof props} = {};
|
||||
names.forEach(name => {
|
||||
if(obj[name] === undefined) {
|
||||
out[name] = props;
|
||||
}
|
||||
});
|
||||
Object.defineProperties(obj, out);
|
||||
//console.log('defineNotNumerableProperties time:', performance.now() - perf);
|
||||
}
|
||||
|
||||
//(window as any).splitStringByLength = splitStringByLength;
|
||||
|
@ -211,4 +211,15 @@
|
||||
"params": [
|
||||
{"name": "nested", "type": "Array<MessageEntity>"}
|
||||
]
|
||||
}, {
|
||||
"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"}
|
||||
]
|
||||
}]
|
Loading…
Reference in New Issue
Block a user