Skip to content

Commit 9fc744e

Browse files
committed
TGS Test Merge (#8359)
2 parents 6a0ab17 + a200793 commit 9fc744e

File tree

7 files changed

+159
-5
lines changed

7 files changed

+159
-5
lines changed

code/__DEFINES/subsystems.dm

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@
125125
#define SS_INIT_HUMANS 21
126126
#define SS_INIT_WHO 20
127127
#define SS_INIT_POWER 19
128+
#define SS_INIT_PREDSHIPS 18
128129
#define SS_INIT_INFLUXMCSTATS 12
129130
#define SS_INIT_INFLUXSTATS 11
130131
#define SS_INIT_LIGHTING 10
@@ -139,10 +140,9 @@
139140
#define SS_INIT_INTERIOR 2.7
140141
#define SS_INIT_TECHTREE 2.5
141142
#define SS_INIT_RADIO 2
143+
#define SS_INIT_ASSETS 1
142144
#define SS_INIT_TIMER 100
143145
#define SS_INIT_UNSPECIFIED 0
144-
#define SS_INIT_PREDSHIPS -19
145-
#define SS_INIT_ASSETS -20
146146
#define SS_INIT_TICKER -21
147147
#define SS_INIT_VOTE -23
148148
#define SS_INIT_DATABASE -27

code/controllers/subsystem/tgui.dm

+7
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ SUBSYSTEM_DEF(tgui)
3434
basehtml = replacetextEx(basehtml, "<!-- tgui:inline-polyfill -->", polyfill)
3535
basehtml = replacetext(basehtml, "tgui:stylesheet", MAP_STYLESHEET)
3636

37+
/datum/controller/subsystem/tgui/OnConfigLoad()
38+
if(CONFIG_GET(string/asset_transport) == "webroot")
39+
var/datum/asset_transport/webroot/webroot = SSassets.transport
40+
41+
var/datum/asset_cache_item/item = webroot.register_asset("iframe.html", file("tgui/public/iframe.html"))
42+
basehtml = replacetext(basehtml, "tgui:storagecdn", webroot.get_asset_url("iframe.html", item))
43+
3744
/datum/controller/subsystem/tgui/Shutdown()
3845
close_all_uis()
3946

tgui/global.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ type ByondType = {
163163
* The ByondCSS stylesheet to load into ByondUI components
164164
*/
165165
styleSheet: string;
166+
167+
/**
168+
* The external URL for the IndexedDB IFrame to use as the origin
169+
*/
170+
storageCdn: string;
166171
};
167172

168173
/**

tgui/packages/common/storage.js

+54-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
export const IMPL_MEMORY = 0;
1010
export const IMPL_HUB_STORAGE = 1;
1111
export const IMPL_INDEXED_DB = 2;
12+
export const IMPL_IFRAME_INDEXED_DB = 3;
1213

1314
const INDEXED_DB_VERSION = 1;
1415
const INDEXED_DB_NAME = 'cm-tgui';
@@ -84,6 +85,51 @@ class HubStorageBackend {
8485
}
8586
}
8687

88+
class IFrameIndexedDbBackend {
89+
constructor() {
90+
this.impl = IMPL_IFRAME_INDEXED_DB;
91+
}
92+
93+
async ready() {
94+
const iframe = document.createElement('iframe');
95+
iframe.style.display = 'none';
96+
iframe.src = Byond.storageCdn;
97+
98+
const completePromise = new Promise((resolve) => {
99+
iframe.onload = () => resolve(this);
100+
});
101+
102+
this.iframeWindow = document.body.appendChild(iframe).contentWindow;
103+
104+
return completePromise;
105+
}
106+
107+
async get(key) {
108+
const promise = new Promise((resolve) => {
109+
window.addEventListener('message', (message) => {
110+
if (message.data.key === key) {
111+
resolve(message.data.value);
112+
}
113+
});
114+
});
115+
116+
this.iframeWindow.postMessage({ type: 'get', key: key }, '*');
117+
return promise;
118+
}
119+
120+
async set(key, value) {
121+
this.iframeWindow.postMessage({ type: 'set', key: key, value: value }, '*');
122+
}
123+
124+
async remove(key) {
125+
this.iframeWindow.postMessage({ type: 'remove', key: key }, '*');
126+
}
127+
128+
async clear() {
129+
this.iframeWindow.postMessage({ type: 'clear' }, '*');
130+
}
131+
}
132+
87133
class IndexedDbBackend {
88134
// TODO: Remove with 516
89135
constructor() {
@@ -145,10 +191,16 @@ class IndexedDbBackend {
145191
* Web Storage Proxy object, which selects the best backend available
146192
* depending on the environment.
147193
*/
148-
class StorageProxy {
149-
constructor() {
194+
export class StorageProxy {
195+
constructor(chat) {
150196
this.backendPromise = (async () => {
151197
if (!Byond.TRIDENT) {
198+
if (chat) {
199+
const iframe = new IFrameIndexedDbBackend();
200+
await iframe.ready();
201+
return iframe;
202+
}
203+
152204
if (!testHubStorage()) {
153205
return new Promise((resolve) => {
154206
const listener = () => {

tgui/packages/tgui-panel/chat/middleware.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @license MIT
55
*/
66

7-
import { storage } from 'common/storage';
7+
import { storage as realStorage, StorageProxy } from 'common/storage';
88
import DOMPurify from 'dompurify';
99

1010
import {
@@ -35,6 +35,9 @@ import { selectChat, selectCurrentChatPage } from './selectors';
3535
// List of blacklisted tags
3636
const FORBID_TAGS = ['a', 'iframe', 'link', 'video'];
3737

38+
const storage =
39+
Byond.storageCdn === 'tgui:storagecdn' ? realStorage : new StorageProxy(true);
40+
3841
const saveChatToStorage = async (store) => {
3942
const state = selectChat(store.getState());
4043
const fromIndex = Math.max(

tgui/public/iframe.html

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<!doctype html>
2+
<html>
3+
4+
<head>
5+
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
6+
<meta charset='utf-8' />
7+
8+
<script type='text/javascript'>
9+
const INDEXED_DB_VERSION = 1;
10+
const INDEXED_DB_NAME = 'tgui';
11+
const INDEXED_DB_STORE_NAME = 'storage';
12+
13+
const READ_ONLY = 'readonly';
14+
const READ_WRITE = 'readwrite';
15+
16+
const dbPromise = new Promise((resolve, reject) => {
17+
const indexedDB = window.indexedDB || window.msIndexedDB;
18+
const req = indexedDB.open(INDEXED_DB_NAME, INDEXED_DB_VERSION);
19+
req.onupgradeneeded = () => {
20+
try {
21+
req.result.createObjectStore(INDEXED_DB_STORE_NAME);
22+
} catch (err) {
23+
reject(new Error('Failed to upgrade IDB: ' + req.error));
24+
}
25+
};
26+
req.onsuccess = () => resolve(req.result);
27+
req.onerror = () => {
28+
reject(new Error('Failed to open IDB: ' + req.error));
29+
};
30+
});
31+
32+
window.addEventListener('message', (messageEvent) => {
33+
switch (messageEvent.data.type) {
34+
case 'get':
35+
get(event.data.key).then((value) => {
36+
messageEvent.source.postMessage({key: messageEvent.data.key, value: value}, "*")
37+
});
38+
break;
39+
case 'set':
40+
set(messageEvent.data.key, messageEvent.data.value);
41+
break;
42+
case 'remove':
43+
remove(messageEvent.data.key);
44+
break;
45+
case 'clear':
46+
clear();
47+
break;
48+
default:
49+
break;
50+
}
51+
});
52+
53+
const getStore = async (mode) => {
54+
return dbPromise.then((db) => db
55+
.transaction(INDEXED_DB_STORE_NAME, mode)
56+
.objectStore(INDEXED_DB_STORE_NAME));
57+
};
58+
59+
const get = async (key) => {
60+
const store = await getStore(READ_ONLY);
61+
return new Promise((resolve, reject) => {
62+
const req = store.get(key);
63+
req.onsuccess = () => resolve(req.result);
64+
req.onerror = () => reject(req.error);
65+
});
66+
};
67+
68+
const set = async (key, value) => {
69+
const store = await getStore(READ_WRITE);
70+
store.put(value, key);
71+
};
72+
73+
const remove = async (key) => {
74+
const store = await getStore(READ_WRITE);
75+
store.delete(key);
76+
};
77+
78+
const clear = async () => {
79+
const store = await getStore(READ_WRITE);
80+
store.clear();
81+
};
82+
</script>
83+
</head>
84+
85+
</html>

tgui/public/tgui.html

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
Byond.styleSheet = "tgui:stylesheet"
4444

45+
Byond.storageCdn = "tgui:storagecdn"
46+
4547
// Backwards compatibility
4648
window.__windowId__ = Byond.windowId;
4749

0 commit comments

Comments
 (0)