tguichat and tgui4.1?

This commit is contained in:
Letter N
2020-08-15 16:08:10 +08:00
parent 90234ca065
commit 15e659fc9c
154 changed files with 9353 additions and 1091 deletions

View File

@@ -6,71 +6,152 @@
* @license MIT
*/
export const STORAGE_NONE = 0;
export const STORAGE_LOCAL_STORAGE = 1;
export const STORAGE_INDEXED_DB = 2;
export const IMPL_MEMORY = 0;
export const IMPL_LOCAL_STORAGE = 1;
export const IMPL_INDEXED_DB = 2;
const createMock = () => {
let storage = {};
const get = key => storage[key];
const set = (key, value) => {
storage[key] = value;
};
const remove = key => {
storage[key] = undefined;
};
const clear = () => {
// NOTE: On IE8, this will probably leak memory if used often.
storage = {};
};
return {
get,
set,
remove,
clear,
engine: STORAGE_NONE,
};
};
const INDEXED_DB_VERSION = 1;
const INDEXED_DB_NAME = 'tgui';
const INDEXED_DB_STORE_NAME = 'storage-v1';
const createLocalStorage = () => {
const get = key => {
const value = localStorage.getItem(key);
if (typeof value !== 'string') {
return;
}
return JSON.parse(value);
};
const set = (key, value) => {
localStorage.setItem(key, JSON.stringify(value));
};
const remove = key => {
localStorage.removeItem(key);
};
const clear = () => {
localStorage.clear();
};
return {
get,
set,
remove,
clear,
engine: STORAGE_LOCAL_STORAGE,
};
};
const READ_ONLY = 'readonly';
const READ_WRITE = 'readwrite';
const testLocalStorage = () => {
// Localstorage can sometimes throw an error, even if DOM storage is not
// disabled in IE11 settings.
// See: https://superuser.com/questions/1080011
const testGeneric = testFn => () => {
try {
return Boolean(window.localStorage && window.localStorage.getItem);
return Boolean(testFn());
}
catch {
return false;
}
};
// Localstorage can sometimes throw an error, even if DOM storage is not
// disabled in IE11 settings.
// See: https://superuser.com/questions/1080011
const testLocalStorage = testGeneric(() => (
window.localStorage && window.localStorage.getItem
));
const testIndexedDb = testGeneric(() => (
(window.indexedDB || window.msIndexedDB)
&& (window.IDBTransaction || window.msIDBTransaction)
));
class MemoryBackend {
constructor() {
this.impl = IMPL_MEMORY;
this.store = {};
}
async get(key) {
return this.store[key];
}
async set(key, value) {
this.store[key] = value;
}
async remove(key) {
this.store[key] = undefined;
}
async clear() {
this.store = {};
}
}
class LocalStorageBackend {
constructor() {
this.impl = IMPL_LOCAL_STORAGE;
this.store = {};
}
async get(key) {
const value = localStorage.getItem(key);
if (typeof value === 'string') {
return JSON.parse(value);
}
}
async set(key, value) {
localStorage.setItem(key, JSON.stringify(value));
}
async remove(key) {
localStorage.removeItem(key);
}
async clear() {
localStorage.clear();
}
}
class IndexedDbBackend {
constructor() {
this.impl = IMPL_INDEXED_DB;
/** @type {Promise<IDBDatabase>} */
this.dbPromise = new Promise((resolve, reject) => {
const indexedDB = window.indexedDB || window.msIndexedDB;
const req = indexedDB.open(INDEXED_DB_NAME, INDEXED_DB_VERSION);
req.onupgradeneeded = () => {
try {
req.result.createObjectStore(INDEXED_DB_STORE_NAME);
}
catch (err) {
reject(new Error('Failed to upgrade IDB: ' + req.error));
}
};
req.onsuccess = () => resolve(req.result);
req.onerror = () => {
reject(new Error('Failed to open IDB: ' + req.error));
};
});
}
getStore(mode) {
return this.dbPromise.then(db => db
.transaction(INDEXED_DB_STORE_NAME, mode)
.objectStore(INDEXED_DB_STORE_NAME));
}
async get(key) {
const store = await this.getStore(READ_ONLY);
return new Promise((resolve, reject) => {
const req = store.get(key);
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
}
async set(key, value) {
// The reason we don't _save_ null is because IE 10 does
// not support saving the `null` type in IndexedDB. How
// ironic, given the bug below!
// See: https://github.com/mozilla/localForage/issues/161
if (value === null) {
value = undefined;
}
// NOTE: We deliberately make this operation transactionless
const store = await this.getStore(READ_WRITE);
store.put(value, key);
}
async remove(key) {
// NOTE: We deliberately make this operation transactionless
const store = await this.getStore(READ_WRITE);
store.delete(key);
}
async clear() {
// NOTE: We deliberately make this operation transactionless
const store = await this.getStore(READ_WRITE);
store.clear();
}
}
export const storage = (
testLocalStorage() && createLocalStorage()
|| createMock()
testIndexedDb() && new IndexedDbBackend()
|| testLocalStorage() && new LocalStorageBackend()
|| new MemoryBackend()
);