Fix Malaysia code
Fix shared media switching tab with scale Refactor users & chats Fix showing chatlist corner button with active search
This commit is contained in:
parent
bf15a88c7f
commit
92dea78bbd
@ -478,12 +478,13 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||
this.searchGroups.people.container.append(peopleContainer);
|
||||
let peopleScrollable = new ScrollableX(peopleContainer);
|
||||
|
||||
let first = true;
|
||||
let hideNewBtnMenuTimeout: number;
|
||||
//const transition = Transition.bind(null, searchContainer.parentElement, 150);
|
||||
const transition = TransitionSlider(searchContainer.parentElement, 'zoom-fade', 150, (id) => {
|
||||
if(hideNewBtnMenuTimeout) clearTimeout(hideNewBtnMenuTimeout);
|
||||
|
||||
if(id === 0) {
|
||||
if(id === 0 && !first) {
|
||||
searchSuper.selectTab(0, false);
|
||||
this.inputSearch.onClearClick();
|
||||
hideNewBtnMenuTimeout = window.setTimeout(() => {
|
||||
@ -491,6 +492,8 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||
this.newBtnMenu.classList.remove('is-hidden');
|
||||
}, 150);
|
||||
}
|
||||
|
||||
first = false;
|
||||
});
|
||||
|
||||
transition(0);
|
||||
|
@ -64,7 +64,7 @@ export default class AppBlockedUsersTab extends SliderSuperTab {
|
||||
if(user.pFlags.bot) {
|
||||
dom.lastMessageSpan.append('@' + user.username);
|
||||
} else {
|
||||
if(user.rPhone) dom.lastMessageSpan.innerHTML = user.rPhone;
|
||||
if(user.phone) dom.lastMessageSpan.innerHTML = appUsersManager.formatUserPhone(user.phone);
|
||||
else dom.lastMessageSpan.append(user.username ? '@' + user.username : appUsersManager.getUserStatusString(peerId));
|
||||
}
|
||||
|
||||
|
@ -153,6 +153,6 @@ export default class AppSettingsTab extends SliderSuperTab {
|
||||
this.avatarElem.setAttribute('peer', '' + user.id);
|
||||
|
||||
this.nameDiv.append(new PeerTitle({peerId: user.id}).element);
|
||||
this.phoneDiv.innerHTML = user.rPhone || '';
|
||||
this.phoneDiv.innerHTML = user.phone ? appUsersManager.formatUserPhone(user.phone) : '';
|
||||
}
|
||||
}
|
||||
|
@ -670,7 +670,7 @@ class PeerProfile {
|
||||
|
||||
let user = appUsersManager.getUser(peerId);
|
||||
if(user.phone && peerId !== rootScope.myId) {
|
||||
setText(user.rPhone, this.phone);
|
||||
setText(appUsersManager.formatUserPhone(user.phone), this.phone);
|
||||
}
|
||||
}/* else {
|
||||
//membersLi.style.display = appPeersManager.isBroadcast(peerId) ? 'none' : '';
|
||||
@ -824,7 +824,7 @@ export default class AppSharedMediaTab extends SliderSuperTab {
|
||||
const rect = this.searchSuper.nav.getBoundingClientRect();
|
||||
if(!rect.width) return;
|
||||
|
||||
const top = rect.top;
|
||||
const top = rect.top - 1;
|
||||
const isSharedMedia = top <= HEADER_HEIGHT;
|
||||
animatedCloseIcon.classList.toggle('state-back', isSharedMedia);
|
||||
this.searchSuper.container.classList.toggle('is-full-viewport', isSharedMedia);
|
||||
|
@ -11,11 +11,19 @@ export type DatabaseStoreName = 'session' | 'stickerSets' | 'users' | 'chats' |
|
||||
export type DatabaseStore = Omit<IDBStore, 'name'> & {name: DatabaseStoreName};
|
||||
const Database = {
|
||||
name: 'tweb' + (Modes.test ? '_test' : ''),
|
||||
version: 5,
|
||||
version: 7,
|
||||
stores: [{
|
||||
name: 'session'
|
||||
}, {
|
||||
name: 'stickerSets'
|
||||
}, {
|
||||
name: 'users'
|
||||
}, {
|
||||
name: 'chats'
|
||||
}, {
|
||||
name: 'dialogs'
|
||||
}, {
|
||||
name: 'messages'
|
||||
}] as DatabaseStore[],
|
||||
};
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -72,7 +72,7 @@ export function safeReplaceObject(wasObject: any, newObject: any) {
|
||||
}
|
||||
|
||||
for(var key in wasObject) {
|
||||
if(!newObject.hasOwnProperty(key) && key.charAt(0) !== '$') {
|
||||
if(!newObject.hasOwnProperty(key)) {
|
||||
delete wasObject[key];
|
||||
}
|
||||
}
|
||||
|
@ -50,16 +50,16 @@ export function throttle<F extends AnyToVoidFunction>(
|
||||
isPending = true;
|
||||
args = _args;
|
||||
|
||||
if (!interval) {
|
||||
if (shouldRunFirst) {
|
||||
if(!interval) {
|
||||
if(shouldRunFirst) {
|
||||
isPending = false;
|
||||
// @ts-ignore
|
||||
fn(...args);
|
||||
}
|
||||
|
||||
interval = window.setInterval(() => {
|
||||
interval = setInterval(() => {
|
||||
if (!isPending) {
|
||||
window.clearInterval(interval!);
|
||||
clearInterval(interval!);
|
||||
interval = null;
|
||||
return;
|
||||
}
|
||||
@ -67,7 +67,7 @@ export function throttle<F extends AnyToVoidFunction>(
|
||||
isPending = false;
|
||||
// @ts-ignore
|
||||
fn(...args);
|
||||
}, ms);
|
||||
}, ms) as any;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import apiManagerProxy from "../mtproto/mtprotoworker";
|
||||
import apiManager from '../mtproto/mtprotoworker';
|
||||
import { RichTextProcessor } from "../richtextprocessor";
|
||||
import rootScope from "../rootScope";
|
||||
//import AppStorage from "../storage";
|
||||
import apiUpdatesManager from "./apiUpdatesManager";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
@ -32,14 +33,18 @@ export type ChatRights = keyof ChatBannedRights['pFlags'] | keyof ChatAdminRight
|
||||
export type UserTyping = Partial<{userId: number, action: SendMessageAction, timeout: number}>;
|
||||
|
||||
export class AppChatsManager {
|
||||
public chats: {[id: number]: Chat.channel | Chat.chat | any} = {};
|
||||
//public usernames: any = {};
|
||||
//public channelAccess: any = {};
|
||||
//public megagroups: {[id: number]: true} = {};
|
||||
/* private storage = new AppStorage<Record<number, Chat>>({
|
||||
storeName: 'chats'
|
||||
}); */
|
||||
|
||||
private chats: {[id: number]: Chat.channel | Chat.chat | any} = {};
|
||||
//private usernames: any = {};
|
||||
//private channelAccess: any = {};
|
||||
//private megagroups: {[id: number]: true} = {};
|
||||
|
||||
public megagroupOnlines: {[id: number]: {timestamp: number, onlines: number}} = {};
|
||||
private megagroupOnlines: {[id: number]: {timestamp: number, onlines: number}} = {};
|
||||
|
||||
public typingsInPeer: {[peerId: number]: UserTyping[]} = {};
|
||||
private typingsInPeer: {[peerId: number]: UserTyping[]} = {};
|
||||
|
||||
constructor() {
|
||||
rootScope.addMultipleEventsListeners({
|
||||
@ -57,9 +62,9 @@ export class AppChatsManager {
|
||||
|
||||
updateChatDefaultBannedRights: (update) => {
|
||||
const chatId = -appPeersManager.getPeerId(update.peer);
|
||||
const chat: Chat = this.getChat(chatId);
|
||||
if(chat._ !== 'chatEmpty') {
|
||||
(chat as Chat.chat).default_banned_rights = update.default_banned_rights;
|
||||
const chat: Chat.chat = this.chats[chatId];
|
||||
if(chat) {
|
||||
chat.default_banned_rights = update.default_banned_rights;
|
||||
rootScope.broadcast('chat_update', chatId);
|
||||
}
|
||||
},
|
||||
@ -142,31 +147,40 @@ export class AppChatsManager {
|
||||
}
|
||||
};
|
||||
|
||||
public saveApiChats(apiChats: any[]) {
|
||||
apiChats.forEach(chat => this.saveApiChat(chat));
|
||||
public getPeerTypings(peerId: number) {
|
||||
return this.typingsInPeer[peerId];
|
||||
}
|
||||
|
||||
public saveApiChat(chat: any) {
|
||||
public saveApiChats(apiChats: any[], override?: boolean) {
|
||||
apiChats.forEach(chat => this.saveApiChat(chat, override));
|
||||
}
|
||||
|
||||
public saveApiChat(chat: any, override?: boolean) {
|
||||
/* if(chat._ !== 'chat' && chat._ !== 'channel') {
|
||||
return;
|
||||
} */
|
||||
|
||||
// * exclude from state
|
||||
// defineNotNumerableProperties(chat, ['rTitle', 'initials']);
|
||||
|
||||
//chat.rTitle = chat.title || 'chat_title_deleted';
|
||||
chat.rTitle = RichTextProcessor.wrapRichText(chat.title, {noLinks: true, noLinebreaks: true}) || 'chat_title_deleted';
|
||||
|
||||
const oldChat = this.chats[chat.id];
|
||||
|
||||
chat.initials = RichTextProcessor.getAbbreviation(chat.title);
|
||||
/* if(oldChat && !override) {
|
||||
return;
|
||||
} */
|
||||
|
||||
if(chat.pFlags === undefined) {
|
||||
chat.pFlags = {};
|
||||
}
|
||||
|
||||
if(chat.pFlags.min) {
|
||||
if(oldChat !== undefined) {
|
||||
return;
|
||||
}
|
||||
if(chat.pFlags.min && oldChat !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
chat.initials = RichTextProcessor.getAbbreviation(chat.title);
|
||||
|
||||
//console.log('im the weatherman', chat.id);
|
||||
|
||||
if(chat._ === 'channel' &&
|
||||
chat.participants_count === undefined &&
|
||||
oldChat !== undefined &&
|
||||
@ -204,6 +218,10 @@ export class AppChatsManager {
|
||||
if(changedTitle) {
|
||||
rootScope.broadcast('peer_title_edit', -chat.id);
|
||||
}
|
||||
|
||||
/* this.storage.set({
|
||||
[chat.id]: chat
|
||||
}); */
|
||||
}
|
||||
|
||||
public getChat(id: number) {
|
||||
@ -335,10 +353,7 @@ export class AppChatsManager {
|
||||
public isChannel(id: number) {
|
||||
if(id < 0) id = -id;
|
||||
const chat = this.chats[id];
|
||||
if(chat && (chat._ === 'channel' || chat._ === 'channelForbidden')/* || this.channelAccess[id] */) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return chat && (chat._ === 'channel' || chat._ === 'channelForbidden')/* || this.channelAccess[id] */;
|
||||
}
|
||||
|
||||
public isMegagroup(id: number) {
|
||||
@ -347,10 +362,7 @@ export class AppChatsManager {
|
||||
} */
|
||||
|
||||
const chat = this.chats[id];
|
||||
if(chat && chat._ === 'channel' && chat.pFlags.megagroup) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return chat && chat._ === 'channel' && chat.pFlags.megagroup;
|
||||
}
|
||||
|
||||
public isBroadcast(id: number) {
|
||||
@ -430,7 +442,7 @@ export class AppChatsManager {
|
||||
return i18n(key, [numberThousandSplitter(count)]);
|
||||
}
|
||||
|
||||
public wrapForFull(id: number, fullChat: any) {
|
||||
/* public wrapForFull(id: number, fullChat: any) {
|
||||
const chatFull = copy(fullChat);
|
||||
const chat = this.getChat(id);
|
||||
|
||||
@ -480,7 +492,7 @@ export class AppChatsManager {
|
||||
}
|
||||
|
||||
return participants;
|
||||
}
|
||||
} */
|
||||
|
||||
public createChannel(title: string, about: string): Promise<number> {
|
||||
return apiManager.invokeApi('channels.createChannel', {
|
||||
|
@ -908,7 +908,7 @@ export class AppImManager {
|
||||
|
||||
public getPeerTyping(peerId: number, container?: HTMLElement) {
|
||||
if(!appUsersManager.isBot(peerId)) {
|
||||
const typings = appChatsManager.typingsInPeer[peerId];
|
||||
const typings = appChatsManager.getPeerTypings(peerId);
|
||||
if(!typings || !typings.length) {
|
||||
return;
|
||||
}
|
||||
|
@ -2331,7 +2331,8 @@ export class AppMessagesManager {
|
||||
public saveMessages(messages: any[], options: Partial<{
|
||||
storage: MessagesStorage,
|
||||
isScheduled: true,
|
||||
isOutgoing: true
|
||||
isOutgoing: true,
|
||||
//isNew: boolean, // * new - from update
|
||||
}> = {}) {
|
||||
//let groups: Set<string>;
|
||||
messages.forEach((message) => {
|
||||
@ -2503,6 +2504,12 @@ export class AppMessagesManager {
|
||||
break;
|
||||
|
||||
case 'messageActionChatEditTitle':
|
||||
/* if(options.isNew) {
|
||||
const chat = appChatsManager.getChat(-peerId);
|
||||
chat.title = message.action.title;
|
||||
appChatsManager.saveApiChat(chat, true);
|
||||
} */
|
||||
|
||||
if(isBroadcast) {
|
||||
message.action._ = 'messageActionChannelEditTitle';
|
||||
}
|
||||
|
@ -154,21 +154,10 @@ export class AppProfileManager {
|
||||
id: appUsersManager.getUserInput(id)
|
||||
}).then((userFull) => {
|
||||
const user = userFull.user as User;
|
||||
/* if(override && isObject(override) && override.phone_number) {
|
||||
user.phone = override.phone_number;
|
||||
if(override.first_name || override.last_name) {
|
||||
user.first_name = override.first_name;
|
||||
user.last_name = override.last_name;
|
||||
}
|
||||
|
||||
appUsersManager.saveApiUser(user);
|
||||
} else { */
|
||||
appUsersManager.saveApiUser(user, true);
|
||||
//}
|
||||
appUsersManager.saveApiUser(user, true);
|
||||
|
||||
if(userFull.profile_photo) {
|
||||
userFull.profile_photo = appPhotosManager.savePhoto(userFull.profile_photo, {type: 'profilePhoto', peerId: id});
|
||||
/* appPhotosManager.savePhoto(userFull.profile_photo, {user_id: id}); */
|
||||
}
|
||||
|
||||
if(userFull.about !== undefined) {
|
||||
@ -253,7 +242,7 @@ export class AppProfileManager {
|
||||
return this.fullPromises[peerId] = apiManager.invokeApi('messages.getFullChat', {
|
||||
chat_id: id
|
||||
}).then((result) => {
|
||||
appChatsManager.saveApiChats(result.chats);
|
||||
appChatsManager.saveApiChats(result.chats, true);
|
||||
appUsersManager.saveApiUsers(result.users);
|
||||
const fullChat = result.full_chat as ChatFull.chatFull;
|
||||
if(fullChat && fullChat.chat_photo && fullChat.chat_photo.id) {
|
||||
@ -362,7 +351,7 @@ export class AppProfileManager {
|
||||
return this.fullPromises[peerId] = apiManager.invokeApi('channels.getFullChannel', {
|
||||
channel: appChatsManager.getChannelInput(id)
|
||||
}).then((result) => {
|
||||
appChatsManager.saveApiChats(result.chats);
|
||||
appChatsManager.saveApiChats(result.chats, true);
|
||||
appUsersManager.saveApiUsers(result.users);
|
||||
const fullChannel = result.full_chat as ChatFull.channelFull;
|
||||
if(fullChannel && fullChannel.chat_photo.id) {
|
||||
|
@ -47,6 +47,8 @@ export class AppUsersManager {
|
||||
private getTopPeersPromise: Promise<number[]>;
|
||||
|
||||
constructor() {
|
||||
//this.users = this.storage.getCache();
|
||||
|
||||
setInterval(this.updateUsersStatuses, 60000);
|
||||
|
||||
rootScope.on('state_synchronized', this.updateUsersStatuses);
|
||||
@ -67,7 +69,7 @@ export class AppUsersManager {
|
||||
}
|
||||
}
|
||||
|
||||
user.sortStatus = this.getUserStatusForSort(user.status);
|
||||
//user.sortStatus = this.getUserStatusForSort(user.status);
|
||||
rootScope.broadcast('user_update', userId);
|
||||
} //////else console.warn('No user by id:', userId);
|
||||
},
|
||||
@ -99,7 +101,7 @@ export class AppUsersManager {
|
||||
first_name: update.first_name,
|
||||
last_name: update.last_name,
|
||||
username: update.username
|
||||
}));
|
||||
}), true);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -271,42 +273,28 @@ export class AppUsersManager {
|
||||
apiUsers.forEach((user) => this.saveApiUser(user));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
public saveApiUser(user: MTUser, override?: boolean) {
|
||||
if(user._ === 'userEmpty') return;
|
||||
|
||||
const userId = user.id;
|
||||
const oldUser = this.users[userId];
|
||||
|
||||
if(oldUser && !override) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(user.pFlags === undefined) {
|
||||
user.pFlags = {};
|
||||
}
|
||||
|
||||
if(user.pFlags.min) {
|
||||
if(this.users[userId] !== undefined) {
|
||||
return;
|
||||
}
|
||||
if(user.pFlags.min && oldUser !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// * exclude from state
|
||||
// defineNotNumerableProperties(user, ['initials', 'num', 'rFirstName', 'rFullName', 'rPhone', 'sortName', 'sortStatus']);
|
||||
|
||||
if(user.phone) {
|
||||
user.rPhone = '+' + formatPhoneNumber(user.phone).formatted;
|
||||
}
|
||||
|
||||
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 {
|
||||
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(user.username) {
|
||||
const searchUsername = searchIndexManager.cleanUsername(user.username);
|
||||
this.usernames[searchUsername] = userId;
|
||||
@ -318,22 +306,17 @@ export class AppUsersManager {
|
||||
|
||||
if(user.status) {
|
||||
if((user.status as UserStatus.userStatusOnline).expires) {
|
||||
(user.status as UserStatus.userStatusOnline).expires -= serverTimeManager.serverTimeOffset
|
||||
(user.status as UserStatus.userStatusOnline).expires -= serverTimeManager.serverTimeOffset;
|
||||
}
|
||||
|
||||
if((user.status as UserStatus.userStatusOffline).was_online) {
|
||||
(user.status as UserStatus.userStatusOffline).was_online -= serverTimeManager.serverTimeOffset
|
||||
(user.status as UserStatus.userStatusOffline).was_online -= serverTimeManager.serverTimeOffset;
|
||||
}
|
||||
}
|
||||
|
||||
if(user.pFlags.bot) {
|
||||
user.sortStatus = -1;
|
||||
} else {
|
||||
user.sortStatus = this.getUserStatusForSort(user.status);
|
||||
}
|
||||
//user.sortStatus = user.pFlags.bot ? -1 : this.getUserStatusForSort(user.status);
|
||||
|
||||
let changedTitle = false;
|
||||
const oldUser = this.users[userId];
|
||||
if(oldUser === undefined) {
|
||||
this.users[userId] = user;
|
||||
} else {
|
||||
@ -347,11 +330,21 @@ export class AppUsersManager {
|
||||
rootScope.broadcast('user_update', userId);
|
||||
}
|
||||
|
||||
//console.log('we never give this up');
|
||||
|
||||
/* this.storage.set({
|
||||
[userId]: user
|
||||
}); */
|
||||
|
||||
if(changedTitle) {
|
||||
rootScope.broadcast('peer_title_edit', user.id);
|
||||
}
|
||||
}
|
||||
|
||||
public formatUserPhone(phone: string) {
|
||||
return '+' + formatPhoneNumber(phone).formatted;
|
||||
}
|
||||
|
||||
public getUserStatusForSort(status: User['status'] | number) {
|
||||
if(typeof(status) === 'number') {
|
||||
status = this.getUser(status).status;
|
||||
@ -579,7 +572,7 @@ export class AppUsersManager {
|
||||
expires: timestamp + onlineTimeFor
|
||||
};
|
||||
|
||||
user.sortStatus = this.getUserStatusForSort(user.status);
|
||||
//user.sortStatus = this.getUserStatusForSort(user.status);
|
||||
rootScope.broadcast('user_update', id);
|
||||
}
|
||||
}
|
||||
@ -781,7 +774,7 @@ export class AppUsersManager {
|
||||
};
|
||||
|
||||
user.status = status;
|
||||
user.sortStatus = this.getUserStatusForSort(user.status);
|
||||
//user.sortStatus = this.getUserStatusForSort(user.status);
|
||||
rootScope.broadcast('user_update', userId);
|
||||
}
|
||||
}
|
||||
|
125
src/lib/idb.ts
125
src/lib/idb.ts
@ -225,7 +225,7 @@ export default class IDBStorage {
|
||||
});
|
||||
}
|
||||
|
||||
public save(entryName: string, value: any) {
|
||||
public save(entryName: string | string[], value: any | any[]) {
|
||||
return this.openDatabase().then((db) => {
|
||||
//this.log('save:', entryName, value);
|
||||
|
||||
@ -240,44 +240,52 @@ export default class IDBStorage {
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const transaction = db.transaction([this.storeName], 'readwrite');
|
||||
transaction.onerror = (e) => {
|
||||
handleError(transaction.error);
|
||||
};
|
||||
/* transaction.oncomplete = (e) => {
|
||||
this.log('save: transaction complete:', entryName);
|
||||
}; */
|
||||
|
||||
/* transaction.addEventListener('abort', (e) => {
|
||||
//handleError();
|
||||
this.log.error('IndexedDB: save transaction abort!', transaction.error);
|
||||
}); */
|
||||
|
||||
const objectStore = transaction.objectStore(this.storeName);
|
||||
var request = objectStore.put(value, entryName);
|
||||
} catch(error) {
|
||||
handleError(error);
|
||||
return Promise.reject(error);
|
||||
|
||||
/* this.storageIsAvailable = false;
|
||||
throw error; */
|
||||
}
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
this.log.error('save: request not finished', entryName, request);
|
||||
}, 10000);
|
||||
|
||||
request.onsuccess = (event) => {
|
||||
resolve();
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
try {
|
||||
const transaction = db.transaction([this.storeName], 'readwrite');
|
||||
|
||||
request.onerror = (error) => {
|
||||
transaction.onerror = (e) => {
|
||||
handleError(transaction.error);
|
||||
reject(transaction.error);
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
|
||||
transaction.oncomplete = (e) => {
|
||||
//this.log('save: transaction complete:', entryName);
|
||||
resolve();
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
this.log.error('save: transaction not finished', entryName, transaction);
|
||||
}, 10000);
|
||||
|
||||
/* transaction.addEventListener('abort', (e) => {
|
||||
//handleError();
|
||||
this.log.error('IndexedDB: save transaction abort!', transaction.error);
|
||||
}); */
|
||||
|
||||
const objectStore = transaction.objectStore(this.storeName);
|
||||
|
||||
if(!Array.isArray(entryName)) {
|
||||
entryName = [].concat(entryName);
|
||||
value = [].concat(value);
|
||||
}
|
||||
|
||||
for(let i = 0, length = entryName.length; i < length; ++i) {
|
||||
const request = objectStore.put(value[i], entryName[i]);
|
||||
request.onerror = (error) => {
|
||||
reject(transaction.error);
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}
|
||||
} catch(error) {
|
||||
handleError(error);
|
||||
reject(error);
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
|
||||
/* this.storageIsAvailable = false;
|
||||
throw error; */
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -401,6 +409,51 @@ export default class IDBStorage {
|
||||
});
|
||||
}
|
||||
|
||||
public getAll<T>(): Promise<T[]> {
|
||||
return this.openDatabase().then((db) => {
|
||||
//this.log('getAll pre:', fileName);
|
||||
|
||||
try {
|
||||
const transaction = db.transaction([this.storeName], 'readonly');
|
||||
/* transaction.onabort = (e) => {
|
||||
this.log.error('getAll transaction onabort?', e);
|
||||
}; */
|
||||
const objectStore = transaction.objectStore(this.storeName);
|
||||
var request = objectStore.getAll();
|
||||
|
||||
//this.log.log('IDB getAll:', fileName, request);
|
||||
} catch(err) {
|
||||
this.log.error('getAll error:', err, request, request.error);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
this.log.error('getAll request not finished!', request);
|
||||
reject();
|
||||
}, 3000);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
const result = request.result;
|
||||
if(result === undefined) {
|
||||
reject('NO_ENTRY_FOUND');
|
||||
} /* else if(typeof result === 'string' &&
|
||||
result.substr(0, 5) === 'data:') {
|
||||
resolve(dataUrlToBlob(result));
|
||||
} */else {
|
||||
resolve(result);
|
||||
}
|
||||
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
request.onerror = () => {
|
||||
clearTimeout(timeout);
|
||||
reject();
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* public getAllKeys(): Promise<Array<string>> {
|
||||
console.time('getAllEntries');
|
||||
return this.openDatabase().then((db) => {
|
||||
|
@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
import { DatabaseStore, DatabaseStoreName } from "../config/database";
|
||||
import { throttle } from "../helpers/schedulers";
|
||||
import IDBStorage, { IDBOptions } from "./idb";
|
||||
|
||||
export default class AppStorage<Storage extends Record<string, any>/* Storage extends {[name: string]: any} *//* Storage extends Record<string, any> */> {
|
||||
@ -19,11 +20,29 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
||||
//private cache: Partial<{[key: string]: Storage[typeof key]}> = {};
|
||||
private cache: Partial<Storage> = {};
|
||||
private useStorage = true;
|
||||
private updateKeys: Set<keyof Storage> = new Set();
|
||||
private saveThrottled: () => void;
|
||||
|
||||
constructor(storageOptions: Omit<IDBOptions, 'storeName' | 'stores'> & {stores?: DatabaseStore[], storeName: DatabaseStoreName}) {
|
||||
this.storage = new IDBStorage(storageOptions);
|
||||
|
||||
AppStorage.STORAGES.push(this);
|
||||
|
||||
this.saveThrottled = throttle(async() => {
|
||||
const keys = Array.from(this.updateKeys.values()) as string[];
|
||||
this.updateKeys.clear();
|
||||
|
||||
try {
|
||||
//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.storage.save(key, new Response(value, {headers: {'Content-Type': 'application/json'}}));
|
||||
await this.storage.save(keys, keys.map(key => this.cache[key]));
|
||||
//console.log('setItem: have set', key/* , value */);
|
||||
} catch(e) {
|
||||
//this.useCS = false;
|
||||
console.error('[AS]: set error:', e, keys/* , value */);
|
||||
}
|
||||
}, 50, false);
|
||||
}
|
||||
|
||||
public getCache() {
|
||||
@ -83,16 +102,8 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
||||
console.log('LocalStorage set: stringify time by own stringify:', performance.now() - perf); */
|
||||
|
||||
if(this.useStorage && !onlyLocal) {
|
||||
try {
|
||||
//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.storage.save(key, new Response(value, {headers: {'Content-Type': 'application/json'}}));
|
||||
await this.storage.save(key, value);
|
||||
//console.log('setItem: have set', key/* , value */);
|
||||
} catch(e) {
|
||||
//this.useCS = false;
|
||||
console.error('[AS]: set error:', e, key/* , value */);
|
||||
}
|
||||
this.updateKeys.add(key);
|
||||
this.saveThrottled();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -126,6 +137,7 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
|
||||
storage.useStorage = enabled;
|
||||
|
||||
if(!enabled) {
|
||||
storage.updateKeys.clear();
|
||||
return storage.clear();
|
||||
} else {
|
||||
return storage.set(storage.cache);
|
||||
|
@ -135,7 +135,7 @@
|
||||
389;MK;Macedonia;;0;🇲🇰
|
||||
261;MG;Madagascar;261 XX XX XXX XX;12;🇲🇬
|
||||
265;MW;Malawi;;0;🇲🇼
|
||||
60;MM;Malaysia;;0;🇲🇲
|
||||
60;MY;Malaysia;;0;🇲🇾
|
||||
960;MV;Maldives;;0;🇲🇻
|
||||
223;ML;Mali;223 XXXX XXXX;11;🇲🇱
|
||||
356;MT;Malta;356 XX XX XX XX;11;🇲🇹
|
||||
|
@ -365,14 +365,17 @@
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
html:not(.no-touch) & {
|
||||
/* html:not(.no-touch) & {
|
||||
transform: translateZ(0);
|
||||
} */
|
||||
&:not(.is-hidden) {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
|
||||
html.no-touch &:hover .btn-corner:not(.is-hidden) {
|
||||
/* html.no-touch &:hover .btn-corner:not(.is-hidden) {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
.connection-status {
|
||||
|
@ -150,17 +150,17 @@
|
||||
}
|
||||
|
||||
&.can-add-members {
|
||||
@include respond-to(handhelds) {
|
||||
//@include respond-to(handhelds) {
|
||||
.btn-corner:not(.is-hidden) {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
@include hover() {
|
||||
/* @include hover() {
|
||||
.btn-corner:not(.is-hidden) {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
.search-super {
|
||||
|
Loading…
x
Reference in New Issue
Block a user