mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-26 01:03:06 +00:00
this is a bit of https://github.com/cmss13-devs/cmss13/pull/8646 https://github.com/cmss13-devs/cmss13/pull/8875 https://github.com/cmss13-devs/cmss13/pull/8606 https://github.com/cmss13-devs/cmss13/pull/8607 https://github.com/cmss13-devs/cmss13/pull/8359 https://github.com/cmss13-devs/cmss13/pull/7860 ( and thus https://github.com/ParadiseSS13/Paradise/pull/25105 https://github.com/ParadiseSS13/Paradise/pull/25205 https://github.com/ParadiseSS13/Paradise/pull/25363 https://github.com/ParadiseSS13/Paradise/pull/26423 and https://github.com/ParadiseSS13/Paradise/pull/26433 ) https://github.com/tgstation/tgstation/pull/89766 in order to work properly - using the efficient storage method, instead of the byond json method - github pages needs to be enabled and built from the gh-pages branch. because yeah --------- Co-authored-by: harryob <55142896+harryob@users.noreply.github.com>
214 lines
6.6 KiB
HTML
214 lines
6.6 KiB
HTML
<!doctype html>
|
|
<html>
|
|
|
|
<head>
|
|
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
|
|
<meta charset='utf-8' />
|
|
|
|
<script type='text/javascript'>
|
|
const INDEXED_DB_VERSION = 2;
|
|
const INDEXED_DB_NAME = 'tgui';
|
|
const INDEXED_DB_STORE_NAME = 'storage';
|
|
|
|
const READ_ONLY = 'readonly';
|
|
const READ_WRITE = 'readwrite';
|
|
|
|
let maxStoredMessages = 2500;
|
|
let startFrom = 0;
|
|
let writeFrom = 0;
|
|
|
|
const dbPromise = new Promise((resolve, reject) => {
|
|
const indexedDB = window.indexedDB || window.msIndexedDB;
|
|
const req = indexedDB.open(INDEXED_DB_NAME, INDEXED_DB_VERSION);
|
|
req.onupgradeneeded = (event) => {
|
|
try {
|
|
|
|
if(event.oldVersion < 1) {
|
|
req.result.createObjectStore(INDEXED_DB_STORE_NAME);
|
|
}
|
|
|
|
if(event.oldVersion < 2) {
|
|
req.result.createObjectStore("ring");
|
|
req.result.createObjectStore("messages", { autoIncrement: true }).transaction.oncomplete = async () => {
|
|
const trans = req.result.transaction("messages", READ_WRITE).objectStore("messages");
|
|
|
|
startFrom = await promiseForRequest(trans.add(null)) - 1;
|
|
for (let index = 0; index < maxStoredMessages - 1; index++) {
|
|
await promiseForRequest(trans.add(null));
|
|
}
|
|
}
|
|
}
|
|
|
|
} catch (err) {
|
|
reject(new Error('Failed to upgrade IDB: ' + req.error));
|
|
}
|
|
};
|
|
req.onsuccess = async () => {
|
|
const storage = req.result.transaction(["ring", "messages", INDEXED_DB_STORE_NAME], "readonly")
|
|
|
|
writeFrom = await promiseForRequest(storage.objectStore("ring").get("value")) || 0;
|
|
|
|
const panelSettings = await promiseForRequest(storage.objectStore(INDEXED_DB_STORE_NAME).get("panel-settings"))
|
|
maxStoredMessages = panelSettings?.maxMessages || 2500;
|
|
|
|
const messageStore = storage.objectStore("messages");
|
|
|
|
const messageCount = await promiseForRequest(messageStore.count());
|
|
if(messageCount !== maxStoredMessages) {
|
|
await alterMessageRing(req.result);
|
|
}
|
|
|
|
let cursorReq = await promiseForRequest(messageStore.openCursor());
|
|
let cursor = await(cursorReq);
|
|
startFrom = cursor.key - 1;
|
|
|
|
resolve(req.result);
|
|
};
|
|
req.onerror = () => {
|
|
reject(new Error('Failed to open IDB: ' + req.error));
|
|
};
|
|
});
|
|
|
|
const alterMessageRing = async (db) => {
|
|
db = db ?? await dbPromise;
|
|
|
|
const existingMessages = (await getSavedMessages(db)).slice(0, maxStoredMessages);
|
|
|
|
const trans = db.transaction("messages", READ_WRITE).objectStore("messages");
|
|
|
|
await promiseForRequest(trans.clear());
|
|
|
|
startFrom = await promiseForRequest(trans.add(null)) - 1;
|
|
for (let index = 0; index < maxStoredMessages - 1; index++) {
|
|
await promiseForRequest(trans.add(null));
|
|
}
|
|
|
|
writeFrom = startFrom;
|
|
|
|
await addMessageBatch(existingMessages, db);
|
|
}
|
|
|
|
window.addEventListener('message', (messageEvent) => {
|
|
switch (messageEvent.data.type) {
|
|
case 'ping':
|
|
messageEvent.source.postMessage(true, "*");
|
|
break;
|
|
case 'get':
|
|
get(messageEvent.data.key).then((value) => {
|
|
messageEvent.source.postMessage({key: messageEvent.data.key, value: value}, "*");
|
|
});
|
|
break;
|
|
case 'set':
|
|
set(messageEvent.data.key, messageEvent.data.value);
|
|
break;
|
|
case 'remove':
|
|
remove(messageEvent.data.key);
|
|
break;
|
|
case 'clear':
|
|
clear();
|
|
break;
|
|
case 'setNumberStored':
|
|
maxStoredMessages = messageEvent.data.newMax;
|
|
alterMessageRing();
|
|
break;
|
|
case 'processChatMessages':
|
|
addMessageBatch(messageEvent.data.messages);
|
|
break;
|
|
case 'getChatMessages':
|
|
getSavedMessages().then((messages) => {
|
|
messageEvent.source.postMessage({messages: messages}, "*");
|
|
})
|
|
default:
|
|
break;
|
|
}
|
|
});
|
|
|
|
const addMessageBatch = async (messages, db) => {
|
|
if(!messages || !messages.length) return;
|
|
|
|
const database = db ?? await dbPromise;
|
|
|
|
const trans = database.transaction("messages", READ_WRITE).objectStore("messages");
|
|
|
|
console.log(writeFrom, startFrom);
|
|
|
|
let cursorReq = trans.openCursor(IDBKeyRange.bound(writeFrom, writeFrom + messages.length, true));
|
|
let cursor = await promiseForRequest(cursorReq);
|
|
|
|
for (let index = 0; index < messages.length; index++) {
|
|
const message = messages[index];
|
|
|
|
cursor.update(message);
|
|
writeFrom = cursor.key;
|
|
|
|
if(cursor.key === startFrom + maxStoredMessages) {
|
|
writeFrom = startFrom;
|
|
|
|
cursorReq = trans.openCursor(IDBKeyRange.bound(startFrom, startFrom + messages.length - index + 1, true));
|
|
cursor = await promiseForRequest(cursorReq);
|
|
} else {
|
|
cursor.continue();
|
|
await promiseForRequest(cursorReq);
|
|
}
|
|
}
|
|
|
|
database.transaction("ring", READ_WRITE).objectStore("ring").put(writeFrom, "value");
|
|
}
|
|
|
|
const getSavedMessages = async (db) => {
|
|
const database = db ?? await dbPromise;
|
|
|
|
const trans = database.transaction("messages", READ_ONLY).objectStore("messages");
|
|
const messyMessages = await promiseForRequest(trans.getAll());
|
|
|
|
const upTo = messyMessages.splice(0, writeFrom);
|
|
|
|
if(messyMessages[0] === null) {
|
|
return upTo;
|
|
}
|
|
|
|
const messages = messyMessages.concat(upTo);
|
|
return messages;
|
|
}
|
|
|
|
const getStore = async (mode) => {
|
|
return dbPromise.then((db) => db
|
|
.transaction(INDEXED_DB_STORE_NAME, mode)
|
|
.objectStore(INDEXED_DB_STORE_NAME));
|
|
};
|
|
|
|
const get = async (key) => {
|
|
const store = await getStore(READ_ONLY);
|
|
return new Promise((resolve, reject) => {
|
|
const req = store.get(key);
|
|
req.onsuccess = () => resolve(req.result);
|
|
req.onerror = () => reject(req.error);
|
|
});
|
|
};
|
|
|
|
const set = async (key, value) => {
|
|
const store = await getStore(READ_WRITE);
|
|
store.put(value, key);
|
|
};
|
|
|
|
const remove = async (key) => {
|
|
const store = await getStore(READ_WRITE);
|
|
store.delete(key);
|
|
};
|
|
|
|
const clear = async () => {
|
|
const store = await getStore(READ_WRITE);
|
|
store.clear();
|
|
};
|
|
|
|
const promiseForRequest = (request) => {
|
|
return new Promise((resolve, reject) => {
|
|
request.onsuccess = () => { resolve(request.result); };
|
|
request.onerror = () => { reject(request.error); };
|
|
});
|
|
}
|
|
</script>
|
|
</head>
|
|
|
|
</html>
|