Browse Source

Improve state save performance

master
morethanwords 4 years ago
parent
commit
2289fbff07
  1. 7
      src/helpers/json.ts
  2. 9
      src/layer.d.ts
  3. 51
      src/lib/appManagers/appChatsManager.ts
  4. 9
      src/lib/appManagers/appDocsManager.ts
  5. 149
      src/lib/appManagers/appMessagesManager.ts
  6. 4
      src/lib/appManagers/appPhotosManager.ts
  7. 4
      src/lib/appManagers/appStateManager.ts
  8. 83
      src/lib/appManagers/appUsersManager.ts
  9. 10
      src/lib/storage.ts
  10. 15
      src/lib/utils.ts
  11. 11
      src/scripts/in/schema_additional_params.json

7
src/helpers/json.ts

@ -24,9 +24,12 @@ @@ -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

@ -493,7 +493,14 @@ export namespace User { @@ -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
};
}

51
src/lib/appManagers/appChatsManager.ts

@ -3,7 +3,7 @@ import apiManager from '../mtproto/mtprotoworker'; @@ -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 { @@ -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);
}
}

9
src/lib/appManagers/appDocsManager.ts

@ -4,7 +4,7 @@ import { MOUNT_CLASS_TO } from '../mtproto/mtproto_config'; @@ -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 { @@ -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 { @@ -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) {

149
src/lib/appManagers/appMessagesManager.ts

@ -13,7 +13,7 @@ import { RichTextProcessor } from "../richtextprocessor"; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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;
}
});
}

4
src/lib/appManagers/appPhotosManager.ts

@ -5,7 +5,7 @@ import { bytesFromHex, getFileNameByLocation } from "../bin_utils"; @@ -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 { @@ -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);

4
src/lib/appManagers/appStateManager.ts

@ -96,13 +96,17 @@ export class AppStateManager extends EventListenerBase<{ @@ -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]) {

83
src/lib/appManagers/appUsersManager.ts

@ -1,12 +1,12 @@ @@ -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"; @@ -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 { @@ -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 { @@ -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});
}
}

10
src/lib/storage.ts

@ -1,6 +1,6 @@ @@ -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 { @@ -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 {

15
src/lib/utils.ts

@ -580,4 +580,17 @@ export function splitStringByLength(str: string, maxLength: number) { @@ -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;

11
src/scripts/in/schema_additional_params.json

@ -211,4 +211,15 @@ @@ -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…
Cancel
Save