Improve smoothness of opening chat on handhelds
Fix schedule send & delete Fix min schedule date
This commit is contained in:
parent
bb7c2bbe47
commit
cbd9c28d3e
@ -2408,7 +2408,8 @@ export default class ChatBubbles {
|
||||
//console.time('appImManager call getHistory');
|
||||
const pageCount = this.appPhotosManager.windowH / 38/* * 1.25 */ | 0;
|
||||
//const loadCount = Object.keys(this.bubbles).length > 0 ? 50 : pageCount;
|
||||
const realLoadCount = Object.keys(this.bubbles).length > 0 || additionMsgId ? Math.max(40, pageCount) : pageCount;//const realLoadCount = 50;
|
||||
//const realLoadCount = Object.keys(this.bubbles).length > 0 || additionMsgId ? Math.max(40, pageCount) : pageCount;//const realLoadCount = 50;
|
||||
const realLoadCount = pageCount;//const realLoadCount = 50;
|
||||
let loadCount = realLoadCount;
|
||||
|
||||
/* if(TEST_SCROLL) {
|
||||
|
@ -191,7 +191,7 @@ export default class Chat extends EventListenerBase<{
|
||||
appSidebarRight.sharedMediaTab.loadSidebarMedia(false);
|
||||
}); */
|
||||
|
||||
return this.setPeerPromise;
|
||||
return result;
|
||||
}
|
||||
|
||||
public finishPeerChange(isTarget: boolean, isJump: boolean, lastMsgId: number) {
|
||||
|
@ -113,7 +113,8 @@ export default class ChatContextMenu {
|
||||
const good = ['bubble', 'bubble__container', 'message', 'time', 'inner'].find(c => className.match(new RegExp(c + '($|\\s)')));
|
||||
if(good) {
|
||||
cancelEvent(e);
|
||||
onContextMenu((e as TouchEvent).changedTouches[0]);
|
||||
//onContextMenu((e as TouchEvent).changedTouches[0]);
|
||||
onContextMenu((e as TouchEvent).changedTouches ? (e as TouchEvent).changedTouches[0] : e as MouseEvent);
|
||||
}
|
||||
}, {listenerSetter: this.chat.bubbles.listenerSetter});
|
||||
|
||||
|
@ -149,7 +149,7 @@ export default class ChatSearch {
|
||||
this.chat.bubbles.bubblesContainer.classList.remove('search-results-active');
|
||||
|
||||
const res = this.chat.setPeer(peerId, lastMsgId);
|
||||
this.setPeerPromise = (res instanceof Promise ? res : Promise.resolve(res)).then(() => {
|
||||
this.setPeerPromise = ((res instanceof Promise ? res : Promise.resolve(res)) as Promise<any>).then(() => {
|
||||
this.selectedIndex = index;
|
||||
this.foundCountEl.innerText = `${index + 1} of ${this.foundCount}`;
|
||||
|
||||
|
@ -271,22 +271,24 @@ export default class ChatTopbar {
|
||||
}
|
||||
});
|
||||
|
||||
this.chat.addListener('setPeer', (mid, isTopMessage) => {
|
||||
const middleware = this.chat.bubbles.getMiddleware();
|
||||
appStateManager.getState().then((state) => {
|
||||
if(!middleware()) return;
|
||||
|
||||
this.pinnedMessage.hidden = !!state.hiddenPinnedMessages[this.chat.peerId];
|
||||
|
||||
if(isTopMessage) {
|
||||
this.pinnedMessage.unsetScrollDownListener();
|
||||
this.pinnedMessage.testMid(mid, 0); // * because slider will not let get bubble by document.elementFromPoint
|
||||
} else if(!this.pinnedMessage.locked) {
|
||||
this.pinnedMessage.handleFollowingPinnedMessage();
|
||||
this.pinnedMessage.testMid(mid);
|
||||
}
|
||||
if(this.pinnedMessage) {
|
||||
this.chat.addListener('setPeer', (mid, isTopMessage) => {
|
||||
const middleware = this.chat.bubbles.getMiddleware();
|
||||
appStateManager.getState().then((state) => {
|
||||
if(!middleware()) return;
|
||||
|
||||
this.pinnedMessage.hidden = !!state.hiddenPinnedMessages[this.chat.peerId];
|
||||
|
||||
if(isTopMessage) {
|
||||
this.pinnedMessage.unsetScrollDownListener();
|
||||
this.pinnedMessage.testMid(mid, 0); // * because slider will not let get bubble by document.elementFromPoint
|
||||
} else if(!this.pinnedMessage.locked) {
|
||||
this.pinnedMessage.handleFollowingPinnedMessage();
|
||||
this.pinnedMessage.testMid(mid);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.setPeerStatusInterval = window.setInterval(this.setPeerStatus, 60e3);
|
||||
|
||||
|
@ -2,9 +2,8 @@ import Countries, { Country, PhoneCodesMain } from "../countries";
|
||||
import { cancelEvent, CLICK_EVENT_NAME } from "../helpers/dom";
|
||||
import ListenerSetter from "../helpers/listenerSetter";
|
||||
import mediaSizes from "../helpers/mediaSizes";
|
||||
import { clamp } from "../helpers/number";
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { isApple, isSafari } from "../helpers/userAgent";
|
||||
import { isApple } from "../helpers/userAgent";
|
||||
|
||||
export const loadedURLs: {[url: string]: boolean} = {};
|
||||
const set = (elem: HTMLElement | HTMLImageElement | SVGImageElement | HTMLVideoElement, url: string) => {
|
||||
|
@ -45,6 +45,10 @@ export default class PopupDatePicker extends PopupElement {
|
||||
|
||||
this.minDate = options.minDate || new Date('2013-08-01T00:00:00');
|
||||
|
||||
if(initDate < this.minDate) {
|
||||
initDate.setFullYear(this.minDate.getFullYear(), this.minDate.getMonth(), this.minDate.getDate());
|
||||
}
|
||||
|
||||
// Controls
|
||||
this.controlsDiv = document.createElement('div');
|
||||
this.controlsDiv.classList.add('date-picker-controls');
|
||||
|
@ -2,8 +2,8 @@ import PopupDatePicker from "./datePicker";
|
||||
|
||||
const getMinDate = () => {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - 1);
|
||||
//date.setHours(0, 0, 0, 0);
|
||||
//date.setDate(date.getDate() - 1);
|
||||
date.setHours(0, 0, 0, 0);
|
||||
return date;
|
||||
};
|
||||
|
||||
|
@ -154,7 +154,9 @@ export default class Scrollable extends ScrollableBase {
|
||||
|
||||
//return;
|
||||
|
||||
if(this.onScrollMeasure || ((this.scrollLocked || (!this.onScrolledTop && !this.onScrolledBottom)) && !this.splitUp && !this.onAdditionalScroll)) return;
|
||||
//if(this.onScrollMeasure || ((this.scrollLocked || (!this.onScrolledTop && !this.onScrolledBottom)) && !this.splitUp && !this.onAdditionalScroll)) return;
|
||||
if((this.scrollLocked || (!this.onScrolledTop && !this.onScrolledBottom)) && !this.splitUp && !this.onAdditionalScroll) return;
|
||||
if(this.onScrollMeasure) window.cancelAnimationFrame(this.onScrollMeasure);
|
||||
this.onScrollMeasure = window.requestAnimationFrame(() => {
|
||||
this.onScrollMeasure = 0;
|
||||
|
||||
|
@ -559,7 +559,7 @@ export function wrapPhoto({photo, message, container, boxWidth, boxHeight, withT
|
||||
if(message?.media?.preloader) { // means upload
|
||||
message.media.preloader.attach(container);
|
||||
} else if(!cacheContext.downloaded) {
|
||||
preloader = new ProgressivePreloader(container, false, false, photo._ == 'document' ? 'prepend' : 'append');
|
||||
preloader = new ProgressivePreloader(null, false, false, photo._ == 'document' ? 'prepend' : 'append');
|
||||
}
|
||||
|
||||
const load = () => {
|
||||
|
@ -466,13 +466,14 @@ export function blurActiveElement() {
|
||||
}
|
||||
}
|
||||
|
||||
export const CLICK_EVENT_NAME = isTouchSupported ? 'touchend' : 'click';
|
||||
export const CLICK_EVENT_NAME: 'mousedown' | 'touchend' | 'click' = (isTouchSupported ? 'mousedown' : 'click') as any;
|
||||
export type AttachClickOptions = AddEventListenerOptions & Partial<{listenerSetter: ListenerSetter, touchMouseDown: true}>;
|
||||
export const attachClickEvent = (elem: HTMLElement, callback: (e: TouchEvent | MouseEvent) => void, options: AttachClickOptions = {}) => {
|
||||
const add = options.listenerSetter ? options.listenerSetter.add.bind(options.listenerSetter, elem) : elem.addEventListener.bind(elem);
|
||||
const remove = options.listenerSetter ? options.listenerSetter.removeManual.bind(options.listenerSetter, elem) : elem.removeEventListener.bind(elem);
|
||||
|
||||
if(options.touchMouseDown && CLICK_EVENT_NAME === 'touchend') {
|
||||
options.touchMouseDown = true;
|
||||
/* if(options.touchMouseDown && CLICK_EVENT_NAME === 'touchend') {
|
||||
add('mousedown', callback, options);
|
||||
} else if(CLICK_EVENT_NAME === 'touchend') {
|
||||
const o = {...options, once: true};
|
||||
@ -498,7 +499,8 @@ export const attachClickEvent = (elem: HTMLElement, callback: (e: TouchEvent | M
|
||||
add('touchstart', onTouchStart);
|
||||
} else {
|
||||
add(CLICK_EVENT_NAME, callback, options);
|
||||
}
|
||||
} */
|
||||
add(CLICK_EVENT_NAME, callback, options);
|
||||
};
|
||||
|
||||
export const detachClickEvent = (elem: HTMLElement, callback: (e: TouchEvent | MouseEvent) => void, options?: AddEventListenerOptions) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { ArgumentTypes } from "../types";
|
||||
import type { ArgumentTypes, SuperReturnType } from "../types";
|
||||
|
||||
export default class EventListenerBase<Listeners extends {[name: string]: Function}> {
|
||||
protected listeners: Partial<{
|
||||
@ -36,14 +36,17 @@ export default class EventListenerBase<Listeners extends {[name: string]: Functi
|
||||
this.listenerResults[name] = args;
|
||||
}
|
||||
|
||||
const arr: Array<SuperReturnType<Listeners[typeof name]>> = [];
|
||||
if(this.listeners[name]) {
|
||||
this.listeners[name].forEach(listener => {
|
||||
listener.callback(...args);
|
||||
arr.push(listener.callback(...args));
|
||||
|
||||
if(listener.once) {
|
||||
this.removeListener(name, listener.callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ export class ApiUpdatesManager {
|
||||
|
||||
constructor() {
|
||||
// * false for test purposes
|
||||
/* false && */appStateManager.addListener('save', () => {
|
||||
/* false && */appStateManager.addListener('save', async() => {
|
||||
const us = this.updatesState;
|
||||
appStateManager.pushToState('updates', {
|
||||
seq: us.seq,
|
||||
|
@ -51,8 +51,8 @@ export class AppImManager {
|
||||
|
||||
public setPeerPromise: Promise<void> = null;
|
||||
|
||||
private mainColumns: HTMLElement;
|
||||
public _selectTab: ReturnType<typeof horizontalMenu>;
|
||||
//private mainColumns: HTMLElement;
|
||||
//public _selectTab: ReturnType<typeof horizontalMenu>;
|
||||
public tabId = -1;
|
||||
//private closeBtn: HTMLButtonElement;// = this.topbar.querySelector('.sidebar-close-button') as HTMLButtonElement;
|
||||
public hideRightSidebar = false;
|
||||
@ -74,8 +74,8 @@ export class AppImManager {
|
||||
|
||||
this.log = logger('IM', LogLevels.log | LogLevels.warn | LogLevels.debug | LogLevels.error);
|
||||
|
||||
this.mainColumns = this.columnEl.parentElement;
|
||||
this._selectTab = horizontalMenu(null, this.mainColumns);
|
||||
//this.mainColumns = this.columnEl.parentElement;
|
||||
//this._selectTab = horizontalMenu(null, this.mainColumns);
|
||||
this.selectTab(0);
|
||||
|
||||
window.addEventListener('blur', () => {
|
||||
@ -420,7 +420,7 @@ export class AppImManager {
|
||||
document.body.classList.remove(RIGHT_COLUMN_ACTIVE_CLASSNAME);
|
||||
}
|
||||
|
||||
this._selectTab(id, mediaSizes.isMobile);
|
||||
//this._selectTab(id, mediaSizes.isMobile);
|
||||
//document.body.classList.toggle(RIGHT_COLUMN_ACTIVE_CLASSNAME, id == 2);
|
||||
}
|
||||
|
||||
@ -498,24 +498,29 @@ export class AppImManager {
|
||||
return this.setPeer(peerId, lastMsgId);
|
||||
}
|
||||
|
||||
if(peerId || mediaSizes.activeScreen != ScreenSize.mobile) {
|
||||
chat.setPeer(peerId, lastMsgId);
|
||||
if(peerId || mediaSizes.activeScreen !== ScreenSize.mobile) {
|
||||
const result = chat.setPeer(peerId, lastMsgId);
|
||||
|
||||
const promise = result?.cached ? result.promise : Promise.resolve();
|
||||
if(peerId) {
|
||||
promise.then(() => {
|
||||
//window.requestAnimationFrame(() => {
|
||||
setTimeout(() => { // * setTimeout is better here
|
||||
if(this.hideRightSidebar) {
|
||||
appSidebarRight.toggleSidebar(true);
|
||||
this.hideRightSidebar = false;
|
||||
}
|
||||
|
||||
this.selectTab(1);
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(peerId == 0) {
|
||||
if(!peerId) {
|
||||
this.selectTab(0);
|
||||
|
||||
document.body.classList.add(LEFT_COLUMN_ACTIVE_CLASSNAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
document.body.classList.remove(LEFT_COLUMN_ACTIVE_CLASSNAME);
|
||||
if(this.hideRightSidebar) {
|
||||
appSidebarRight.toggleSidebar(true);
|
||||
this.hideRightSidebar = false;
|
||||
}
|
||||
|
||||
this.selectTab(1);
|
||||
}
|
||||
|
||||
public setInnerPeer(peerId: number, lastMsgId?: number, type: ChatType = 'chat') {
|
||||
|
@ -227,51 +227,77 @@ export class AppMessagesManager {
|
||||
}
|
||||
}); */
|
||||
|
||||
function timedChunk(items: any[], process: (...args: any[]) => any, context: any, callback: (...args: any[]) => void) {
|
||||
const todo = items.slice();
|
||||
|
||||
const f = () => {
|
||||
const start = +new Date();
|
||||
|
||||
do {
|
||||
process.call(context, todo.shift());
|
||||
} while(todo.length > 0 && (+new Date() - start < 50));
|
||||
|
||||
if(todo.length > 0) {
|
||||
setTimeout(f, 25);
|
||||
} else {
|
||||
callback(items);
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(f, 25);
|
||||
}
|
||||
|
||||
appStateManager.addListener('save', () => {
|
||||
const messages: any[] = [];
|
||||
const dialogs: Dialog[] = [];
|
||||
const items: any[] = [];
|
||||
|
||||
const processDialog = (dialog: MTDialog.dialog) => {
|
||||
const historyStorage = this.getHistoryStorage(dialog.peerId);
|
||||
const history = [].concat(historyStorage.pending, historyStorage.history);
|
||||
dialog = copy(dialog);
|
||||
let removeUnread = 0;
|
||||
for(const mid of history) {
|
||||
const message = this.getMessageByPeer(dialog.peerId, mid);
|
||||
if(/* message._ != 'messageEmpty' && */!message.pFlags.is_outgoing) {
|
||||
messages.push(message);
|
||||
|
||||
if(message.fromId != dialog.peerId) {
|
||||
appStateManager.setPeer(message.fromId, appPeersManager.getPeer(message.fromId));
|
||||
}
|
||||
|
||||
dialog.top_message = message.mid;
|
||||
this.setDialogIndexByMessage(dialog, message);
|
||||
|
||||
break;
|
||||
} else if(message.pFlags && message.pFlags.unread) {
|
||||
++removeUnread;
|
||||
}
|
||||
}
|
||||
|
||||
if(removeUnread && dialog.unread_count) dialog.unread_count -= removeUnread;
|
||||
|
||||
dialog.unread_count = Math.max(0, dialog.unread_count);
|
||||
dialogs.push(dialog);
|
||||
|
||||
appStateManager.setPeer(dialog.peerId, appPeersManager.getPeer(dialog.peerId));
|
||||
};
|
||||
|
||||
for(const folderId in this.dialogsStorage.byFolders) {
|
||||
const folder = this.dialogsStorage.getFolder(+folderId);
|
||||
|
||||
|
||||
for(let dialog of folder) {
|
||||
const historyStorage = this.getHistoryStorage(dialog.peerId);
|
||||
const history = [].concat(historyStorage.pending, historyStorage.history);
|
||||
|
||||
dialog = copy(dialog);
|
||||
let removeUnread = 0;
|
||||
for(const mid of history) {
|
||||
const message = this.getMessageByPeer(dialog.peerId, mid);
|
||||
if(/* message._ != 'messageEmpty' && */!message.pFlags.is_outgoing) {
|
||||
messages.push(message);
|
||||
|
||||
if(message.fromId != dialog.peerId) {
|
||||
appStateManager.setPeer(message.fromId, appPeersManager.getPeer(message.fromId));
|
||||
}
|
||||
|
||||
dialog.top_message = message.mid;
|
||||
this.setDialogIndexByMessage(dialog, message);
|
||||
|
||||
break;
|
||||
} else if(message.pFlags && message.pFlags.unread) {
|
||||
++removeUnread;
|
||||
}
|
||||
}
|
||||
|
||||
if(removeUnread && dialog.unread_count) dialog.unread_count -= removeUnread;
|
||||
|
||||
dialog.unread_count = Math.max(0, dialog.unread_count);
|
||||
dialogs.push(dialog);
|
||||
|
||||
appStateManager.setPeer(dialog.peerId, appPeersManager.getPeer(dialog.peerId));
|
||||
items.push(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
appStateManager.pushToState('dialogs', dialogs);
|
||||
appStateManager.pushToState('messages', messages);
|
||||
appStateManager.pushToState('filters', this.filtersStorage.filters);
|
||||
appStateManager.pushToState('allDialogsLoaded', this.dialogsStorage.allDialogsLoaded);
|
||||
appStateManager.pushToState('maxSeenMsgId', this.maxSeenId);
|
||||
return new Promise((resolve => timedChunk(items, processDialog, this, resolve))).then(() => {
|
||||
appStateManager.pushToState('dialogs', dialogs);
|
||||
appStateManager.pushToState('messages', messages);
|
||||
appStateManager.pushToState('filters', this.filtersStorage.filters);
|
||||
appStateManager.pushToState('allDialogsLoaded', this.dialogsStorage.allDialogsLoaded);
|
||||
appStateManager.pushToState('maxSeenMsgId', this.maxSeenId);
|
||||
});
|
||||
});
|
||||
|
||||
appStateManager.getState().then(state => {
|
||||
@ -3187,6 +3213,7 @@ export class AppMessagesManager {
|
||||
}
|
||||
|
||||
public readMessages(peerId: number, msgIds: number[]) {
|
||||
msgIds = msgIds.map(mid => this.getLocalMessageId(mid));
|
||||
if(peerId < 0 && appPeersManager.isChannel(peerId)) {
|
||||
const channelId = -peerId;
|
||||
apiManager.invokeApi('channels.readMessageContents', {
|
||||
@ -4113,7 +4140,7 @@ export class AppMessagesManager {
|
||||
public sendScheduledMessages(peerId: number, mids: number[]) {
|
||||
return apiManager.invokeApi('messages.sendScheduledMessages', {
|
||||
peer: appPeersManager.getInputPeerById(peerId),
|
||||
id: mids
|
||||
id: mids.map(mid => this.getLocalMessageId(mid))
|
||||
}).then(updates => {
|
||||
apiUpdatesManager.processUpdateMessage(updates);
|
||||
});
|
||||
@ -4122,7 +4149,7 @@ export class AppMessagesManager {
|
||||
public deleteScheduledMessages(peerId: number, mids: number[]) {
|
||||
return apiManager.invokeApi('messages.deleteScheduledMessages', {
|
||||
peer: appPeersManager.getInputPeerById(peerId),
|
||||
id: mids
|
||||
id: mids.map(mid => this.getLocalMessageId(mid))
|
||||
}).then(updates => {
|
||||
apiUpdatesManager.processUpdateMessage(updates);
|
||||
});
|
||||
|
@ -16,13 +16,16 @@ const STATE_VERSION = App.version;
|
||||
|
||||
type State = Partial<{
|
||||
dialogs: Dialog[],
|
||||
allDialogsLoaded: DialogsStorage['allDialogsLoaded'],
|
||||
//peers: {[peerId: string]: ReturnType<AppPeersManager['getPeer']>},
|
||||
allDialogsLoaded: DialogsStorage['allDialogsLoaded'],
|
||||
chats: {[peerId: string]: ReturnType<AppChatsManager['getChat']>},
|
||||
users: {[peerId: string]: ReturnType<AppUsersManager['getUser']>},
|
||||
messages: any[],
|
||||
contactsList: number[],
|
||||
updates: any,
|
||||
updates: Partial<{
|
||||
seq: number,
|
||||
pts: number,
|
||||
date: number
|
||||
}>,
|
||||
filters: FiltersStorage['filters'],
|
||||
maxSeenMsgId: number,
|
||||
stateCreatedTime: number,
|
||||
@ -35,16 +38,45 @@ type State = Partial<{
|
||||
hiddenPinnedMessages: {[peerId: string]: number}
|
||||
}>;
|
||||
|
||||
/* const STATE_INIT: State = {
|
||||
dialogs: [],
|
||||
allDialogsLoaded: {},
|
||||
chats: {},
|
||||
users: {},
|
||||
messages: [],
|
||||
contactsList: [],
|
||||
updates: {},
|
||||
filters: {},
|
||||
maxSeenMsgId: 0,
|
||||
stateCreatedTime: 0,
|
||||
recentEmoji: [],
|
||||
topPeers: [],
|
||||
recentSearch: [],
|
||||
stickerSets: {},
|
||||
version: '',
|
||||
authState:
|
||||
}; */
|
||||
|
||||
const ALL_KEYS = ['dialogs', 'allDialogsLoaded', 'chats',
|
||||
'users', 'messages', 'contactsList',
|
||||
'updates', 'filters', 'maxSeenMsgId',
|
||||
'stateCreatedTime', 'recentEmoji', 'topPeers',
|
||||
'recentSearch', 'stickerSets', 'version',
|
||||
'authState', 'hiddenPinnedMessages'
|
||||
] as any as Array<keyof State>;
|
||||
|
||||
const REFRESH_KEYS = ['dialogs', 'allDialogsLoaded', 'messages', 'contactsList', 'stateCreatedTime',
|
||||
'updates', 'maxSeenMsgId', 'filters', 'topPeers'] as any as Array<keyof State>;
|
||||
|
||||
export class AppStateManager extends EventListenerBase<{
|
||||
save: (state: State) => void
|
||||
save: (state: State) => Promise<void>
|
||||
}> {
|
||||
public loaded: Promise<State>;
|
||||
private log = logger('STATE'/* , LogLevels.error */);
|
||||
|
||||
private state: State;
|
||||
private savePromise: Promise<void>;
|
||||
private tempId = 0;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@ -55,7 +87,18 @@ export class AppStateManager extends EventListenerBase<{
|
||||
if(this.loaded) return this.loaded;
|
||||
//console.time('load state');
|
||||
return this.loaded = new Promise((resolve) => {
|
||||
AppStorage.get<[State, UserAuth]>('state', 'user_auth').then(([state, auth]) => {
|
||||
AppStorage.get<any>(...ALL_KEYS, 'user_auth').then((arr) => {
|
||||
let state: State = {};
|
||||
|
||||
// ! then can't store false values
|
||||
ALL_KEYS.forEach((key, idx) => {
|
||||
const value = arr[idx];
|
||||
if(value !== false) {
|
||||
// @ts-ignore
|
||||
state[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
const time = Date.now();
|
||||
if(state) {
|
||||
if(state.version != STATE_VERSION) {
|
||||
@ -84,6 +127,7 @@ export class AppStateManager extends EventListenerBase<{
|
||||
|
||||
//return resolve();
|
||||
|
||||
const auth: UserAuth = arr[arr.length - 1];
|
||||
if(auth) {
|
||||
// ! Warning ! DON'T delete this
|
||||
this.state.authState = {_: 'authStateSignedIn'};
|
||||
@ -95,7 +139,10 @@ export class AppStateManager extends EventListenerBase<{
|
||||
//console.timeEnd('load state');
|
||||
resolve(this.state);
|
||||
}).catch(resolve).finally(() => {
|
||||
setInterval(() => this.saveState(), 10000);
|
||||
setInterval(() => {
|
||||
this.tempId++;
|
||||
this.saveState();
|
||||
}, 10000);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -105,18 +152,26 @@ export class AppStateManager extends EventListenerBase<{
|
||||
}
|
||||
|
||||
public saveState() {
|
||||
if(this.state === undefined) return;
|
||||
if(this.state === undefined || this.savePromise) return;
|
||||
|
||||
const tempId = this.tempId;
|
||||
this.savePromise = Promise.all(this.setListenerResult('save', this.state)).then(() => {
|
||||
return AppStorage.set(this.state);
|
||||
}).then(() => {
|
||||
this.savePromise = null;
|
||||
|
||||
if(this.tempId !== tempId) {
|
||||
this.saveState();
|
||||
}
|
||||
});
|
||||
//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);
|
||||
}
|
||||
|
||||
@ -129,6 +184,16 @@ export class AppStateManager extends EventListenerBase<{
|
||||
if(container.hasOwnProperty(peerId)) return;
|
||||
container[peerId] = peer;
|
||||
}
|
||||
|
||||
public resetState() {
|
||||
for(let i in this.state) {
|
||||
// @ts-ignore
|
||||
this.state[i] = false;
|
||||
}
|
||||
AppStorage.set(this.state).then(() => {
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//console.trace('appStateManager include');
|
||||
|
@ -100,7 +100,7 @@ export class AppUsersManager {
|
||||
}
|
||||
});
|
||||
|
||||
appStateManager.addListener('save', () => {
|
||||
appStateManager.addListener('save', async() => {
|
||||
const contactsList = [...this.contactsList];
|
||||
for(const userId of contactsList) {
|
||||
appStateManager.setPeer(userId, this.getUser(userId));
|
||||
|
@ -13,7 +13,7 @@ function dT() {
|
||||
}
|
||||
|
||||
export function logger(prefix: string, level = LogLevels.log | LogLevels.warn | LogLevels.error) {
|
||||
if(process.env.NODE_ENV != 'development'/* || true */) {
|
||||
if(process.env.NODE_ENV != 'development' || true) {
|
||||
level = LogLevels.error;
|
||||
}
|
||||
|
||||
|
@ -70,9 +70,9 @@ export class ProgressLine {
|
||||
this.container.addEventListener('mouseup', this.onMouseUp);
|
||||
|
||||
if(isTouchSupported) {
|
||||
this.container.addEventListener('touchmove', this.onMouseMove);
|
||||
this.container.addEventListener('touchstart', this.onMouseDown);
|
||||
this.container.addEventListener('touchend', this.onMouseUp);
|
||||
this.container.addEventListener('touchmove', this.onMouseMove, {passive: true});
|
||||
this.container.addEventListener('touchstart', this.onMouseDown, {passive: true});
|
||||
this.container.addEventListener('touchend', this.onMouseUp, {passive: true});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,6 @@ import { MOUNT_CLASS_TO } from './mtproto/mtproto_config';
|
||||
//import { stringify } from '../helpers/json';
|
||||
|
||||
class AppStorage {
|
||||
//private log = (...args: any[]) => console.log('[SW LS]', ...args);
|
||||
private log = (...args: any[]) => {};
|
||||
|
||||
private cacheStorage = new CacheStorageController('session');
|
||||
|
||||
//public noPrefix = false;
|
||||
@ -66,24 +63,23 @@ class AppStorage {
|
||||
}
|
||||
|
||||
public async set(obj: any) {
|
||||
let keyValues: any = {};
|
||||
let prefix = this.storageGetPrefix(),
|
||||
key, value;
|
||||
|
||||
const prefix = this.storageGetPrefix();
|
||||
//console.log('storageSetValue', obj, callback, arguments);
|
||||
|
||||
for(key in obj) {
|
||||
for(let key in obj) {
|
||||
if(obj.hasOwnProperty(key)) {
|
||||
value = obj[key];
|
||||
let value = obj[key];
|
||||
key = prefix + key;
|
||||
this.cache[key] = value;
|
||||
|
||||
let perf = performance.now();
|
||||
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();
|
||||
let elapsedTime = performance.now() - perf;
|
||||
if(elapsedTime > 10) {
|
||||
console.warn('LocalStorage set: stringify time by JSON.stringify:', elapsedTime, key);
|
||||
}
|
||||
/* perf = performance.now();
|
||||
value = stringify(value);
|
||||
console.log('LocalStorage set: stringify time by own stringify:', performance.now() - perf); */
|
||||
|
||||
@ -97,8 +93,6 @@ class AppStorage {
|
||||
//this.useCS = false;
|
||||
console.error('[AS]: set error:', e, key/* , value */);
|
||||
}
|
||||
} else {
|
||||
keyValues[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -109,11 +103,9 @@ class AppStorage {
|
||||
keys = Array.prototype.slice.call(arguments);
|
||||
}
|
||||
|
||||
let prefix = this.storageGetPrefix(),
|
||||
i, key;
|
||||
|
||||
for(i = 0; i < keys.length; i++) {
|
||||
key = keys[i] = prefix + keys[i];
|
||||
const prefix = this.storageGetPrefix();
|
||||
for(let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i] = prefix + keys[i];
|
||||
delete this.cache[key];
|
||||
if(this.useCS) {
|
||||
try {
|
||||
|
@ -22,6 +22,8 @@ $chat-helper-size: 39px;
|
||||
transition: transform var(--layer-transition);
|
||||
transform: translateY(var(--translateY));
|
||||
|
||||
//display: none !important;
|
||||
|
||||
/* // * for no ESG top
|
||||
flex: 1 1 auto;
|
||||
height: calc(100% - 56px); */
|
||||
@ -407,6 +409,17 @@ $chat-helper-size: 39px;
|
||||
position: relative;
|
||||
flex: 3;
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
body.is-left-column-shown & {
|
||||
transform: translate3d(100vw, 0, 0);
|
||||
}
|
||||
|
||||
body.is-right-column-shown & {
|
||||
transform: translate3d(-25vw, 0, 0);
|
||||
filter: brightness(80%);
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(floating-left-sidebar) {
|
||||
position: fixed !important;
|
||||
left: 0;
|
||||
|
@ -9,6 +9,11 @@
|
||||
@include respond-to(handhelds) {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
|
||||
body:not(.is-left-column-shown) & {
|
||||
transform: translate3d(-25vw, 0, 0);
|
||||
filter: brightness(80%);
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(floating-left-sidebar) {
|
||||
|
@ -5,6 +5,12 @@
|
||||
box-shadow: 0 0.25rem 0.5rem 0.1rem hsla(0, 0%, 44.7%, .25);
|
||||
}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
body:not(.is-right-column-shown) & {
|
||||
transform: translate3d(100vw, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
width: var(--right-column-width);
|
||||
transition: transform var(--layer-transition);
|
||||
|
@ -24,10 +24,12 @@
|
||||
@include respond-to(handhelds) {
|
||||
.main-column {
|
||||
width: 100%;
|
||||
display: flex !important;
|
||||
z-index: 1;
|
||||
|
||||
&:not(.active) {
|
||||
/* &:not(.active) {
|
||||
display: none;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
/* #column-left {
|
||||
|
@ -177,7 +177,7 @@
|
||||
|
||||
&:disabled {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
//opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
src/types.d.ts
vendored
1
src/types.d.ts
vendored
@ -34,6 +34,7 @@ export type Modify<T, R> = Omit<T, keyof R> & R;
|
||||
//export type Parameters<T> = T extends (... args: infer T) => any ? T : never;
|
||||
|
||||
export type ArgumentTypes<F extends Function> = F extends (...args: infer A) => any ? A : never;
|
||||
export type SuperReturnType<F extends Function> = F extends (...args: any) => any ? ReturnType<F> : never;
|
||||
|
||||
export type AnyLiteral = Record<string, any>;
|
||||
export type AnyClass = new (...args: any[]) => any;
|
||||
|
Loading…
x
Reference in New Issue
Block a user