[breaking change] separate session and state db
This commit is contained in:
parent
705e9a3f10
commit
54ace14d23
@ -12,7 +12,7 @@ import type { AppInlineBotsManager } from "../../lib/appManagers/appInlineBotsMa
|
|||||||
import type { AppPhotosManager } from "../../lib/appManagers/appPhotosManager";
|
import type { AppPhotosManager } from "../../lib/appManagers/appPhotosManager";
|
||||||
import type { AppDocsManager, MyDocument } from "../../lib/appManagers/appDocsManager";
|
import type { AppDocsManager, MyDocument } from "../../lib/appManagers/appDocsManager";
|
||||||
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
|
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
|
||||||
import type sessionStorage from '../../lib/sessionStorage';
|
import type stateStorage from '../../lib/stateStorage';
|
||||||
import type Chat from "./chat";
|
import type Chat from "./chat";
|
||||||
import { CHAT_ANIMATION_GROUP } from "../../lib/appManagers/appImManager";
|
import { CHAT_ANIMATION_GROUP } from "../../lib/appManagers/appImManager";
|
||||||
import { getObjectKeysAndSort } from "../../helpers/object";
|
import { getObjectKeysAndSort } from "../../helpers/object";
|
||||||
@ -147,7 +147,14 @@ export default class ChatBubbles {
|
|||||||
[_ in MessageEntity['_']]: boolean
|
[_ in MessageEntity['_']]: boolean
|
||||||
}> = {};
|
}> = {};
|
||||||
|
|
||||||
constructor(private chat: Chat, private appMessagesManager: AppMessagesManager, private appStickersManager: AppStickersManager, private appUsersManager: AppUsersManager, private appInlineBotsManager: AppInlineBotsManager, private appPhotosManager: AppPhotosManager, private appDocsManager: AppDocsManager, private appPeersManager: AppPeersManager, private appChatsManager: AppChatsManager, private storage: typeof sessionStorage) {
|
constructor(private chat: Chat,
|
||||||
|
private appMessagesManager: AppMessagesManager,
|
||||||
|
private appStickersManager: AppStickersManager,
|
||||||
|
private appUsersManager: AppUsersManager,
|
||||||
|
private appInlineBotsManager: AppInlineBotsManager,
|
||||||
|
private appPhotosManager: AppPhotosManager,
|
||||||
|
private appPeersManager: AppPeersManager
|
||||||
|
) {
|
||||||
//this.chat.log.error('Bubbles construction');
|
//this.chat.log.error('Bubbles construction');
|
||||||
|
|
||||||
this.listenerSetter = new ListenerSetter();
|
this.listenerSetter = new ListenerSetter();
|
||||||
|
@ -21,7 +21,7 @@ import type { ApiManagerProxy } from "../../lib/mtproto/mtprotoworker";
|
|||||||
import type { AppDraftsManager } from "../../lib/appManagers/appDraftsManager";
|
import type { AppDraftsManager } from "../../lib/appManagers/appDraftsManager";
|
||||||
import type { AppEmojiManager } from "../../lib/appManagers/appEmojiManager";
|
import type { AppEmojiManager } from "../../lib/appManagers/appEmojiManager";
|
||||||
import type { ServerTimeManager } from "../../lib/mtproto/serverTimeManager";
|
import type { ServerTimeManager } from "../../lib/mtproto/serverTimeManager";
|
||||||
import type sessionStorage from '../../lib/sessionStorage';
|
import type stateStorage from '../../lib/stateStorage';
|
||||||
import EventListenerBase from "../../helpers/eventListenerBase";
|
import EventListenerBase from "../../helpers/eventListenerBase";
|
||||||
import { logger, LogTypes } from "../../lib/logger";
|
import { logger, LogTypes } from "../../lib/logger";
|
||||||
import rootScope from "../../lib/rootScope";
|
import rootScope from "../../lib/rootScope";
|
||||||
@ -82,7 +82,7 @@ export default class Chat extends EventListenerBase<{
|
|||||||
public apiManager: ApiManagerProxy,
|
public apiManager: ApiManagerProxy,
|
||||||
public appDraftsManager: AppDraftsManager,
|
public appDraftsManager: AppDraftsManager,
|
||||||
public serverTimeManager: ServerTimeManager,
|
public serverTimeManager: ServerTimeManager,
|
||||||
public storage: typeof sessionStorage,
|
public storage: typeof stateStorage,
|
||||||
public appNotificationsManager: AppNotificationsManager,
|
public appNotificationsManager: AppNotificationsManager,
|
||||||
public appEmojiManager: AppEmojiManager
|
public appEmojiManager: AppEmojiManager
|
||||||
) {
|
) {
|
||||||
@ -170,7 +170,7 @@ export default class Chat extends EventListenerBase<{
|
|||||||
this.initPeerId = peerId;
|
this.initPeerId = peerId;
|
||||||
|
|
||||||
this.topbar = new ChatTopbar(this, appSidebarRight, this.appMessagesManager, this.appPeersManager, this.appChatsManager, this.appNotificationsManager);
|
this.topbar = new ChatTopbar(this, appSidebarRight, this.appMessagesManager, this.appPeersManager, this.appChatsManager, this.appNotificationsManager);
|
||||||
this.bubbles = new ChatBubbles(this, this.appMessagesManager, this.appStickersManager, this.appUsersManager, this.appInlineBotsManager, this.appPhotosManager, this.appDocsManager, this.appPeersManager, this.appChatsManager, this.storage);
|
this.bubbles = new ChatBubbles(this, this.appMessagesManager, this.appStickersManager, this.appUsersManager, this.appInlineBotsManager, this.appPhotosManager, this.appPeersManager);
|
||||||
this.input = new ChatInput(this, this.appMessagesManager, this.appDocsManager, this.appChatsManager, this.appPeersManager, this.appWebPagesManager, this.appImManager, this.appDraftsManager, this.serverTimeManager, this.appNotificationsManager, this.appEmojiManager);
|
this.input = new ChatInput(this, this.appMessagesManager, this.appDocsManager, this.appChatsManager, this.appPeersManager, this.appWebPagesManager, this.appImManager, this.appDraftsManager, this.serverTimeManager, this.appNotificationsManager, this.appEmojiManager);
|
||||||
this.selection = new ChatSelection(this, this.bubbles, this.input, this.appMessagesManager);
|
this.selection = new ChatSelection(this, this.bubbles, this.input, this.appMessagesManager);
|
||||||
this.contextMenu = new ChatContextMenu(this.bubbles.bubblesContainer, this, this.appMessagesManager, this.appChatsManager, this.appPeersManager, this.appPollsManager);
|
this.contextMenu = new ChatContextMenu(this.bubbles.bubblesContainer, this, this.appMessagesManager, this.appChatsManager, this.appPeersManager, this.appPollsManager);
|
||||||
|
@ -225,7 +225,7 @@ export default class ChatContextMenu {
|
|||||||
withSelection: true
|
withSelection: true
|
||||||
}, {
|
}, {
|
||||||
icon: 'link',
|
icon: 'link',
|
||||||
text: 'CopyLink',
|
text: 'MessageContext.CopyMessageLink1',
|
||||||
onClick: this.onCopyLinkClick,
|
onClick: this.onCopyLinkClick,
|
||||||
verify: () => this.appPeersManager.isChannel(this.peerId) && !this.message.pFlags.is_outgoing
|
verify: () => this.appPeersManager.isChannel(this.peerId) && !this.message.pFlags.is_outgoing
|
||||||
}, {
|
}, {
|
||||||
|
14
src/components/sidebarLeft/tabs/addContact.ts
Normal file
14
src/components/sidebarLeft/tabs/addContact.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { SliderSuperTab } from "../../slider";
|
||||||
|
|
||||||
|
export default class AppAddContactTab extends SliderSuperTab {
|
||||||
|
protected init() {
|
||||||
|
this.container.classList.add('add-contact-container');
|
||||||
|
this.setTitle('AddContactTitle');
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* https://github.com/morethanwords/tweb
|
|
||||||
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
|
||||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { IDBStore } from "../lib/idb";
|
|
||||||
import Modes from "./modes";
|
|
||||||
|
|
||||||
export type DatabaseStoreName = 'session' | 'stickerSets' | 'users' | 'chats' | 'messages' | 'dialogs';
|
|
||||||
export type DatabaseStore = Omit<IDBStore, 'name'> & {name: DatabaseStoreName};
|
|
||||||
const Database = {
|
|
||||||
name: 'tweb' + (Modes.test ? '_test' : ''),
|
|
||||||
version: 7,
|
|
||||||
stores: [{
|
|
||||||
name: 'session'
|
|
||||||
}, {
|
|
||||||
name: 'stickerSets'
|
|
||||||
}, {
|
|
||||||
name: 'users'
|
|
||||||
}, {
|
|
||||||
name: 'chats'
|
|
||||||
}, {
|
|
||||||
name: 'dialogs'
|
|
||||||
}, {
|
|
||||||
name: 'messages'
|
|
||||||
}] as DatabaseStore[],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Database;
|
|
14
src/config/databases/index.ts
Normal file
14
src/config/databases/index.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { IDBStore } from "../../lib/idb";
|
||||||
|
|
||||||
|
export type DatabaseStore<StoreName extends string> = Omit<IDBStore, 'name'> & {name: StoreName};
|
||||||
|
export type Database<StoreName extends string> = {
|
||||||
|
name: string,
|
||||||
|
version: number,
|
||||||
|
stores: DatabaseStore<StoreName>[]
|
||||||
|
};
|
17
src/config/databases/session.ts
Normal file
17
src/config/databases/session.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Database } from '.';
|
||||||
|
|
||||||
|
const DATABASE_SESSION: Database<'session'> = {
|
||||||
|
name: 'telegram',
|
||||||
|
version: 1,
|
||||||
|
stores: [{
|
||||||
|
name: 'session'
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DATABASE_SESSION;
|
27
src/config/databases/state.ts
Normal file
27
src/config/databases/state.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Database } from '.';
|
||||||
|
|
||||||
|
const DATABASE_STATE: Database<'session' | 'stickerSets' | 'users' | 'chats' | 'messages' | 'dialogs'> = {
|
||||||
|
name: 'tweb',
|
||||||
|
version: 7,
|
||||||
|
stores: [{
|
||||||
|
name: 'session'
|
||||||
|
}, {
|
||||||
|
name: 'stickerSets'
|
||||||
|
}, {
|
||||||
|
name: 'users'
|
||||||
|
}, {
|
||||||
|
name: 'chats'
|
||||||
|
}, {
|
||||||
|
name: 'dialogs'
|
||||||
|
}, {
|
||||||
|
name: 'messages'
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DATABASE_STATE;
|
@ -437,6 +437,7 @@ const lang = {
|
|||||||
"NoResult": "No results",
|
"NoResult": "No results",
|
||||||
"Updating": "Updating...",
|
"Updating": "Updating...",
|
||||||
"Emoji": "Emoji",
|
"Emoji": "Emoji",
|
||||||
|
"AddContactTitle": "Add Contact",
|
||||||
|
|
||||||
// * macos
|
// * macos
|
||||||
"AccountSettings.Filters": "Chat Folders",
|
"AccountSettings.Filters": "Chat Folders",
|
||||||
@ -664,6 +665,7 @@ const lang = {
|
|||||||
"Message.Context.Select": "Select",
|
"Message.Context.Select": "Select",
|
||||||
"Message.Context.Pin": "Pin",
|
"Message.Context.Pin": "Pin",
|
||||||
"Message.Context.Unpin": "Unpin",
|
"Message.Context.Unpin": "Unpin",
|
||||||
|
"MessageContext.CopyMessageLink1": "Copy Message Link",
|
||||||
"NewPoll.Anonymous": "Anonymous Voting",
|
"NewPoll.Anonymous": "Anonymous Voting",
|
||||||
"NewPoll.Explanation.Placeholder": "Add a Comment (Optional)",
|
"NewPoll.Explanation.Placeholder": "Add a Comment (Optional)",
|
||||||
"NewPoll.OptionsAddOption": "Add an Option",
|
"NewPoll.OptionsAddOption": "Add an Option",
|
||||||
|
@ -21,7 +21,7 @@ import { tsNow } from "../../helpers/date";
|
|||||||
import { deepEqual } from "../../helpers/object";
|
import { deepEqual } from "../../helpers/object";
|
||||||
import { isObject } from "../mtproto/bin_utils";
|
import { isObject } from "../mtproto/bin_utils";
|
||||||
import { MOUNT_CLASS_TO } from "../../config/debug";
|
import { MOUNT_CLASS_TO } from "../../config/debug";
|
||||||
import sessionStorage from "../sessionStorage";
|
import stateStorage from "../stateStorage";
|
||||||
|
|
||||||
export type MyDraftMessage = DraftMessage.draftMessage;
|
export type MyDraftMessage = DraftMessage.draftMessage;
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ export class AppDraftsManager {
|
|||||||
private getAllDraftPromise: Promise<void> = null;
|
private getAllDraftPromise: Promise<void> = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
sessionStorage.get('drafts').then(drafts => {
|
stateStorage.get('drafts').then(drafts => {
|
||||||
this.drafts = drafts || {};
|
this.drafts = drafts || {};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ export class AppDraftsManager {
|
|||||||
delete this.drafts[key];
|
delete this.drafts[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionStorage.set({
|
stateStorage.set({
|
||||||
drafts: this.drafts
|
drafts: this.drafts
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import I18n from "../langPack";
|
|||||||
import { isObject } from "../mtproto/bin_utils";
|
import { isObject } from "../mtproto/bin_utils";
|
||||||
import apiManager from "../mtproto/mtprotoworker";
|
import apiManager from "../mtproto/mtprotoworker";
|
||||||
import SearchIndex from "../searchIndex";
|
import SearchIndex from "../searchIndex";
|
||||||
import sessionStorage from "../sessionStorage";
|
import stateStorage from "../stateStorage";
|
||||||
import appStateManager from "./appStateManager";
|
import appStateManager from "./appStateManager";
|
||||||
|
|
||||||
type EmojiLangPack = {
|
type EmojiLangPack = {
|
||||||
@ -45,7 +45,7 @@ export class AppEmojiManager {
|
|||||||
private getRecentEmojisPromise: Promise<AppEmojiManager['recent']>;
|
private getRecentEmojisPromise: Promise<AppEmojiManager['recent']>;
|
||||||
|
|
||||||
/* public getPopularEmoji() {
|
/* public getPopularEmoji() {
|
||||||
return sessionStorage.get('emojis_popular').then(popEmojis => {
|
return stateStorage.get('emojis_popular').then(popEmojis => {
|
||||||
var result = []
|
var result = []
|
||||||
if (popEmojis && popEmojis.length) {
|
if (popEmojis && popEmojis.length) {
|
||||||
for (var i = 0, len = popEmojis.length; i < len; i++) {
|
for (var i = 0, len = popEmojis.length; i < len; i++) {
|
||||||
@ -55,7 +55,7 @@ export class AppEmojiManager {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessionStorage.get('emojis_recent').then(recentEmojis => {
|
return stateStorage.get('emojis_recent').then(recentEmojis => {
|
||||||
recentEmojis = recentEmojis || popular || []
|
recentEmojis = recentEmojis || popular || []
|
||||||
var shortcut
|
var shortcut
|
||||||
var code
|
var code
|
||||||
@ -111,7 +111,7 @@ export class AppEmojiManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const storageKey: any = 'emojiKeywords_' + langCode;
|
const storageKey: any = 'emojiKeywords_' + langCode;
|
||||||
return this.getKeywordsPromises[langCode] = sessionStorage.get(storageKey).then((pack: EmojiLangPack) => {
|
return this.getKeywordsPromises[langCode] = stateStorage.get(storageKey).then((pack: EmojiLangPack) => {
|
||||||
if(!isObject(pack)) {
|
if(!isObject(pack)) {
|
||||||
pack = {} as any;
|
pack = {} as any;
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ export class AppEmojiManager {
|
|||||||
packKeywords[keyword] = emoticons;
|
packKeywords[keyword] = emoticons;
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionStorage.set({
|
stateStorage.set({
|
||||||
[storageKey]: pack
|
[storageKey]: pack
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ import lottieLoader from '../lottieLoader';
|
|||||||
import useHeavyAnimationCheck, { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
import useHeavyAnimationCheck, { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
||||||
import appDraftsManager from './appDraftsManager';
|
import appDraftsManager from './appDraftsManager';
|
||||||
import serverTimeManager from '../mtproto/serverTimeManager';
|
import serverTimeManager from '../mtproto/serverTimeManager';
|
||||||
import sessionStorage from '../sessionStorage';
|
import stateStorage from '../stateStorage';
|
||||||
import appDownloadManager from './appDownloadManager';
|
import appDownloadManager from './appDownloadManager';
|
||||||
import { AppStateManager } from './appStateManager';
|
import { AppStateManager } from './appStateManager';
|
||||||
import { MOUNT_CLASS_TO } from '../../config/debug';
|
import { MOUNT_CLASS_TO } from '../../config/debug';
|
||||||
@ -215,8 +215,8 @@ export class AppImManager {
|
|||||||
popup.show();
|
popup.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
sessionStorage.get('chatPositions').then((c) => {
|
stateStorage.get('chatPositions').then((c) => {
|
||||||
sessionStorage.setToCache('chatPositions', c || {});
|
stateStorage.setToCache('chatPositions', c || {});
|
||||||
});
|
});
|
||||||
|
|
||||||
(window as any).showMaskedAlert = (element: HTMLAnchorElement, e: Event) => {
|
(window as any).showMaskedAlert = (element: HTMLAnchorElement, e: Event) => {
|
||||||
@ -385,7 +385,7 @@ export class AppImManager {
|
|||||||
|
|
||||||
const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');
|
const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');
|
||||||
|
|
||||||
const chatPositions = sessionStorage.getFromCache('chatPositions');
|
const chatPositions = stateStorage.getFromCache('chatPositions');
|
||||||
if(!(chat.bubbles.scrollable.getDistanceToEnd() <= 16 && chat.bubbles.scrollable.loadedAll.bottom) && Object.keys(chat.bubbles.bubbles).length) {
|
if(!(chat.bubbles.scrollable.getDistanceToEnd() <= 16 && chat.bubbles.scrollable.loadedAll.bottom) && Object.keys(chat.bubbles.bubbles).length) {
|
||||||
const position = {
|
const position = {
|
||||||
mids: getObjectKeysAndSort(chat.bubbles.bubbles, 'desc'),
|
mids: getObjectKeysAndSort(chat.bubbles.bubbles, 'desc'),
|
||||||
@ -401,7 +401,7 @@ export class AppImManager {
|
|||||||
this.log('deleted chat position');
|
this.log('deleted chat position');
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionStorage.set({chatPositions}, true);
|
stateStorage.set({chatPositions}, true);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,7 +411,7 @@ export class AppImManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');
|
const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');
|
||||||
const cache = sessionStorage.getFromCache('chatPositions');
|
const cache = stateStorage.getFromCache('chatPositions');
|
||||||
return cache && cache[key];
|
return cache && cache[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -820,7 +820,7 @@ export class AppImManager {
|
|||||||
apiManager,
|
apiManager,
|
||||||
appDraftsManager,
|
appDraftsManager,
|
||||||
serverTimeManager,
|
serverTimeManager,
|
||||||
sessionStorage,
|
stateStorage,
|
||||||
appNotificationsManager,
|
appNotificationsManager,
|
||||||
appEmojiManager
|
appEmojiManager
|
||||||
);
|
);
|
||||||
|
@ -20,7 +20,7 @@ import { InputNotifyPeer, InputPeerNotifySettings, NotifyPeer, PeerNotifySetting
|
|||||||
import I18n from "../langPack";
|
import I18n from "../langPack";
|
||||||
import apiManager from "../mtproto/mtprotoworker";
|
import apiManager from "../mtproto/mtprotoworker";
|
||||||
import rootScope from "../rootScope";
|
import rootScope from "../rootScope";
|
||||||
import sessionStorage from "../sessionStorage";
|
import stateStorage from "../stateStorage";
|
||||||
import apiUpdatesManager from "./apiUpdatesManager";
|
import apiUpdatesManager from "./apiUpdatesManager";
|
||||||
import appPeersManager from "./appPeersManager";
|
import appPeersManager from "./appPeersManager";
|
||||||
import appStateManager from "./appStateManager";
|
import appStateManager from "./appStateManager";
|
||||||
@ -268,7 +268,7 @@ export class AppNotificationsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public updateLocalSettings = () => {
|
public updateLocalSettings = () => {
|
||||||
Promise.all(['notify_nodesktop', 'notify_volume', 'notify_novibrate', 'notify_nopreview', 'notify_nopush'].map(k => sessionStorage.get(k as any)))
|
Promise.all(['notify_nodesktop', 'notify_volume', 'notify_novibrate', 'notify_nopreview', 'notify_nopush'].map(k => stateStorage.get(k as any)))
|
||||||
.then((updSettings) => {
|
.then((updSettings) => {
|
||||||
this.settings.nodesktop = updSettings[0];
|
this.settings.nodesktop = updSettings[0];
|
||||||
this.settings.volume = updSettings[1] === undefined ? 0.5 : updSettings[1];
|
this.settings.volume = updSettings[1] === undefined ? 0.5 : updSettings[1];
|
||||||
|
@ -12,7 +12,7 @@ import type FiltersStorage from '../storages/filters';
|
|||||||
import type DialogsStorage from '../storages/dialogs';
|
import type DialogsStorage from '../storages/dialogs';
|
||||||
import EventListenerBase from '../../helpers/eventListenerBase';
|
import EventListenerBase from '../../helpers/eventListenerBase';
|
||||||
import rootScope from '../rootScope';
|
import rootScope from '../rootScope';
|
||||||
import sessionStorage from '../sessionStorage';
|
import stateStorage from '../stateStorage';
|
||||||
import { logger } from '../logger';
|
import { logger } from '../logger';
|
||||||
import { copy, setDeepProperty, validateInitObject } from '../../helpers/object';
|
import { copy, setDeepProperty, validateInitObject } from '../../helpers/object';
|
||||||
import App from '../../config/app';
|
import App from '../../config/app';
|
||||||
@ -20,6 +20,8 @@ import DEBUG, { MOUNT_CLASS_TO } from '../../config/debug';
|
|||||||
import AppStorage from '../storage';
|
import AppStorage from '../storage';
|
||||||
import { Chat } from '../../layer';
|
import { Chat } from '../../layer';
|
||||||
import { isMobile } from '../../helpers/userAgent';
|
import { isMobile } from '../../helpers/userAgent';
|
||||||
|
import DATABASE_STATE from '../../config/databases/state';
|
||||||
|
import sessionStorage from '../sessionStorage';
|
||||||
|
|
||||||
const REFRESH_EVERY = 24 * 60 * 60 * 1000; // 1 day
|
const REFRESH_EVERY = 24 * 60 * 60 * 1000; // 1 day
|
||||||
const REFRESH_EVERY_WEEK = 24 * 60 * 60 * 1000 * 7; // 7 days
|
const REFRESH_EVERY_WEEK = 24 * 60 * 60 * 1000 * 7; // 7 days
|
||||||
@ -174,22 +176,14 @@ export class AppStateManager extends EventListenerBase<{
|
|||||||
private singlePeerMap: Map<string, number> = new Map();
|
private singlePeerMap: Map<string, number> = new Map();
|
||||||
|
|
||||||
public storages = {
|
public storages = {
|
||||||
users: new AppStorage<Record<number, User>>({
|
users: new AppStorage<Record<number, User>, typeof DATABASE_STATE>(DATABASE_STATE, 'users'),
|
||||||
storeName: 'users'
|
chats: new AppStorage<Record<number, Chat>, typeof DATABASE_STATE>(DATABASE_STATE, 'chats'),
|
||||||
}),
|
dialogs: new AppStorage<Record<number, Dialog>, typeof DATABASE_STATE>(DATABASE_STATE, 'dialogs')
|
||||||
|
|
||||||
chats: new AppStorage<Record<number, Chat>>({
|
|
||||||
storeName: 'chats'
|
|
||||||
}),
|
|
||||||
|
|
||||||
dialogs: new AppStorage<Record<number, Dialog>>({
|
|
||||||
storeName: 'dialogs'
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public storagesResults: {[key in keyof AppStateManager['storages']]: any[]} = {} as any;
|
public storagesResults: {[key in keyof AppStateManager['storages']]: any[]} = {} as any;
|
||||||
|
|
||||||
public storage = sessionStorage;
|
public storage = stateStorage;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -201,11 +195,10 @@ export class AppStateManager extends EventListenerBase<{
|
|||||||
console.time('load state');
|
console.time('load state');
|
||||||
this.loaded = new Promise((resolve) => {
|
this.loaded = new Promise((resolve) => {
|
||||||
const storagesKeys = Object.keys(this.storages) as Array<keyof AppStateManager['storages']>;
|
const storagesKeys = Object.keys(this.storages) as Array<keyof AppStateManager['storages']>;
|
||||||
const storagesPromises = storagesKeys.map(key => this.storages[key].getAll());
|
const storagesPromises: Promise<any>[] = storagesKeys.map(key => this.storages[key].getAll());
|
||||||
|
|
||||||
const promises = ALL_KEYS
|
const promises: Promise<any>[] = ALL_KEYS.map(key => stateStorage.get(key))
|
||||||
.concat('user_auth' as any)
|
.concat(sessionStorage.get('user_auth'))
|
||||||
.map(key => sessionStorage.get(key))
|
|
||||||
.concat(storagesPromises);
|
.concat(storagesPromises);
|
||||||
|
|
||||||
Promise.all(promises).then((arr) => {
|
Promise.all(promises).then((arr) => {
|
||||||
@ -257,16 +250,40 @@ export class AppStateManager extends EventListenerBase<{
|
|||||||
arr.splice(0, ALL_KEYS.length);
|
arr.splice(0, ALL_KEYS.length);
|
||||||
|
|
||||||
// * Read auth
|
// * Read auth
|
||||||
const auth: UserAuth = arr.shift() as any;
|
let auth = arr.shift() as UserAuth | number;
|
||||||
|
if(!auth) { // try to read Webogram's session from localStorage
|
||||||
|
try {
|
||||||
|
const keys = Object.keys(localStorage);
|
||||||
|
for(let i = 0; i < keys.length; ++i) {
|
||||||
|
const key = keys[i];
|
||||||
|
let value: any;
|
||||||
|
try {
|
||||||
|
value = localStorage.getItem(key);
|
||||||
|
value = JSON.parse(value);
|
||||||
|
} catch(err) {
|
||||||
|
//console.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionStorage.set({
|
||||||
|
[key as any]: value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auth = sessionStorage.getFromCache('user_auth');
|
||||||
|
} catch(err) {
|
||||||
|
this.log.error('localStorage import error', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(auth) {
|
if(auth) {
|
||||||
// ! Warning ! DON'T delete this
|
// ! Warning ! DON'T delete this
|
||||||
state.authState = {_: 'authStateSignedIn'};
|
state.authState = {_: 'authStateSignedIn'};
|
||||||
rootScope.broadcast('user_auth', typeof(auth) !== 'number' ? (auth as any).id : auth); // * support old version
|
rootScope.broadcast('user_auth', typeof(auth) === 'number' ? {dcID: 0, id: auth} : auth); // * support old version
|
||||||
}
|
}
|
||||||
|
|
||||||
// * Read storages
|
// * Read storages
|
||||||
for(let i = 0, length = storagesKeys.length; i < length; ++i) {
|
for(let i = 0, length = storagesKeys.length; i < length; ++i) {
|
||||||
this.storagesResults[storagesKeys[i]] = arr[i];
|
this.storagesResults[storagesKeys[i]] = arr[i] as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
arr.splice(0, storagesKeys.length);
|
arr.splice(0, storagesKeys.length);
|
||||||
@ -362,7 +379,7 @@ export class AppStateManager extends EventListenerBase<{
|
|||||||
this.state[key] = value;
|
this.state[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionStorage.set({
|
this.storage.set({
|
||||||
[key]: value
|
[key]: value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,12 @@ import appDocsManager from './appDocsManager';
|
|||||||
import AppStorage from '../storage';
|
import AppStorage from '../storage';
|
||||||
import { MOUNT_CLASS_TO } from '../../config/debug';
|
import { MOUNT_CLASS_TO } from '../../config/debug';
|
||||||
import { forEachReverse } from '../../helpers/array';
|
import { forEachReverse } from '../../helpers/array';
|
||||||
|
import DATABASE_STATE from '../../config/databases/state';
|
||||||
|
|
||||||
const CACHE_TIME = 3600e3;
|
const CACHE_TIME = 3600e3;
|
||||||
|
|
||||||
export class AppStickersManager {
|
export class AppStickersManager {
|
||||||
private storage = new AppStorage<Record<string, MessagesStickerSet>>({
|
private storage = new AppStorage<Record<string, MessagesStickerSet>, typeof DATABASE_STATE>(DATABASE_STATE, 'stickerSets');
|
||||||
storeName: 'stickerSets'
|
|
||||||
});
|
|
||||||
|
|
||||||
private getStickerSetPromises: {[setId: string]: Promise<MessagesStickerSet>} = {};
|
private getStickerSetPromises: {[setId: string]: Promise<MessagesStickerSet>} = {};
|
||||||
private getStickersByEmoticonsPromises: {[emoticon: string]: Promise<Document[]>} = {};
|
private getStickersByEmoticonsPromises: {[emoticon: string]: Promise<Document[]>} = {};
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Database from '../config/database';
|
import { Database } from '../config/databases';
|
||||||
|
import Modes from '../config/modes';
|
||||||
import { blobConstruct } from '../helpers/blob';
|
import { blobConstruct } from '../helpers/blob';
|
||||||
import { safeAssign } from '../helpers/object';
|
import { safeAssign } from '../helpers/object';
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
@ -37,27 +38,31 @@ export type IDBOptions = {
|
|||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
|
|
||||||
export default class IDBStorage {
|
export default class IDBStorage<T extends Database<any>> {
|
||||||
private static STORAGES: IDBStorage[] = [];
|
private static STORAGES: IDBStorage<Database<any>>[] = [];
|
||||||
private openDbPromise: Promise<IDBDatabase>;
|
private openDbPromise: Promise<IDBDatabase>;
|
||||||
private db: IDBDatabase;
|
private db: IDBDatabase;
|
||||||
private storageIsAvailable = true;
|
private storageIsAvailable = true;
|
||||||
|
|
||||||
private log: ReturnType<typeof logger>;
|
private log: ReturnType<typeof logger>;
|
||||||
|
|
||||||
private name: string = Database.name;
|
private name: string;
|
||||||
private version: number = Database.version;
|
private version: number;
|
||||||
private stores: IDBStore[] = Database.stores;
|
private stores: IDBStore[];
|
||||||
|
|
||||||
private storeName: string;
|
private storeName: string;
|
||||||
|
|
||||||
constructor(options: IDBOptions) {
|
constructor(db: T, storeName: typeof db['stores'][0]['name']) {
|
||||||
safeAssign(this, options);
|
safeAssign(this, db);
|
||||||
|
this.storeName = storeName;
|
||||||
|
|
||||||
this.log = logger('IDB-' + this.storeName);
|
this.log = logger('IDB-' + this.storeName);
|
||||||
|
|
||||||
this.openDatabase(true);
|
this.openDatabase(true);
|
||||||
|
|
||||||
|
if(Modes.test) {
|
||||||
|
this.name += '_test';
|
||||||
|
}
|
||||||
|
|
||||||
IDBStorage.STORAGES.push(this);
|
IDBStorage.STORAGES.push(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,17 +79,23 @@ export default class IDBStorage {
|
|||||||
public static deleteDatabase() {
|
public static deleteDatabase() {
|
||||||
this.closeDatabases();
|
this.closeDatabases();
|
||||||
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
const storages = this.STORAGES;
|
||||||
const deleteRequest = indexedDB.deleteDatabase(Database.name);
|
const dbNames = Array.from(new Set(storages.map(storage => storage.name)));
|
||||||
|
const promises = dbNames.map(dbName => {
|
||||||
deleteRequest.onerror = () => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
reject();
|
const deleteRequest = indexedDB.deleteDatabase(dbName);
|
||||||
};
|
|
||||||
|
deleteRequest.onerror = () => {
|
||||||
deleteRequest.onsuccess = () => {
|
reject();
|
||||||
resolve();
|
};
|
||||||
};
|
|
||||||
|
deleteRequest.onsuccess = () => {
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isAvailable() {
|
public isAvailable() {
|
||||||
|
@ -11,7 +11,7 @@ import type lang from "../lang";
|
|||||||
import type langSign from "../langSign";
|
import type langSign from "../langSign";
|
||||||
import { LangPackDifference, LangPackString } from "../layer";
|
import { LangPackDifference, LangPackString } from "../layer";
|
||||||
import apiManager from "./mtproto/mtprotoworker";
|
import apiManager from "./mtproto/mtprotoworker";
|
||||||
import sessionStorage from "./sessionStorage";
|
import stateStorage from "./stateStorage";
|
||||||
import App from "../config/app";
|
import App from "../config/app";
|
||||||
import rootScope from "./rootScope";
|
import rootScope from "./rootScope";
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ namespace I18n {
|
|||||||
export function getCacheLangPack(): Promise<LangPackDifference> {
|
export function getCacheLangPack(): Promise<LangPackDifference> {
|
||||||
if(cacheLangPackPromise) return cacheLangPackPromise;
|
if(cacheLangPackPromise) return cacheLangPackPromise;
|
||||||
return cacheLangPackPromise = Promise.all([
|
return cacheLangPackPromise = Promise.all([
|
||||||
sessionStorage.get('langPack') as Promise<LangPackDifference>,
|
stateStorage.get('langPack') as Promise<LangPackDifference>,
|
||||||
polyfillPromise
|
polyfillPromise
|
||||||
]).then(([langPack]) => {
|
]).then(([langPack]) => {
|
||||||
if(!langPack/* || true */) {
|
if(!langPack/* || true */) {
|
||||||
@ -177,7 +177,7 @@ namespace I18n {
|
|||||||
export function saveLangPack(langPack: LangPackDifference) {
|
export function saveLangPack(langPack: LangPackDifference) {
|
||||||
langPack.appVersion = App.langPackVersion;
|
langPack.appVersion = App.langPackVersion;
|
||||||
|
|
||||||
return sessionStorage.set({langPack}).then(() => {
|
return stateStorage.set({langPack}).then(() => {
|
||||||
applyLangPack(langPack);
|
applyLangPack(langPack);
|
||||||
return langPack;
|
return langPack;
|
||||||
});
|
});
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { UserAuth } from './mtproto_config';
|
||||||
import sessionStorage from '../sessionStorage';
|
import sessionStorage from '../sessionStorage';
|
||||||
|
|
||||||
import MTPNetworker, { MTMessage } from './networker';
|
import MTPNetworker, { MTMessage } from './networker';
|
||||||
import { isObject } from './bin_utils';
|
import { isObject } from './bin_utils';
|
||||||
import networkerFactory from './networkerFactory';
|
import networkerFactory from './networkerFactory';
|
||||||
@ -104,17 +104,39 @@ export class ApiManager {
|
|||||||
//telegramMeWebService.setAuthorized(this.telegramMeNotified);
|
//telegramMeWebService.setAuthorized(this.telegramMeNotified);
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
public async getBaseDcId() {
|
||||||
|
if(this.baseDcId) {
|
||||||
|
return this.baseDcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseDcId = await sessionStorage.get('dc');
|
||||||
|
if(!this.baseDcId) {
|
||||||
|
if(!baseDcId) {
|
||||||
|
this.setBaseDcId(App.baseDcId);
|
||||||
|
} else {
|
||||||
|
this.baseDcId = baseDcId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.baseDcId;
|
||||||
|
}
|
||||||
|
|
||||||
// mtpSetUserAuth
|
// mtpSetUserAuth
|
||||||
public setUserAuth(userId: number) {
|
public async setUserAuth(userAuth: UserAuth) {
|
||||||
|
if(!userAuth.dcID) {
|
||||||
|
const baseDcId = await this.getBaseDcId();
|
||||||
|
userAuth.dcID = baseDcId;
|
||||||
|
}
|
||||||
|
|
||||||
sessionStorage.set({
|
sessionStorage.set({
|
||||||
user_auth: userId
|
user_auth: userAuth
|
||||||
});
|
});
|
||||||
|
|
||||||
//this.telegramMeNotify(true);
|
//this.telegramMeNotify(true);
|
||||||
|
|
||||||
/// #if !MTPROTO_WORKER
|
/// #if !MTPROTO_WORKER
|
||||||
rootScope.broadcast('user_auth', userId);
|
rootScope.broadcast('user_auth', userAuth);
|
||||||
/// #endif
|
/// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,8 +451,8 @@ export class ApiManager {
|
|||||||
if(dcId = (options.dcId || this.baseDcId)) {
|
if(dcId = (options.dcId || this.baseDcId)) {
|
||||||
this.getNetworker(dcId, options).then(performRequest, rejectPromise);
|
this.getNetworker(dcId, options).then(performRequest, rejectPromise);
|
||||||
} else {
|
} else {
|
||||||
sessionStorage.get('dc').then((baseDcId) => {
|
this.getBaseDcId().then(baseDcId => {
|
||||||
this.getNetworker(this.baseDcId = dcId = baseDcId || App.baseDcId, options).then(performRequest, rejectPromise);
|
this.getNetworker(dcId = baseDcId, options).then(performRequest, rejectPromise);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export type UserAuth = number;
|
/**
|
||||||
|
* Legacy Webogram's format, don't change dcID to camelCase.
|
||||||
|
*/
|
||||||
|
export type UserAuth = {dcID: number, id: number};
|
||||||
|
|
||||||
export const REPLIES_PEER_ID = 1271266957;
|
export const REPLIES_PEER_ID = 1271266957;
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type { LocalStorageProxyDeleteTask, LocalStorageProxySetTask } from '../storage';
|
||||||
|
import type { InvokeApiOptions } from '../../types';
|
||||||
|
import type { MethodDeclMap } from '../../layer';
|
||||||
import MTProtoWorker from 'worker-loader!./mtproto.worker';
|
import MTProtoWorker from 'worker-loader!./mtproto.worker';
|
||||||
//import './mtproto.worker';
|
//import './mtproto.worker';
|
||||||
import { isObject } from '../../helpers/object';
|
import { isObject } from '../../helpers/object';
|
||||||
import type { MethodDeclMap } from '../../layer';
|
|
||||||
import type { InvokeApiOptions } from '../../types';
|
|
||||||
import CryptoWorkerMethods from '../crypto/crypto_methods';
|
import CryptoWorkerMethods from '../crypto/crypto_methods';
|
||||||
import { logger } from '../logger';
|
import { logger } from '../logger';
|
||||||
import rootScope from '../rootScope';
|
import rootScope from '../rootScope';
|
||||||
@ -93,6 +94,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
|||||||
|
|
||||||
this.addTaskListener('clear', () => {
|
this.addTaskListener('clear', () => {
|
||||||
const promise = IDBStorage.deleteDatabase();
|
const promise = IDBStorage.deleteDatabase();
|
||||||
|
localStorage.clear(); // * clear legacy Webogram's localStorage
|
||||||
promise.finally(() => {
|
promise.finally(() => {
|
||||||
location.reload();
|
location.reload();
|
||||||
});
|
});
|
||||||
@ -162,6 +164,21 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.addTaskListener('localStorageProxy', (task: LocalStorageProxySetTask | LocalStorageProxyDeleteTask) => {
|
||||||
|
const storageTask = task.payload;
|
||||||
|
if(storageTask.type === 'set') {
|
||||||
|
for(let i = 0, length = storageTask.keys.length; i < length; ++i) {
|
||||||
|
if(storageTask.values[i] !== undefined) {
|
||||||
|
localStorage.setItem(storageTask.keys[i], JSON.stringify(storageTask.values[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(storageTask.type === 'delete') {
|
||||||
|
for(let i = 0, length = storageTask.keys.length; i < length; ++i) {
|
||||||
|
localStorage.removeItem(storageTask.keys[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/// #if !MTPROTO_SW
|
/// #if !MTPROTO_SW
|
||||||
this.registerWorker();
|
this.registerWorker();
|
||||||
/// #endif
|
/// #endif
|
||||||
@ -457,7 +474,11 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
|||||||
return this.performTaskWorker('setQueueId', queueId);
|
return this.performTaskWorker('setQueueId', queueId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setUserAuth(userAuth: UserAuth) {
|
public setUserAuth(userAuth: UserAuth | number) {
|
||||||
|
if(typeof(userAuth) === 'number') {
|
||||||
|
userAuth = {dcID: 0, id: userAuth};
|
||||||
|
}
|
||||||
|
|
||||||
rootScope.broadcast('user_auth', userAuth);
|
rootScope.broadcast('user_auth', userAuth);
|
||||||
return this.performTaskWorker('setUserAuth', userAuth);
|
return this.performTaskWorker('setUserAuth', userAuth);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ export class TimeManager {
|
|||||||
private timeOffset = 0;
|
private timeOffset = 0;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
sessionStorage.get('server_time_offset').then((to: any) => {
|
sessionStorage.get('server_time_offset').then((to) => {
|
||||||
if(to) {
|
if(to) {
|
||||||
this.timeOffset = to;
|
this.timeOffset = to;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ export class RootScope extends EventListenerBase<{
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.on('user_auth', (e) => {
|
this.on('user_auth', (e) => {
|
||||||
this.myId = e;
|
this.myId = e.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('connection_status_change', (e) => {
|
this.on('connection_status_change', (e) => {
|
||||||
|
@ -4,33 +4,27 @@
|
|||||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ChatSavedPosition } from './appManagers/appImManager';
|
|
||||||
import type { State } from './appManagers/appStateManager';
|
|
||||||
import type { AppDraftsManager } from './appManagers/appDraftsManager';
|
|
||||||
import type { AppInstance } from './mtproto/singleInstance';
|
import type { AppInstance } from './mtproto/singleInstance';
|
||||||
|
import type { UserAuth } from './mtproto/mtproto_config';
|
||||||
import { MOUNT_CLASS_TO } from '../config/debug';
|
import { MOUNT_CLASS_TO } from '../config/debug';
|
||||||
import { LangPackDifference } from '../layer';
|
|
||||||
import AppStorage from './storage';
|
import AppStorage from './storage';
|
||||||
|
import DATABASE_SESSION from '../config/databases/session';
|
||||||
|
|
||||||
const sessionStorage = new AppStorage<{
|
const sessionStorage = new AppStorage<{
|
||||||
dc: number,
|
dc: number,
|
||||||
user_auth: number,
|
user_auth: UserAuth,
|
||||||
dc1_auth_key: any,
|
dc1_auth_key: string,
|
||||||
dc2_auth_key: any,
|
dc2_auth_key: string,
|
||||||
dc3_auth_key: any,
|
dc3_auth_key: string,
|
||||||
dc4_auth_key: any,
|
dc4_auth_key: string,
|
||||||
dc5_auth_key: any,
|
dc5_auth_key: string,
|
||||||
max_seen_msg: number,
|
dc1_server_salt: string,
|
||||||
|
dc2_server_salt: string,
|
||||||
|
dc3_server_salt: string,
|
||||||
|
dc4_server_salt: string,
|
||||||
|
dc5_server_salt: string,
|
||||||
server_time_offset: number,
|
server_time_offset: number,
|
||||||
xt_instance: AppInstance,
|
xt_instance: AppInstance
|
||||||
|
}, typeof DATABASE_SESSION>(DATABASE_SESSION, 'session');
|
||||||
chatPositions: {
|
|
||||||
[peerId_threadId: string]: ChatSavedPosition
|
|
||||||
},
|
|
||||||
langPack: LangPackDifference,
|
|
||||||
drafts: AppDraftsManager['drafts']
|
|
||||||
} & State>({
|
|
||||||
storeName: 'session'
|
|
||||||
});
|
|
||||||
MOUNT_CLASS_TO.appStorage = sessionStorage;
|
MOUNT_CLASS_TO.appStorage = sessionStorage;
|
||||||
export default sessionStorage;
|
export default sessionStorage;
|
||||||
|
23
src/lib/stateStorage.ts
Normal file
23
src/lib/stateStorage.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* https://github.com/morethanwords/tweb
|
||||||
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
||||||
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { ChatSavedPosition } from './appManagers/appImManager';
|
||||||
|
import type { State } from './appManagers/appStateManager';
|
||||||
|
import type { AppDraftsManager } from './appManagers/appDraftsManager';
|
||||||
|
import { MOUNT_CLASS_TO } from '../config/debug';
|
||||||
|
import { LangPackDifference } from '../layer';
|
||||||
|
import AppStorage from './storage';
|
||||||
|
import DATABASE_STATE from '../config/databases/state';
|
||||||
|
|
||||||
|
const stateStorage = new AppStorage<{
|
||||||
|
chatPositions: {
|
||||||
|
[peerId_threadId: string]: ChatSavedPosition
|
||||||
|
},
|
||||||
|
langPack: LangPackDifference,
|
||||||
|
drafts: AppDraftsManager['drafts']
|
||||||
|
} & State, typeof DATABASE_STATE>(DATABASE_STATE, 'session');
|
||||||
|
MOUNT_CLASS_TO.stateStorage = stateStorage;
|
||||||
|
export default stateStorage;
|
@ -9,16 +9,35 @@
|
|||||||
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
* https://github.com/zhukov/webogram/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DatabaseStore, DatabaseStoreName } from "../config/database";
|
import { Database } from "../config/databases";
|
||||||
|
import DATABASE_SESSION from "../config/databases/session";
|
||||||
import { CancellablePromise, deferredPromise } from "../helpers/cancellablePromise";
|
import { CancellablePromise, deferredPromise } from "../helpers/cancellablePromise";
|
||||||
import { throttle } from "../helpers/schedulers";
|
import { throttle } from "../helpers/schedulers";
|
||||||
import IDBStorage, { IDBOptions } from "./idb";
|
import { WorkerTaskTemplate } from "../types";
|
||||||
|
import IDBStorage from "./idb";
|
||||||
|
|
||||||
function noop() {}
|
function noop() {}
|
||||||
|
|
||||||
export default class AppStorage<Storage extends Record<string, any>/* Storage extends {[name: string]: any} *//* Storage extends Record<string, any> */> {
|
export interface LocalStorageProxySetTask extends WorkerTaskTemplate {
|
||||||
private static STORAGES: AppStorage<any>[] = [];
|
type: 'localStorageProxy',
|
||||||
private storage: IDBStorage;//new CacheStorageController('session');
|
payload: {
|
||||||
|
type: 'set',
|
||||||
|
keys: string[],
|
||||||
|
values: any[]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface LocalStorageProxyDeleteTask extends WorkerTaskTemplate {
|
||||||
|
type: 'localStorageProxy',
|
||||||
|
payload: {
|
||||||
|
type: 'delete',
|
||||||
|
keys: string[]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class AppStorage<Storage extends Record<string, any>, T extends Database<any>/* Storage extends {[name: string]: any} *//* Storage extends Record<string, any> */> {
|
||||||
|
private static STORAGES: AppStorage<any, Database<any>>[] = [];
|
||||||
|
private storage: IDBStorage<T>;//new CacheStorageController('session');
|
||||||
|
|
||||||
//private cache: Partial<{[key: string]: Storage[typeof key]}> = {};
|
//private cache: Partial<{[key: string]: Storage[typeof key]}> = {};
|
||||||
private cache: Partial<Storage> = {};
|
private cache: Partial<Storage> = {};
|
||||||
@ -35,8 +54,8 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
|||||||
private deleteThrottled: () => void;
|
private deleteThrottled: () => void;
|
||||||
private deleteDeferred = deferredPromise<void>();
|
private deleteDeferred = deferredPromise<void>();
|
||||||
|
|
||||||
constructor(storageOptions: Omit<IDBOptions, 'storeName' | 'stores'> & {stores?: DatabaseStore[], storeName: DatabaseStoreName}) {
|
constructor(private db: T, storeName: typeof db['stores'][number]['name']) {
|
||||||
this.storage = new IDBStorage(storageOptions);
|
this.storage = new IDBStorage<T>(db, storeName);
|
||||||
|
|
||||||
AppStorage.STORAGES.push(this);
|
AppStorage.STORAGES.push(this);
|
||||||
|
|
||||||
@ -53,7 +72,20 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
|||||||
//console.log('setItem: will set', key/* , value */);
|
//console.log('setItem: will set', key/* , value */);
|
||||||
//await this.cacheStorage.delete(key); // * try to prevent memory leak in Chrome leading to 'Unexpected internal error.'
|
//await this.cacheStorage.delete(key); // * try to prevent memory leak in Chrome leading to 'Unexpected internal error.'
|
||||||
//await this.storage.save(key, new Response(value, {headers: {'Content-Type': 'application/json'}}));
|
//await this.storage.save(key, new Response(value, {headers: {'Content-Type': 'application/json'}}));
|
||||||
await this.storage.save(keys, keys.map(key => this.cache[key]));
|
|
||||||
|
const values = keys.map(key => this.cache[key]);
|
||||||
|
if(db === DATABASE_SESSION && !('localStorage' in self)) { // * support legacy Webogram's localStorage
|
||||||
|
self.postMessage({
|
||||||
|
type: 'localStorageProxy',
|
||||||
|
payload: {
|
||||||
|
type: 'set',
|
||||||
|
keys,
|
||||||
|
values
|
||||||
|
}
|
||||||
|
} as LocalStorageProxySetTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.storage.save(keys, values);
|
||||||
//console.log('setItem: have set', key/* , value */);
|
//console.log('setItem: have set', key/* , value */);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
//this.useCS = false;
|
//this.useCS = false;
|
||||||
@ -78,6 +110,16 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
|||||||
set.clear();
|
set.clear();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if(db === DATABASE_SESSION && !('localStorage' in self)) { // * support legacy Webogram's localStorage
|
||||||
|
self.postMessage({
|
||||||
|
type: 'localStorageProxy',
|
||||||
|
payload: {
|
||||||
|
type: 'delete',
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
} as LocalStorageProxyDeleteTask);
|
||||||
|
}
|
||||||
|
|
||||||
await this.storage.delete(keys);
|
await this.storage.delete(keys);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error('[AS]: delete error:', e, keys);
|
console.error('[AS]: delete error:', e, keys);
|
||||||
@ -107,7 +149,7 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
|||||||
}, (error) => {
|
}, (error) => {
|
||||||
if(!['NO_ENTRY_FOUND', 'STORAGE_OFFLINE'].includes(error)) {
|
if(!['NO_ENTRY_FOUND', 'STORAGE_OFFLINE'].includes(error)) {
|
||||||
this.useStorage = false;
|
this.useStorage = false;
|
||||||
console.error('[AS]: get error:', error, keys, storageOptions.storeName);
|
console.error('[AS]: get error:', error, keys, storeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let i = 0, length = keys.length; i < length; ++i) {
|
for(let i = 0, length = keys.length; i < length; ++i) {
|
||||||
@ -135,7 +177,7 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
|||||||
return this.cache;
|
return this.cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getFromCache(key: keyof Storage) {
|
public getFromCache<T extends keyof Storage>(key: T) {
|
||||||
return this.cache[key];
|
return this.cache[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,12 +185,12 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
|||||||
return this.cache[key] = value;
|
return this.cache[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async get(key: keyof Storage, useCache = true): Promise<Storage[typeof key]> {
|
public async get<T extends keyof Storage>(key: T, useCache = true): Promise<Storage[T]> {
|
||||||
if(this.cache.hasOwnProperty(key) && useCache) {
|
if(this.cache.hasOwnProperty(key) && useCache) {
|
||||||
return this.getFromCache(key);
|
return this.getFromCache(key);
|
||||||
} else if(this.useStorage) {
|
} else if(this.useStorage) {
|
||||||
const r = this.getPromises.get(key);
|
const r = this.getPromises.get(key);
|
||||||
if(r) return r;
|
if(r) return r as any;
|
||||||
|
|
||||||
const p = deferredPromise<Storage[typeof key]>();
|
const p = deferredPromise<Storage[typeof key]>();
|
||||||
this.getPromises.set(key, p);
|
this.getPromises.set(key, p);
|
||||||
@ -232,8 +274,21 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
|||||||
storage.keysToDelete.clear();
|
storage.keysToDelete.clear();
|
||||||
storage.getPromises.forEach((deferred) => deferred.resolve());
|
storage.getPromises.forEach((deferred) => deferred.resolve());
|
||||||
storage.getPromises.clear();
|
storage.getPromises.clear();
|
||||||
|
|
||||||
|
if(storage.db === DATABASE_SESSION && 'localStorage' in self) { // * support legacy Webogram's localStorage
|
||||||
|
localStorage.clear();
|
||||||
|
}
|
||||||
|
|
||||||
return storage.clear();
|
return storage.clear();
|
||||||
} else {
|
} else {
|
||||||
|
if(storage.db === DATABASE_SESSION && 'localStorage' in self) { // * support legacy Webogram's localStorage
|
||||||
|
for(const i in storage.cache) {
|
||||||
|
if(storage.cache[i] !== undefined) {
|
||||||
|
localStorage.setItem(i, JSON.stringify(storage.cache[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return storage.set(storage.cache);
|
return storage.set(storage.cache);
|
||||||
}
|
}
|
||||||
})).catch(noop);
|
})).catch(noop);
|
||||||
|
@ -126,7 +126,7 @@ export default class FiltersStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// exclude_read
|
// exclude_read
|
||||||
if(pFlags.exclude_read && !dialog.unread_count) {
|
if(pFlags.exclude_read && !dialog.unread_count && !dialog.pFlags.unread_mark) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user