bc-deeplib 2.4.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deeplib.d.ts +133 -107
- package/dist/deeplib.js +493 -596
- package/dist/deeplib.js.map +4 -4
- package/dist/index.js +2626 -0
- package/dist/public/dl_translations/en.lang +4 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/vendored_types/declarations.d.ts +10 -1
- package/dist/vendored_types/utility.d.ts +3 -1
- package/lib/build.js +15 -13
- package/package.json +10 -7
package/dist/deeplib.js
CHANGED
|
@@ -1,203 +1,5 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
1
|
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
|
|
28
|
-
// node_modules/.pnpm/bondage-club-mod-sdk@1.2.0/node_modules/bondage-club-mod-sdk/dist/bcmodsdk.js
|
|
29
|
-
var require_bcmodsdk = __commonJS({
|
|
30
|
-
"node_modules/.pnpm/bondage-club-mod-sdk@1.2.0/node_modules/bondage-club-mod-sdk/dist/bcmodsdk.js"(exports) {
|
|
31
|
-
var bcModSdk = (function() {
|
|
32
|
-
"use strict";
|
|
33
|
-
const o = "1.2.0";
|
|
34
|
-
function e(o2) {
|
|
35
|
-
alert("Mod ERROR:\n" + o2);
|
|
36
|
-
const e2 = new Error(o2);
|
|
37
|
-
throw console.error(e2), e2;
|
|
38
|
-
}
|
|
39
|
-
__name(e, "e");
|
|
40
|
-
const t = new TextEncoder();
|
|
41
|
-
function n(o2) {
|
|
42
|
-
return !!o2 && "object" == typeof o2 && !Array.isArray(o2);
|
|
43
|
-
}
|
|
44
|
-
__name(n, "n");
|
|
45
|
-
function r(o2) {
|
|
46
|
-
const e2 = /* @__PURE__ */ new Set();
|
|
47
|
-
return o2.filter(((o3) => !e2.has(o3) && e2.add(o3)));
|
|
48
|
-
}
|
|
49
|
-
__name(r, "r");
|
|
50
|
-
const i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set();
|
|
51
|
-
function c(o2) {
|
|
52
|
-
a.has(o2) || (a.add(o2), console.warn(o2));
|
|
53
|
-
}
|
|
54
|
-
__name(c, "c");
|
|
55
|
-
function s(o2) {
|
|
56
|
-
const e2 = [], t2 = /* @__PURE__ */ new Map(), n2 = /* @__PURE__ */ new Set();
|
|
57
|
-
for (const r3 of f.values()) {
|
|
58
|
-
const i3 = r3.patching.get(o2.name);
|
|
59
|
-
if (i3) {
|
|
60
|
-
e2.push(...i3.hooks);
|
|
61
|
-
for (const [e3, a2] of i3.patches.entries()) t2.has(e3) && t2.get(e3) !== a2 && c(`ModSDK: Mod '${r3.name}' is patching function ${o2.name} with same pattern that is already applied by different mod, but with different pattern:
|
|
62
|
-
Pattern:
|
|
63
|
-
${e3}
|
|
64
|
-
Patch1:
|
|
65
|
-
${t2.get(e3) || ""}
|
|
66
|
-
Patch2:
|
|
67
|
-
${a2}`), t2.set(e3, a2), n2.add(r3.name);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
e2.sort(((o3, e3) => e3.priority - o3.priority));
|
|
71
|
-
const r2 = (function(o3, e3) {
|
|
72
|
-
if (0 === e3.size) return o3;
|
|
73
|
-
let t3 = o3.toString().replaceAll("\r\n", "\n");
|
|
74
|
-
for (const [n3, r3] of e3.entries()) t3.includes(n3) || c(`ModSDK: Patching ${o3.name}: Patch ${n3} not applied`), t3 = t3.replaceAll(n3, r3);
|
|
75
|
-
return (0, eval)(`(${t3})`);
|
|
76
|
-
})(o2.original, t2);
|
|
77
|
-
let i2 = /* @__PURE__ */ __name(function(e3) {
|
|
78
|
-
var t3, i3;
|
|
79
|
-
const a2 = null === (i3 = (t3 = m.errorReporterHooks).hookChainExit) || void 0 === i3 ? void 0 : i3.call(t3, o2.name, n2), c2 = r2.apply(this, e3);
|
|
80
|
-
return null == a2 || a2(), c2;
|
|
81
|
-
}, "i");
|
|
82
|
-
for (let t3 = e2.length - 1; t3 >= 0; t3--) {
|
|
83
|
-
const n3 = e2[t3], r3 = i2;
|
|
84
|
-
i2 = /* @__PURE__ */ __name(function(e3) {
|
|
85
|
-
var t4, i3;
|
|
86
|
-
const a2 = null === (i3 = (t4 = m.errorReporterHooks).hookEnter) || void 0 === i3 ? void 0 : i3.call(t4, o2.name, n3.mod), c2 = n3.hook.apply(this, [e3, (o3) => {
|
|
87
|
-
if (1 !== arguments.length || !Array.isArray(e3)) throw new Error(`Mod ${n3.mod} failed to call next hook: Expected args to be array, got ${typeof o3}`);
|
|
88
|
-
return r3.call(this, o3);
|
|
89
|
-
}]);
|
|
90
|
-
return null == a2 || a2(), c2;
|
|
91
|
-
}, "i");
|
|
92
|
-
}
|
|
93
|
-
return { hooks: e2, patches: t2, patchesSources: n2, enter: i2, final: r2 };
|
|
94
|
-
}
|
|
95
|
-
__name(s, "s");
|
|
96
|
-
function l(o2, e2 = false) {
|
|
97
|
-
let r2 = i.get(o2);
|
|
98
|
-
if (r2) e2 && (r2.precomputed = s(r2));
|
|
99
|
-
else {
|
|
100
|
-
let e3 = window;
|
|
101
|
-
const a2 = o2.split(".");
|
|
102
|
-
for (let t2 = 0; t2 < a2.length - 1; t2++) if (e3 = e3[a2[t2]], !n(e3)) throw new Error(`ModSDK: Function ${o2} to be patched not found; ${a2.slice(0, t2 + 1).join(".")} is not object`);
|
|
103
|
-
const c2 = e3[a2[a2.length - 1]];
|
|
104
|
-
if ("function" != typeof c2) throw new Error(`ModSDK: Function ${o2} to be patched not found`);
|
|
105
|
-
const l2 = (function(o3) {
|
|
106
|
-
let e4 = -1;
|
|
107
|
-
for (const n2 of t.encode(o3)) {
|
|
108
|
-
let o4 = 255 & (e4 ^ n2);
|
|
109
|
-
for (let e5 = 0; e5 < 8; e5++) o4 = 1 & o4 ? -306674912 ^ o4 >>> 1 : o4 >>> 1;
|
|
110
|
-
e4 = e4 >>> 8 ^ o4;
|
|
111
|
-
}
|
|
112
|
-
return ((-1 ^ e4) >>> 0).toString(16).padStart(8, "0").toUpperCase();
|
|
113
|
-
})(c2.toString().replaceAll("\r\n", "\n")), d2 = { name: o2, original: c2, originalHash: l2 };
|
|
114
|
-
r2 = Object.assign(Object.assign({}, d2), { precomputed: s(d2), router: /* @__PURE__ */ __name(() => {
|
|
115
|
-
}, "router"), context: e3, contextProperty: a2[a2.length - 1] }), r2.router = /* @__PURE__ */ (function(o3) {
|
|
116
|
-
return function(...e4) {
|
|
117
|
-
return o3.precomputed.enter.apply(this, [e4]);
|
|
118
|
-
};
|
|
119
|
-
})(r2), i.set(o2, r2), e3[r2.contextProperty] = r2.router;
|
|
120
|
-
}
|
|
121
|
-
return r2;
|
|
122
|
-
}
|
|
123
|
-
__name(l, "l");
|
|
124
|
-
function d() {
|
|
125
|
-
for (const o2 of i.values()) o2.precomputed = s(o2);
|
|
126
|
-
}
|
|
127
|
-
__name(d, "d");
|
|
128
|
-
function p() {
|
|
129
|
-
const o2 = /* @__PURE__ */ new Map();
|
|
130
|
-
for (const [e2, t2] of i) o2.set(e2, { name: e2, original: t2.original, originalHash: t2.originalHash, sdkEntrypoint: t2.router, currentEntrypoint: t2.context[t2.contextProperty], hookedByMods: r(t2.precomputed.hooks.map(((o3) => o3.mod))), patchedByMods: Array.from(t2.precomputed.patchesSources) });
|
|
131
|
-
return o2;
|
|
132
|
-
}
|
|
133
|
-
__name(p, "p");
|
|
134
|
-
const f = /* @__PURE__ */ new Map();
|
|
135
|
-
function u(o2) {
|
|
136
|
-
f.get(o2.name) !== o2 && e(`Failed to unload mod '${o2.name}': Not registered`), f.delete(o2.name), o2.loaded = false, d();
|
|
137
|
-
}
|
|
138
|
-
__name(u, "u");
|
|
139
|
-
function g(o2, t2) {
|
|
140
|
-
o2 && "object" == typeof o2 || e("Failed to register mod: Expected info object, got " + typeof o2), "string" == typeof o2.name && o2.name || e("Failed to register mod: Expected name to be non-empty string, got " + typeof o2.name);
|
|
141
|
-
let r2 = `'${o2.name}'`;
|
|
142
|
-
"string" == typeof o2.fullName && o2.fullName || e(`Failed to register mod ${r2}: Expected fullName to be non-empty string, got ${typeof o2.fullName}`), r2 = `'${o2.fullName} (${o2.name})'`, "string" != typeof o2.version && e(`Failed to register mod ${r2}: Expected version to be string, got ${typeof o2.version}`), o2.repository || (o2.repository = void 0), void 0 !== o2.repository && "string" != typeof o2.repository && e(`Failed to register mod ${r2}: Expected repository to be undefined or string, got ${typeof o2.version}`), null == t2 && (t2 = {}), t2 && "object" == typeof t2 || e(`Failed to register mod ${r2}: Expected options to be undefined or object, got ${typeof t2}`);
|
|
143
|
-
const i2 = true === t2.allowReplace, a2 = f.get(o2.name);
|
|
144
|
-
a2 && (a2.allowReplace && i2 || e(`Refusing to load mod ${r2}: it is already loaded and doesn't allow being replaced.
|
|
145
|
-
Was the mod loaded multiple times?`), u(a2));
|
|
146
|
-
const c2 = /* @__PURE__ */ __name((o3) => {
|
|
147
|
-
let e2 = g2.patching.get(o3.name);
|
|
148
|
-
return e2 || (e2 = { hooks: [], patches: /* @__PURE__ */ new Map() }, g2.patching.set(o3.name, e2)), e2;
|
|
149
|
-
}, "c"), s2 = /* @__PURE__ */ __name((o3, t3) => (...n2) => {
|
|
150
|
-
var i3, a3;
|
|
151
|
-
const c3 = null === (a3 = (i3 = m.errorReporterHooks).apiEndpointEnter) || void 0 === a3 ? void 0 : a3.call(i3, o3, g2.name);
|
|
152
|
-
g2.loaded || e(`Mod ${r2} attempted to call SDK function after being unloaded`);
|
|
153
|
-
const s3 = t3(...n2);
|
|
154
|
-
return null == c3 || c3(), s3;
|
|
155
|
-
}, "s"), p2 = { unload: s2("unload", (() => u(g2))), hookFunction: s2("hookFunction", ((o3, t3, n2) => {
|
|
156
|
-
"string" == typeof o3 && o3 || e(`Mod ${r2} failed to patch a function: Expected function name string, got ${typeof o3}`);
|
|
157
|
-
const i3 = l(o3), a3 = c2(i3);
|
|
158
|
-
"number" != typeof t3 && e(`Mod ${r2} failed to hook function '${o3}': Expected priority number, got ${typeof t3}`), "function" != typeof n2 && e(`Mod ${r2} failed to hook function '${o3}': Expected hook function, got ${typeof n2}`);
|
|
159
|
-
const s3 = { mod: g2.name, priority: t3, hook: n2 };
|
|
160
|
-
return a3.hooks.push(s3), d(), () => {
|
|
161
|
-
const o4 = a3.hooks.indexOf(s3);
|
|
162
|
-
o4 >= 0 && (a3.hooks.splice(o4, 1), d());
|
|
163
|
-
};
|
|
164
|
-
})), patchFunction: s2("patchFunction", ((o3, t3) => {
|
|
165
|
-
"string" == typeof o3 && o3 || e(`Mod ${r2} failed to patch a function: Expected function name string, got ${typeof o3}`);
|
|
166
|
-
const i3 = l(o3), a3 = c2(i3);
|
|
167
|
-
n(t3) || e(`Mod ${r2} failed to patch function '${o3}': Expected patches object, got ${typeof t3}`);
|
|
168
|
-
for (const [n2, i4] of Object.entries(t3)) "string" == typeof i4 ? a3.patches.set(n2, i4) : null === i4 ? a3.patches.delete(n2) : e(`Mod ${r2} failed to patch function '${o3}': Invalid format of patch '${n2}'`);
|
|
169
|
-
d();
|
|
170
|
-
})), removePatches: s2("removePatches", ((o3) => {
|
|
171
|
-
"string" == typeof o3 && o3 || e(`Mod ${r2} failed to patch a function: Expected function name string, got ${typeof o3}`);
|
|
172
|
-
const t3 = l(o3);
|
|
173
|
-
c2(t3).patches.clear(), d();
|
|
174
|
-
})), callOriginal: s2("callOriginal", ((o3, t3, n2) => {
|
|
175
|
-
"string" == typeof o3 && o3 || e(`Mod ${r2} failed to call a function: Expected function name string, got ${typeof o3}`);
|
|
176
|
-
const i3 = l(o3);
|
|
177
|
-
return Array.isArray(t3) || e(`Mod ${r2} failed to call a function: Expected args array, got ${typeof t3}`), i3.original.apply(null != n2 ? n2 : globalThis, t3);
|
|
178
|
-
})), getOriginalHash: s2("getOriginalHash", ((o3) => {
|
|
179
|
-
"string" == typeof o3 && o3 || e(`Mod ${r2} failed to get hash: Expected function name string, got ${typeof o3}`);
|
|
180
|
-
return l(o3).originalHash;
|
|
181
|
-
})) }, g2 = { name: o2.name, fullName: o2.fullName, version: o2.version, repository: o2.repository, allowReplace: i2, api: p2, loaded: true, patching: /* @__PURE__ */ new Map() };
|
|
182
|
-
return f.set(o2.name, g2), Object.freeze(p2);
|
|
183
|
-
}
|
|
184
|
-
__name(g, "g");
|
|
185
|
-
function h() {
|
|
186
|
-
const o2 = [];
|
|
187
|
-
for (const e2 of f.values()) o2.push({ name: e2.name, fullName: e2.fullName, version: e2.version, repository: e2.repository });
|
|
188
|
-
return o2;
|
|
189
|
-
}
|
|
190
|
-
__name(h, "h");
|
|
191
|
-
let m;
|
|
192
|
-
const y = void 0 === window.bcModSdk ? window.bcModSdk = (function() {
|
|
193
|
-
const e2 = { version: o, apiVersion: 1, registerMod: g, getModsInfo: h, getPatchingInfo: p, errorReporterHooks: Object.seal({ apiEndpointEnter: null, hookEnter: null, hookChainExit: null }) };
|
|
194
|
-
return m = e2, Object.freeze(e2);
|
|
195
|
-
})() : (n(window.bcModSdk) || e("Failed to init Mod SDK: Name already in use"), 1 !== window.bcModSdk.apiVersion && e(`Failed to init Mod SDK: Different version already loaded ('1.2.0' vs '${window.bcModSdk.version}')`), window.bcModSdk.version !== o && alert(`Mod SDK warning: Loading different but compatible versions ('1.2.0' vs '${window.bcModSdk.version}')
|
|
196
|
-
One of mods you are using is using an old version of SDK. It will work for now but please inform author to update`), window.bcModSdk);
|
|
197
|
-
return "undefined" != typeof exports && (Object.defineProperty(exports, "__esModule", { value: true }), exports.default = y), y;
|
|
198
|
-
})();
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
3
|
|
|
202
4
|
// src/base/base_module.ts
|
|
203
5
|
var BaseModule = class {
|
|
@@ -226,10 +28,8 @@ var BaseModule = class {
|
|
|
226
28
|
* If no settings exist yet, registers default settings first.
|
|
227
29
|
*/
|
|
228
30
|
get settings() {
|
|
229
|
-
|
|
230
|
-
if (!this.settingsStorage) return {};
|
|
31
|
+
if (!this.settingsStorage) return null;
|
|
231
32
|
if (!modStorage.playerStorage) {
|
|
232
|
-
Player[modName] = {};
|
|
233
33
|
this.registerDefaultSettings(modStorage.playerStorage);
|
|
234
34
|
} else if (!modStorage.playerStorage[this.settingsStorage]) {
|
|
235
35
|
this.registerDefaultSettings(modStorage.playerStorage);
|
|
@@ -241,16 +41,13 @@ var BaseModule = class {
|
|
|
241
41
|
* Automatically initializes storage and defaults if they don't exist.
|
|
242
42
|
*/
|
|
243
43
|
set settings(value) {
|
|
244
|
-
const modName = ModSdkManager.ModInfo.name;
|
|
245
|
-
const storage = new ModStorage(modName);
|
|
246
44
|
if (!this.settingsStorage) return;
|
|
247
|
-
if (!
|
|
248
|
-
Player[modName] = {};
|
|
45
|
+
if (!modStorage.playerStorage) {
|
|
249
46
|
this.registerDefaultSettings(modStorage.playerStorage);
|
|
250
|
-
} else if (!
|
|
47
|
+
} else if (!modStorage.playerStorage[this.settingsStorage]) {
|
|
251
48
|
this.registerDefaultSettings(modStorage.playerStorage);
|
|
252
49
|
}
|
|
253
|
-
|
|
50
|
+
modStorage.playerStorage[this.settingsStorage] = value;
|
|
254
51
|
}
|
|
255
52
|
/**
|
|
256
53
|
* Initializes the module.
|
|
@@ -406,7 +203,7 @@ var BaseSubscreen = class _BaseSubscreen {
|
|
|
406
203
|
this.pageStructure.forEach((item, ix) => {
|
|
407
204
|
item.forEach((setting) => {
|
|
408
205
|
const element = ElementWrap(`${setting.id}-container`) ?? ElementWrap(`${setting.id}`);
|
|
409
|
-
if (ix
|
|
206
|
+
if (ix !== _BaseSubscreen.currentPage - 1) {
|
|
410
207
|
if (element) domUtil.hide(element);
|
|
411
208
|
} else {
|
|
412
209
|
if (element) domUtil.unhide(element);
|
|
@@ -474,7 +271,7 @@ var BaseSubscreen = class _BaseSubscreen {
|
|
|
474
271
|
if (this.options.doShowTitle) {
|
|
475
272
|
const subscreenTitle = advElement.createLabel({
|
|
476
273
|
id: "deeplib-subscreen-title",
|
|
477
|
-
label: getText(`${this.options.name}.title`).replace("$ModVersion",
|
|
274
|
+
label: getText(`${this.options.name}.title`).replace("$ModVersion", MOD_VERSION_CAPTION)
|
|
478
275
|
});
|
|
479
276
|
layout.appendToSubscreen(subscreenTitle);
|
|
480
277
|
}
|
|
@@ -576,7 +373,7 @@ var BaseSubscreen = class _BaseSubscreen {
|
|
|
576
373
|
ElementSetSize(settingsDiv, this.options.settingsWidth ?? 1e3 + offset, 660);
|
|
577
374
|
if (this.options.doShowTitle) {
|
|
578
375
|
ElementSetPosition("deeplib-subscreen-title", 530 - offset, 75);
|
|
579
|
-
ElementSetSize("deeplib-subscreen-title", 800,
|
|
376
|
+
ElementSetSize("deeplib-subscreen-title", 800, 90);
|
|
580
377
|
}
|
|
581
378
|
ElementSetPosition("deeplib-nav-menu", 1905, 75, "top-right");
|
|
582
379
|
ElementSetSize("deeplib-nav-menu", null, 90);
|
|
@@ -677,6 +474,8 @@ var styles_default = `.deeplib-subscreen,
|
|
|
677
474
|
color: var(--deeplib-text-color);
|
|
678
475
|
user-select: none;
|
|
679
476
|
pointer-events: none;
|
|
477
|
+
display: flex;
|
|
478
|
+
align-items: center;
|
|
680
479
|
}
|
|
681
480
|
|
|
682
481
|
.deeplib-text {
|
|
@@ -949,52 +748,76 @@ var styles_default = `.deeplib-subscreen,
|
|
|
949
748
|
height: 100dvh;
|
|
950
749
|
background-color: rgba(0, 0, 0, 0.5);
|
|
951
750
|
}
|
|
952
|
-
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VSb290IjoiL21udC9zaGluZG93cy9TdHVmZi9Db2RlL2JjL0JDLURlZXBMaWIvc3JjL3N0eWxlcyIsInNvdXJjZXMiOlsidmFycy5zY3NzIiwiYnV0dG9ucy5zY3NzIiwiZWxlbWVudHMuc2NzcyIsImlucHV0cy5zY3NzIiwibWVzc2FnZXMuc2NzcyIsIm1vZGFsLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQTtFQUVFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUNkRjtFQUNFO0VBQ0E7RUFDQTs7QUFFQTtFQUVFOztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUVBO0VBQ0E7RUFDQTs7QUFHRjtFQUNFOztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7O0FBR0Y7RUFDRTs7O0FDM0NKO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7OztBQUdGO0VBQ0U7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUdFO0VBQ0U7RUFDQTs7QUFISjtFQU1FO0VBQ0E7O0FBR0Y7RUFDRTtFQUNBOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7OztBQUlKO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7OztBQ2pISjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7OztBQUtOO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFOztBQUdGO0VBQ0U7RUFDQTs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7OztBQU9SO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFHRjtFQUNFOzs7QUN2Rko7RUFDRTtFQUNBOzs7QUFHRjtBQUFBO0VBRUU7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7QUFBQTtFQUVFOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTs7O0FDN0JGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7RUFDQTtFQUNBOztBQUdGO0VBQ0U7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTs7QUFLTjtFQUNFO0VBQ0E7RUFDQTtFQUNBOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBIiwic291cmNlc0NvbnRlbnQiOlsiLmRlZXBsaWItc3Vic2NyZWVuLFxuLmRlZXBsaWItbW9kYWwge1xuICAtLWRlZXBsaWItYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tdG1kLW1haW4sIHdoaXRlKTtcbiAgLS1kZWVwbGliLWVsZW1lbnQtY29sb3I6IHZhcigtLXRtZC1lbGVtZW50LCB3aGl0ZSk7XG4gIC0tZGVlcGxpYi1lbGVtZW50LWhvdmVyLWNvbG9yOiB2YXIoLS10bWQtZWxlbWVudC1ob3ZlciwgY3lhbik7XG4gIC0tZGVlcGxpYi1hY2NlbnQtY29sb3I6IHZhcigtLXRtZC1hY2NlbnQsICNGRkZGODgpO1xuICAtLWRlZXBsaWItYmxvY2tlZC1jb2xvcjogdmFyKC0tdG1kLWJsb2NrZWQsIHJlZCk7XG4gIC0tZGVlcGxpYi10ZXh0LWNvbG9yOiB2YXIoLS10bWQtdGV4dCwgYmxhY2spO1xuICAtLWRlZXBsaWItaWNvbi1jb2xvcjogdmFyKC0tdG1kLWFjY2VudCwgYmxhY2spO1xuICAtLWRlZXBsaWItaWNvbi1ob3Zlci1jb2xvcjogdmFyKC0tdG1kLWFjY2VudC1ob3ZlciwgYmxhY2spO1xuICAtLWRlZXBsaWItYm9yZGVyLWNvbG9yOiB2YXIoLS10bWQtYWNjZW50LCBibGFjayk7XG4gIC0tZGVlcGxpYi1ib3JkZXItd2lkdGg6IG1pbigwLjJ2aCwgMC4xdncpO1xuICAtLWRlZXBsaWItYm9yZGVyLXdpZHRoOiBtaW4oMC4yZHZoLCAwLjFkdncpO1xuICAtLWRlZXBsaWItYm9yZGVyLXJhZGl1czogbWluKDF2aCwgMC41dncpO1xuICAtLWRlZXBsaWItYm9yZGVyLXJhZGl1czogbWluKDFkdmgsIDAuNWR2dyk7XG59XG4iLCIuZGVlcGxpYi1idXR0b24ge1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogMTAwJTtcblxuICAmLmJ1dHRvbi1zdHlsaW5nLFxuICAmLmJ1dHRvbi1zdHlsaW5nOjpiZWZvcmUge1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIH1cblxuICBpbWcge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDAlO1xuICAgIGxlZnQ6IDAlO1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMTAwJTtcbiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBsZWZ0O1xuICAgIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItaWNvbi1jb2xvcik7XG4gICAgYmFja2dyb3VuZC1ibGVuZC1tb2RlOiBtdWx0aXBseTtcbiAgICBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47XG4gICAgbWFzay1wb3NpdGlvbjogbGVmdDtcbiAgICBtYXNrLXNpemU6IGNvbnRhaW47XG4gICAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcbiAgICBtYXNrLXJlcGVhdDogbm8tcmVwZWF0O1xuICAgIGNvbG9yOiB0cmFuc3BhcmVudDtcblxuICAgIGJhY2tncm91bmQtaW1hZ2U6IHZhcigtLWltYWdlKTtcbiAgICBtYXNrLWltYWdlOiB2YXIoLS1pbWFnZSk7XG4gICAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gIH1cblxuICAmOmhvdmVyIGltZyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1pY29uLWhvdmVyLWNvbG9yKTtcbiAgfVxuXG4gIC5idXR0b24tbGFiZWwge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50ICFpbXBvcnRhbnQ7XG4gICAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gICAgZm9udC1zaXplOiBtaW4oMy42ZHZoLCAxLjhkdncpO1xuICAgIGRpc3BsYXk6IGNvbnRlbnRzO1xuICB9XG5cbiAgLmJ1dHRvbi10b29sdGlwIHtcbiAgICBib3JkZXItcmFkaXVzOiBtaW4oMS4wZHZoLCAwLjVkdncpO1xuICB9XG59IiwiI2RlZXBsaWItcGFnZS1sYWJlbCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuI2RlZXBsaWItc3Vic2NyZWVuLXRpdGxlIHtcbiAgdGV4dC1hbGlnbjogbGVmdDtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gIHVzZXItc2VsZWN0OiBub25lO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLmRlZXBsaWItdGV4dCB7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xufVxuXG4uZGVlcGxpYi1zdWJzY3JlZW4ge1xuICBwYWRkaW5nOiAwO1xuICBtYXJnaW46IDA7XG4gIHBvaW50ZXItZXZlbnRzOiBub25lO1xufVxuXG4uZGVlcGxpYi1zdWJzY3JlZW4gKiB7XG4gIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG4gIHBvaW50ZXItZXZlbnRzOiBhbGw7XG59XG5cbi5kZWVwbGliLXNldHRpbmdzIHtcbiAgZGlzcGxheTogZ3JpZDtcbiAgZ3JpZC1hdXRvLXJvd3M6IG1pbi1jb250ZW50O1xuICBwYWRkaW5nOiBtaW4oMS4wZHZoLCAwLjVkdncpO1xuICBnYXA6IDAuM2VtO1xufVxuXG4uZGVlcGxpYi1taXNjIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbi1yZXZlcnNlO1xuICBnYXA6IG1pbigxdmgsIDAuNXZ3KTtcbn1cblxuLmRlZXBsaWItdG9vbHRpcCB7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgcGFkZGluZzogbWluKDF2aCwgMC41dncpO1xuICBmb250LXNpemU6IDAuOGVtO1xuICBib3JkZXI6IG1pbigwLjJ2aCwgMC4xdncpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLWNvbG9yKTtcbiAgei1pbmRleDogMTtcbn1cblxuLmRlZXBsaWItb3ZlcmZsb3ctYm94IHtcbiAgYm9yZGVyOiB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcikgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItd2lkdGgpO1xufVxuXG4uZGVlcGxpYi1wcmV2LW5leHQge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGdhcDogbWluKDJkdmgsIDFkdncpO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgYm9yZGVyOiBtaW4oMC4ydmgsIDAuMXZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG5cbiAgLmRlZXBsaWItcHJldi1uZXh0LWJ1dHRvbiB7XG4gICAgJjpob3ZlciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtaG92ZXItY29sb3IpO1xuICAgICAgYm9yZGVyLXJhZGl1czogdmFyKC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzKTtcbiAgICB9XG5cbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYXNwZWN0LXJhdGlvOiAxO1xuICB9XG5cbiAgLmRlZXBsaWItcHJldi1uZXh0LWxhYmVsIHtcbiAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG59XG5cbiNkZWVwbGliLW5hdi1tZW51IHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgZ2FwOiBtaW4oMmR2aCwgMWR2dyk7XG4gIHotaW5kZXg6IDE7XG5cbiAgJj4uZGVlcGxpYi1idXR0b24ge1xuICAgIGZsZXg6IDEgMCBhdXRvO1xuICB9XG59XG5cbiNkZWVwbGliLXN0b3JhZ2UtbWV0ZXIge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHRvcDogMHB4O1xuICBsZWZ0OiAwcHg7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG4gIG92ZXJmbG93OiBoaWRkZW47XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGJvcmRlcjogdmFyKC0tZGVlcGxpYi1ib3JkZXItd2lkdGgpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLWNvbG9yKTtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzKTtcbiAgei1pbmRleDogLTE7XG5cbiAgI2RlZXBsaWItc3RvcmFnZS1iYXIge1xuICAgIGhlaWdodDogMTAwJTtcbiAgICB3aWR0aDogMCU7XG4gICAgYmFja2dyb3VuZDogdmFyKC0tZGVlcGxpYi1hY2NlbnQtY29sb3IpO1xuICB9XG59IiwiLmRlZXBsaWItY2hlY2tib3gtY29udGFpbmVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiAwLjNlbTtcbiAgd2lkdGg6IGZpdC1jb250ZW50O1xuXG4gIHNwYW4ge1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG5cbiAgLmRlZXBsaWItaW5wdXQge1xuICAgIHdpZHRoOiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgaGVpZ2h0OiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgd2lkdGg6IG1pbig1ZHZoLCAyLjVkdncpO1xuICAgIGhlaWdodDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMHZoLCAwLjV2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcblxuICAgICZbdHlwZT1cImNoZWNrYm94XCJdOmNoZWNrZWQ6OmJlZm9yZSB7XG4gICAgICB3aWR0aDogODAlO1xuICAgICAgaGVpZ2h0OiA4MCU7XG4gICAgfVxuICB9XG59XG5cbi5kZWVwbGliLWlucHV0LWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogMC4zZW07XG4gIHdpZHRoOiBmaXQtY29udGVudDtcblxuICBzcGFuIHtcbiAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgfVxuXG4gICY6aGFzKC5kZWVwbGliLXRleHQpIHtcbiAgICBtYXJnaW4tdG9wOiBtaW4oMXZoLCAwLjV2dyk7XG4gICAgbWFyZ2luLXRvcDogbWluKDFkdmgsIDAuNWR2dyk7XG4gIH1cblxuICAuZGVlcGxpYi1pbnB1dCB7XG4gICAgZm9udC1zaXplOiAwLjZlbTtcbiAgICBwYWRkaW5nOiBtaW4oMXZoLCAwLjV2dyk7XG4gICAgcGFkZGluZzogbWluKDFkdmgsIDAuNWR2dyk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gICAgb3V0bGluZTogbm9uZTtcbiAgICBtaW4taGVpZ2h0OiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgbWluLWhlaWdodDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMHZoLCAwLjV2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcblxuICAgICZbdHlwZT1cImNvbG9yXCJdIHtcbiAgICAgIHBhZGRpbmc6IDBweDtcbiAgICAgIHdpZHRoOiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgICBoZWlnaHQ6IG1pbig1dmgsIDIuNXZ3KTtcbiAgICAgIHdpZHRoOiBtaW4oNWR2aCwgMi41ZHZ3KTtcbiAgICAgIGhlaWdodDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgICBib3JkZXItcmFkaXVzOiAwcHg7XG5cbiAgICAgICY6ZGlzYWJsZWQge1xuICAgICAgICBib3JkZXI6IHZhcigtLWRlZXBsaWItYmxvY2tlZC1jb2xvcikgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItd2lkdGgpO1xuICAgICAgICBjdXJzb3I6IG5vdC1hbGxvd2VkO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5cbi5kZWVwbGliLWRyb3Bkb3duLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogbWluKDJ2aCwgMXZ3KTtcbiAgZ2FwOiBtaW4oMmR2aCwgMWR2dyk7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICB3aWR0aDogZml0LWNvbnRlbnQ7XG5cbiAgc2VsZWN0IHtcbiAgICBwYWRkaW5nOiAwIG1pbigxdmgsIDAuNXZ3KTtcbiAgICBwYWRkaW5nOiAwIG1pbigxZHZoLCAwLjVkdncpO1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxdmgsIDAuNXZ3KTtcbiAgICBib3JkZXItcmFkaXVzOiBtaW4oMWR2aCwgMC41ZHZ3KTtcbiAgfVxuXG4gIHNwYW4ge1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG59IiwiLmRlZXBsaWItaGlnaGxpZ2h0LXRleHQge1xuICBmb250LXdlaWdodDogYm9sZDtcbiAgY29sb3I6IHJnYigyMDMsIDE4NSwgMjMpO1xufVxuXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyayddIGRpdi5DaGF0TWVzc2FnZS5kZWVwbGliLW1lc3NhZ2UsXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyazInXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yKTtcbiAgYm9yZGVyOiBtaW4oMC4yZHZoLCAwLjFkdncpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLWNvbG9yKTtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG59XG5cbiNUZXh0QXJlYUNoYXRMb2cgZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNlZWU7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCAjNDQwMTcxO1xuICBjb2xvcjogIzExMTtcbiAgcGFkZGluZy1sZWZ0OiBtaW4oMC42ZHZoLCAwLjNkdncpO1xuICBkaXNwbGF5OiBibG9jaztcbiAgd2hpdGUtc3BhY2U6IG5vcm1hbDtcbn1cblxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsnXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEsXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyazInXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEge1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbn1cblxuI1RleHRBcmVhQ2hhdExvZyBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEge1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xuICBjb2xvcjogIzExMTtcbn1cbiIsIi5kZWVwbGliLW1vZGFsIHtcbiAgcG9zaXRpb246IGZpeGVkO1xuICB0b3A6IDEwJTtcbiAgbGVmdDogNTAlO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7XG4gIHotaW5kZXg6IDEwMDE7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IDAuNWVtO1xuICB3aWR0aDogbWF4KDUwZHZ3LCAyNWR2aCk7XG4gIGZvbnQtc2l6ZTogbWluKDRkdmgsIDJkdncpO1xuICBwYWRkaW5nOiBtaW4oMmR2aCwgMWR2dyk7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjJkdmgsIDAuNmR2dyk7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuXG4gIC5kZWVwbGliLW1vZGFsLWlucHV0IHtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBmb250LXNpemU6IG1pbigyLjZkdmgsIDEuOGR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgICBwYWRkaW5nOiBtaW4oMWR2aCwgMC41ZHZ3KTtcbiAgfVxuXG4gIGlucHV0LmRlZXBsaWItbW9kYWwtaW5wdXQge1xuICAgIG1heC13aWR0aDogbWF4KDUwZHZoLCAyNWR2dyk7XG4gIH1cblxuICAuZGVlcGxpYi1tb2RhbC1idXR0b24tY29udGFpbmVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcbiAgICBnYXA6IDAuNWVtO1xuICAgIHdpZHRoOiAxMDAlO1xuXG4gICAgLmRlZXBsaWItYnV0dG9uIHtcbiAgICAgIGZvbnQtc2l6ZTogMC44ZW07XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgd2lkdGg6IGF1dG87XG4gICAgICBwYWRkaW5nOiBtaW4oMC40dmgsIDAuMnZ3KSBtaW4oMnZoLCAxdncpO1xuXG4gICAgICAuYnV0dG9uLWxhYmVsIHtcbiAgICAgICAgZGlzcGxheTogY29udGVudHM7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLmRlZXBsaWItbW9kYWwtcHJvbXB0LWNvbnRhaW5lciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIH1cbn1cblxuLmRlZXBsaWItbW9kYWwtYmxvY2tlciB7XG4gIHotaW5kZXg6IDEwMDA7XG4gIHBvc2l0aW9uOiBmaXhlZDtcbiAgdG9wOiAwO1xuICBsZWZ0OiAwO1xuICB3aWR0aDogMTAwZHZ3O1xuICBoZWlnaHQ6IDEwMGR2aDtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjUpO1xufVxuIl19 */`;
|
|
751
|
+
|
|
752
|
+
#deeplib-modal-import_export .deeplib-modal-checkbox-container {
|
|
753
|
+
margin-top: 0.5em;
|
|
754
|
+
display: flex;
|
|
755
|
+
flex-direction: column;
|
|
756
|
+
gap: var(--half-gap);
|
|
757
|
+
}
|
|
758
|
+
/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VSb290IjoiL21udC9zaGluZG93cy9TdHVmZi9Db2RlL2JjL0JDLURlZXBMaWIvc3JjL3N0eWxlcyIsInNvdXJjZXMiOlsidmFycy5zY3NzIiwiYnV0dG9ucy5zY3NzIiwiZWxlbWVudHMuc2NzcyIsImlucHV0cy5zY3NzIiwibWVzc2FnZXMuc2NzcyIsIm1vZGFsLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQTtFQUVFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUNkRjtFQUNFO0VBQ0E7RUFDQTs7QUFFQTtFQUVFOztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUVBO0VBQ0E7RUFDQTs7QUFHRjtFQUNFOztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7O0FBR0Y7RUFDRTs7O0FDM0NKO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFHRTtFQUNFO0VBQ0E7O0FBSEo7RUFNRTtFQUNBOztBQUdGO0VBQ0U7RUFDQTs7O0FBSUo7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFOzs7QUFJSjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTtFQUNBOzs7QUNuSEo7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBOzs7QUFLTjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTs7QUFHRjtFQUNFO0VBQ0E7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBOzs7QUFPUjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7O0FBR0Y7RUFDRTs7O0FDdkZKO0VBQ0U7RUFDQTs7O0FBR0Y7QUFBQTtFQUVFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0FBQUE7RUFFRTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7OztBQzdCRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFHRjtFQUNFOztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7O0FBS047RUFDRTtFQUNBO0VBQ0E7RUFDQTs7O0FBSUo7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBSUE7RUFDRTtFQUNBO0VBQ0E7RUFDQSIsInNvdXJjZXNDb250ZW50IjpbIi5kZWVwbGliLXN1YnNjcmVlbixcbi5kZWVwbGliLW1vZGFsIHtcbiAgLS1kZWVwbGliLWJhY2tncm91bmQtY29sb3I6IHZhcigtLXRtZC1tYWluLCB3aGl0ZSk7XG4gIC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yOiB2YXIoLS10bWQtZWxlbWVudCwgd2hpdGUpO1xuICAtLWRlZXBsaWItZWxlbWVudC1ob3Zlci1jb2xvcjogdmFyKC0tdG1kLWVsZW1lbnQtaG92ZXIsIGN5YW4pO1xuICAtLWRlZXBsaWItYWNjZW50LWNvbG9yOiB2YXIoLS10bWQtYWNjZW50LCAjRkZGRjg4KTtcbiAgLS1kZWVwbGliLWJsb2NrZWQtY29sb3I6IHZhcigtLXRtZC1ibG9ja2VkLCByZWQpO1xuICAtLWRlZXBsaWItdGV4dC1jb2xvcjogdmFyKC0tdG1kLXRleHQsIGJsYWNrKTtcbiAgLS1kZWVwbGliLWljb24tY29sb3I6IHZhcigtLXRtZC1hY2NlbnQsIGJsYWNrKTtcbiAgLS1kZWVwbGliLWljb24taG92ZXItY29sb3I6IHZhcigtLXRtZC1hY2NlbnQtaG92ZXIsIGJsYWNrKTtcbiAgLS1kZWVwbGliLWJvcmRlci1jb2xvcjogdmFyKC0tdG1kLWFjY2VudCwgYmxhY2spO1xuICAtLWRlZXBsaWItYm9yZGVyLXdpZHRoOiBtaW4oMC4ydmgsIDAuMXZ3KTtcbiAgLS1kZWVwbGliLWJvcmRlci13aWR0aDogbWluKDAuMmR2aCwgMC4xZHZ3KTtcbiAgLS1kZWVwbGliLWJvcmRlci1yYWRpdXM6IG1pbigxdmgsIDAuNXZ3KTtcbiAgLS1kZWVwbGliLWJvcmRlci1yYWRpdXM6IG1pbigxZHZoLCAwLjVkdncpO1xufVxuIiwiLmRlZXBsaWItYnV0dG9uIHtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG5cbiAgJi5idXR0b24tc3R5bGluZyxcbiAgJi5idXR0b24tc3R5bGluZzo6YmVmb3JlIHtcbiAgICBib3JkZXItcmFkaXVzOiBtaW4oMS4wZHZoLCAwLjVkdncpO1xuICB9XG5cbiAgaW1nIHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAwJTtcbiAgICBsZWZ0OiAwJTtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYmFja2dyb3VuZC1wb3NpdGlvbjogbGVmdDtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWljb24tY29sb3IpO1xuICAgIGJhY2tncm91bmQtYmxlbmQtbW9kZTogbXVsdGlwbHk7XG4gICAgYmFja2dyb3VuZC1zaXplOiBjb250YWluO1xuICAgIG1hc2stcG9zaXRpb246IGxlZnQ7XG4gICAgbWFzay1zaXplOiBjb250YWluO1xuICAgIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7XG4gICAgbWFzay1yZXBlYXQ6IG5vLXJlcGVhdDtcbiAgICBjb2xvcjogdHJhbnNwYXJlbnQ7XG5cbiAgICBiYWNrZ3JvdW5kLWltYWdlOiB2YXIoLS1pbWFnZSk7XG4gICAgbWFzay1pbWFnZTogdmFyKC0taW1hZ2UpO1xuICAgIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICB9XG5cbiAgJjpob3ZlciBpbWcge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItaWNvbi1ob3Zlci1jb2xvcik7XG4gIH1cblxuICAuYnV0dG9uLWxhYmVsIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudCAhaW1wb3J0YW50O1xuICAgIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICAgIGZvbnQtc2l6ZTogbWluKDMuNmR2aCwgMS44ZHZ3KTtcbiAgICBkaXNwbGF5OiBjb250ZW50cztcbiAgfVxuXG4gIC5idXR0b24tdG9vbHRpcCB7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgfVxufSIsIiNkZWVwbGliLXBhZ2UtbGFiZWwge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG59XG5cbiNkZWVwbGliLXN1YnNjcmVlbi10aXRsZSB7XG4gIHRleHQtYWxpZ246IGxlZnQ7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG59XG5cbi5kZWVwbGliLXRleHQge1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbn1cblxuLmRlZXBsaWItc3Vic2NyZWVuIHtcbiAgcGFkZGluZzogMDtcbiAgbWFyZ2luOiAwO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLmRlZXBsaWItc3Vic2NyZWVuICoge1xuICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICBwb2ludGVyLWV2ZW50czogYWxsO1xufVxuXG4uZGVlcGxpYi1zZXR0aW5ncyB7XG4gIGRpc3BsYXk6IGdyaWQ7XG4gIGdyaWQtYXV0by1yb3dzOiBtaW4tY29udGVudDtcbiAgcGFkZGluZzogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgZ2FwOiAwLjNlbTtcbn1cblxuLmRlZXBsaWItbWlzYyB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW4tcmV2ZXJzZTtcbiAgZ2FwOiBtaW4oMXZoLCAwLjV2dyk7XG59XG5cbi5kZWVwbGliLXRvb2x0aXAge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIHBhZGRpbmc6IG1pbigxdmgsIDAuNXZ3KTtcbiAgZm9udC1zaXplOiAwLjhlbTtcbiAgYm9yZGVyOiBtaW4oMC4ydmgsIDAuMXZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG4gIHotaW5kZXg6IDE7XG59XG5cbi5kZWVwbGliLW92ZXJmbG93LWJveCB7XG4gIGJvcmRlcjogdmFyKC0tZGVlcGxpYi1ib3JkZXItY29sb3IpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLXdpZHRoKTtcbn1cblxuLmRlZXBsaWItcHJldi1uZXh0IHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBnYXA6IG1pbigyZHZoLCAxZHZ3KTtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yKTtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIGJvcmRlcjogbWluKDAuMnZoLCAwLjF2dykgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItY29sb3IpO1xuXG4gIC5kZWVwbGliLXByZXYtbmV4dC1idXR0b24ge1xuICAgICY6aG92ZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWhvdmVyLWNvbG9yKTtcbiAgICAgIGJvcmRlci1yYWRpdXM6IHZhcigtLWRlZXBsaWItYm9yZGVyLXJhZGl1cyk7XG4gICAgfVxuXG4gICAgaGVpZ2h0OiAxMDAlO1xuICAgIGFzcGVjdC1yYXRpbzogMTtcbiAgfVxuXG4gIC5kZWVwbGliLXByZXYtbmV4dC1sYWJlbCB7XG4gICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgfVxufVxuXG4jZGVlcGxpYi1uYXYtbWVudSB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGdhcDogbWluKDJkdmgsIDFkdncpO1xuICB6LWluZGV4OiAxO1xuXG4gICY+LmRlZXBsaWItYnV0dG9uIHtcbiAgICBmbGV4OiAxIDAgYXV0bztcbiAgfVxufVxuXG4jZGVlcGxpYi1zdG9yYWdlLW1ldGVyIHtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IDBweDtcbiAgbGVmdDogMHB4O1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xuICBvdmVyZmxvdzogaGlkZGVuO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBib3JkZXI6IHZhcigtLWRlZXBsaWItYm9yZGVyLXdpZHRoKSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG4gIGJvcmRlci1yYWRpdXM6IHZhcigtLWRlZXBsaWItYm9yZGVyLXJhZGl1cyk7XG4gIHotaW5kZXg6IC0xO1xuXG4gICNkZWVwbGliLXN0b3JhZ2UtYmFyIHtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgd2lkdGg6IDAlO1xuICAgIGJhY2tncm91bmQ6IHZhcigtLWRlZXBsaWItYWNjZW50LWNvbG9yKTtcbiAgfVxufSIsIi5kZWVwbGliLWNoZWNrYm94LWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogMC4zZW07XG4gIHdpZHRoOiBmaXQtY29udGVudDtcblxuICBzcGFuIHtcbiAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgfVxuXG4gIC5kZWVwbGliLWlucHV0IHtcbiAgICB3aWR0aDogbWluKDV2aCwgMi41dncpO1xuICAgIGhlaWdodDogbWluKDV2aCwgMi41dncpO1xuICAgIHdpZHRoOiBtaW4oNWR2aCwgMi41ZHZ3KTtcbiAgICBoZWlnaHQ6IG1pbig1ZHZoLCAyLjVkdncpO1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxLjB2aCwgMC41dncpO1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG5cbiAgICAmW3R5cGU9XCJjaGVja2JveFwiXTpjaGVja2VkOjpiZWZvcmUge1xuICAgICAgd2lkdGg6IDgwJTtcbiAgICAgIGhlaWdodDogODAlO1xuICAgIH1cbiAgfVxufVxuXG4uZGVlcGxpYi1pbnB1dC1jb250YWluZXIge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IDAuM2VtO1xuICB3aWR0aDogZml0LWNvbnRlbnQ7XG5cbiAgc3BhbiB7XG4gICAgdXNlci1zZWxlY3Q6IG5vbmU7XG4gIH1cblxuICAmOmhhcyguZGVlcGxpYi10ZXh0KSB7XG4gICAgbWFyZ2luLXRvcDogbWluKDF2aCwgMC41dncpO1xuICAgIG1hcmdpbi10b3A6IG1pbigxZHZoLCAwLjVkdncpO1xuICB9XG5cbiAgLmRlZXBsaWItaW5wdXQge1xuICAgIGZvbnQtc2l6ZTogMC42ZW07XG4gICAgcGFkZGluZzogbWluKDF2aCwgMC41dncpO1xuICAgIHBhZGRpbmc6IG1pbigxZHZoLCAwLjVkdncpO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICAgIG91dGxpbmU6IG5vbmU7XG4gICAgbWluLWhlaWdodDogbWluKDV2aCwgMi41dncpO1xuICAgIG1pbi1oZWlnaHQ6IG1pbig1ZHZoLCAyLjVkdncpO1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxLjB2aCwgMC41dncpO1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG5cbiAgICAmW3R5cGU9XCJjb2xvclwiXSB7XG4gICAgICBwYWRkaW5nOiAwcHg7XG4gICAgICB3aWR0aDogbWluKDV2aCwgMi41dncpO1xuICAgICAgaGVpZ2h0OiBtaW4oNXZoLCAyLjV2dyk7XG4gICAgICB3aWR0aDogbWluKDVkdmgsIDIuNWR2dyk7XG4gICAgICBoZWlnaHQ6IG1pbig1ZHZoLCAyLjVkdncpO1xuICAgICAgYm9yZGVyLXJhZGl1czogMHB4O1xuXG4gICAgICAmOmRpc2FibGVkIHtcbiAgICAgICAgYm9yZGVyOiB2YXIoLS1kZWVwbGliLWJsb2NrZWQtY29sb3IpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLXdpZHRoKTtcbiAgICAgICAgY3Vyc29yOiBub3QtYWxsb3dlZDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuXG4uZGVlcGxpYi1kcm9wZG93bi1jb250YWluZXIge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IG1pbigydmgsIDF2dyk7XG4gIGdhcDogbWluKDJkdmgsIDFkdncpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgd2lkdGg6IGZpdC1jb250ZW50O1xuXG4gIHNlbGVjdCB7XG4gICAgcGFkZGluZzogMCBtaW4oMXZoLCAwLjV2dyk7XG4gICAgcGFkZGluZzogMCBtaW4oMWR2aCwgMC41ZHZ3KTtcbiAgICBib3JkZXItcmFkaXVzOiBtaW4oMXZoLCAwLjV2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDFkdmgsIDAuNWR2dyk7XG4gIH1cblxuICBzcGFuIHtcbiAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgfVxufSIsIi5kZWVwbGliLWhpZ2hsaWdodC10ZXh0IHtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG4gIGNvbG9yOiByZ2IoMjAzLCAxODUsIDIzKTtcbn1cblxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsnXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlLFxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsyJ10gZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xufVxuXG4jVGV4dEFyZWFDaGF0TG9nIGRpdi5DaGF0TWVzc2FnZS5kZWVwbGliLW1lc3NhZ2Uge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZWVlO1xuICBib3JkZXI6IG1pbigwLjJkdmgsIDAuMWR2dykgc29saWQgIzQ0MDE3MTtcbiAgY29sb3I6ICMxMTE7XG4gIHBhZGRpbmctbGVmdDogbWluKDAuNmR2aCwgMC4zZHZ3KTtcbiAgZGlzcGxheTogYmxvY2s7XG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XG59XG5cbiNUZXh0QXJlYUNoYXRMb2dbZGF0YS1jb2xvcnRoZW1lPSdkYXJrJ10gZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSBhLFxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsyJ10gZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSBhIHtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG59XG5cbiNUZXh0QXJlYUNoYXRMb2cgZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSBhIHtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBmb250LXdlaWdodDogYm9sZDtcbiAgY29sb3I6ICMxMTE7XG59XG4iLCIuZGVlcGxpYi1tb2RhbCB7XG4gIHBvc2l0aW9uOiBmaXhlZDtcbiAgdG9wOiAxMCU7XG4gIGxlZnQ6IDUwJTtcbiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpO1xuICB6LWluZGV4OiAxMDAxO1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiAwLjVlbTtcbiAgd2lkdGg6IG1heCg1MGR2dywgMjVkdmgpO1xuICBmb250LXNpemU6IG1pbig0ZHZoLCAyZHZ3KTtcbiAgcGFkZGluZzogbWluKDJkdmgsIDFkdncpO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBib3JkZXItcmFkaXVzOiBtaW4oMS4yZHZoLCAwLjZkdncpO1xuICBib3JkZXI6IG1pbigwLjJkdmgsIDAuMWR2dykgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItY29sb3IpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcblxuICAuZGVlcGxpYi1tb2RhbC1pbnB1dCB7XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgZm9udC1zaXplOiBtaW4oMi42ZHZoLCAxLjhkdncpO1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gICAgcGFkZGluZzogbWluKDFkdmgsIDAuNWR2dyk7XG4gIH1cblxuICBpbnB1dC5kZWVwbGliLW1vZGFsLWlucHV0IHtcbiAgICBtYXgtd2lkdGg6IG1heCg1MGR2aCwgMjVkdncpO1xuICB9XG5cbiAgLmRlZXBsaWItbW9kYWwtYnV0dG9uLWNvbnRhaW5lciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICAgIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7XG4gICAgZ2FwOiAwLjVlbTtcbiAgICB3aWR0aDogMTAwJTtcblxuICAgIC5kZWVwbGliLWJ1dHRvbiB7XG4gICAgICBmb250LXNpemU6IDAuOGVtO1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIHdpZHRoOiBhdXRvO1xuICAgICAgcGFkZGluZzogbWluKDAuNHZoLCAwLjJ2dykgbWluKDJ2aCwgMXZ3KTtcblxuICAgICAgLmJ1dHRvbi1sYWJlbCB7XG4gICAgICAgIGRpc3BsYXk6IGNvbnRlbnRzO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC5kZWVwbGliLW1vZGFsLXByb21wdC1jb250YWluZXIge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICB9XG59XG5cbi5kZWVwbGliLW1vZGFsLWJsb2NrZXIge1xuICB6LWluZGV4OiAxMDAwO1xuICBwb3NpdGlvbjogZml4ZWQ7XG4gIHRvcDogMDtcbiAgbGVmdDogMDtcbiAgd2lkdGg6IDEwMGR2dztcbiAgaGVpZ2h0OiAxMDBkdmg7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC41KTtcbn1cblxuI2RlZXBsaWItbW9kYWwtaW1wb3J0X2V4cG9ydCB7XG4gIC5kZWVwbGliLW1vZGFsLWNoZWNrYm94LWNvbnRhaW5lciB7XG4gICAgbWFyZ2luLXRvcDogMC41ZW07XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgIGdhcDogdmFyKC0taGFsZi1nYXApO1xuICB9XG59Il19 */`;
|
|
953
759
|
|
|
954
760
|
// src/base/initialization.ts
|
|
955
761
|
var modStorage;
|
|
956
762
|
var sdk;
|
|
957
|
-
var
|
|
763
|
+
var modLogger;
|
|
764
|
+
var MOD_NAME;
|
|
958
765
|
function initMod(options) {
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
options.beforeLogin?.();
|
|
967
|
-
const removeHook = sdk.hookFunction("LoginResponse", 0, (args, next) => {
|
|
968
|
-
logger.debug("Init! LoginResponse caught: ", args);
|
|
969
|
-
next(args);
|
|
970
|
-
const response = args[0];
|
|
971
|
-
if (response === "InvalidNamePassword") return next(args);
|
|
972
|
-
if (response && typeof response.Name === "string" && typeof response.AccountName === "string") {
|
|
973
|
-
init(options);
|
|
974
|
-
removeHook();
|
|
975
|
-
}
|
|
766
|
+
const url = "https://cdn.jsdelivr.net/npm/bondage-club-mod-sdk@1.2.0/+esm";
|
|
767
|
+
import(`${url}`).then(() => {
|
|
768
|
+
sdk = new ModSdkManager({
|
|
769
|
+
name: options.modName,
|
|
770
|
+
fullName: options.modName,
|
|
771
|
+
version: MOD_VERSION,
|
|
772
|
+
repository: options.modRepository
|
|
976
773
|
});
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
774
|
+
MOD_NAME = options.modName;
|
|
775
|
+
modStorage = new ModStorage(options.modName);
|
|
776
|
+
modLogger = new Logger(MOD_NAME);
|
|
777
|
+
Style.injectInline("deeplib-style", styles_default);
|
|
778
|
+
modLogger.debug("Init wait");
|
|
779
|
+
if (!CurrentScreen || CurrentScreen === "Login") {
|
|
780
|
+
options.beforeLogin?.();
|
|
781
|
+
const removeHook = sdk.hookFunction("LoginResponse", 0, (args, next) => {
|
|
782
|
+
modLogger.debug("Init! LoginResponse caught: ", args);
|
|
783
|
+
next(args);
|
|
784
|
+
const response = args[0];
|
|
785
|
+
if (response === "InvalidNamePassword") return next(args);
|
|
786
|
+
if (response && typeof response.Name === "string" && typeof response.AccountName === "string") {
|
|
787
|
+
init(options);
|
|
788
|
+
removeHook();
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
} else {
|
|
792
|
+
modLogger.debug(`Already logged in, initing ${MOD_NAME}`);
|
|
793
|
+
init(options);
|
|
794
|
+
}
|
|
795
|
+
});
|
|
981
796
|
}
|
|
982
797
|
__name(initMod, "initMod");
|
|
983
798
|
async function init(options) {
|
|
984
|
-
|
|
985
|
-
const MOD_VERSION = ModSdkManager.ModInfo.version;
|
|
986
|
-
if (window[MOD_NAME + "Loaded"]) return;
|
|
799
|
+
if (window[options.modName + "Loaded"]) return;
|
|
987
800
|
modStorage.load();
|
|
988
801
|
await Localization.init(options.translationOptions);
|
|
989
|
-
|
|
802
|
+
options.modules ??= [];
|
|
803
|
+
const modulesToRegister = [];
|
|
804
|
+
if (!options.modules.some((m) => m instanceof VersionModule)) {
|
|
805
|
+
modulesToRegister.push(new VersionModule());
|
|
806
|
+
}
|
|
807
|
+
modulesToRegister.push(...options.modules);
|
|
808
|
+
if (!initModules(modulesToRegister)) {
|
|
990
809
|
unloadMod();
|
|
991
810
|
return;
|
|
992
811
|
}
|
|
993
812
|
await options.initFunction?.();
|
|
994
|
-
if (options.mainMenuOptions)
|
|
995
|
-
MainMenu.setOptions(
|
|
996
|
-
|
|
997
|
-
|
|
813
|
+
if (options.mainMenuOptions && getModule("GUI")) {
|
|
814
|
+
MainMenu.setOptions({
|
|
815
|
+
...options.mainMenuOptions,
|
|
816
|
+
repoLink: options.modRepository
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
window[options.modName + "Loaded"] = true;
|
|
820
|
+
modLogger.log(`Loaded! Version: ${MOD_VERSION_CAPTION}`);
|
|
998
821
|
}
|
|
999
822
|
__name(init, "init");
|
|
1000
823
|
function initModules(modulesToRegister) {
|
|
@@ -1013,15 +836,15 @@ function initModules(modulesToRegister) {
|
|
|
1013
836
|
for (const module of modules()) {
|
|
1014
837
|
module.registerDefaultSettings(modStorage.playerStorage);
|
|
1015
838
|
}
|
|
1016
|
-
|
|
839
|
+
modLogger.debug("Modules Loaded.");
|
|
1017
840
|
return true;
|
|
1018
841
|
}
|
|
1019
842
|
__name(initModules, "initModules");
|
|
1020
843
|
function unloadMod() {
|
|
1021
|
-
const MOD_NAME = ModSdkManager.ModInfo.name;
|
|
1022
844
|
unloadModules();
|
|
845
|
+
sdk.unload();
|
|
1023
846
|
delete window[MOD_NAME + "Loaded"];
|
|
1024
|
-
|
|
847
|
+
modLogger.debug("Unloaded.");
|
|
1025
848
|
return true;
|
|
1026
849
|
}
|
|
1027
850
|
__name(unloadMod, "unloadMod");
|
|
@@ -1143,6 +966,7 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1143
966
|
static afterAll;
|
|
1144
967
|
constructor(options) {
|
|
1145
968
|
super();
|
|
969
|
+
options ??= {};
|
|
1146
970
|
_VersionModule.newVersionMessage = options.newVersionMessage;
|
|
1147
971
|
if (options.migrators) {
|
|
1148
972
|
_VersionModule.migrators = options.migrators;
|
|
@@ -1159,7 +983,7 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1159
983
|
* - Hooks into `ChatRoomSync` to show a "new version" message when applicable.
|
|
1160
984
|
*/
|
|
1161
985
|
load() {
|
|
1162
|
-
_VersionModule.version =
|
|
986
|
+
_VersionModule.version = MOD_VERSION;
|
|
1163
987
|
_VersionModule.checkVersionUpdate();
|
|
1164
988
|
if (modStorage.playerStorage.GlobalModule.doShowNewVersionMessage && _VersionModule.isItNewVersion) {
|
|
1165
989
|
_VersionModule.sendNewVersionMessage();
|
|
@@ -1197,8 +1021,8 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1197
1021
|
for (const migrator of toMigrate) {
|
|
1198
1022
|
_VersionModule.beforeEach?.();
|
|
1199
1023
|
migrator.migrate();
|
|
1200
|
-
|
|
1201
|
-
`Migrating
|
|
1024
|
+
modLogger.info(
|
|
1025
|
+
`Migrating from ${previousVersion} to ${migrator.migrationVersion} with ${migrator.constructor.name}`
|
|
1202
1026
|
);
|
|
1203
1027
|
_VersionModule.afterEach?.();
|
|
1204
1028
|
}
|
|
@@ -1209,7 +1033,7 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1209
1033
|
if (!_VersionModule.newVersionMessage) return;
|
|
1210
1034
|
const beepLogLength = FriendListBeepLog.push({
|
|
1211
1035
|
MemberNumber: Player.MemberNumber,
|
|
1212
|
-
MemberName:
|
|
1036
|
+
MemberName: MOD_NAME,
|
|
1213
1037
|
ChatRoomName: getText("module.version.version_update"),
|
|
1214
1038
|
ChatRoomSpace: "X",
|
|
1215
1039
|
Private: false,
|
|
@@ -1219,7 +1043,7 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1219
1043
|
});
|
|
1220
1044
|
const beepIdx = beepLogLength - 1;
|
|
1221
1045
|
const title = CommonStringPartitionReplace(getText("module.version.new_version_toast_title"), {
|
|
1222
|
-
$modName$:
|
|
1046
|
+
$modName$: MOD_NAME,
|
|
1223
1047
|
$modVersion$: _VersionModule.version
|
|
1224
1048
|
}).join("");
|
|
1225
1049
|
const data = FriendListBeepLog[beepIdx];
|
|
@@ -1257,7 +1081,7 @@ var VersionModule = class _VersionModule extends BaseModule {
|
|
|
1257
1081
|
/** Saves the current mod version into persistent player storage. */
|
|
1258
1082
|
static saveVersion() {
|
|
1259
1083
|
if (modStorage.playerStorage) {
|
|
1260
|
-
|
|
1084
|
+
modStorage.playerStorage.Version = _VersionModule.version;
|
|
1261
1085
|
}
|
|
1262
1086
|
}
|
|
1263
1087
|
/** Loads the stored mod version from persistent player storage. */
|
|
@@ -1846,221 +1670,6 @@ function elementPrevNext(options) {
|
|
|
1846
1670
|
return retElem;
|
|
1847
1671
|
}
|
|
1848
1672
|
__name(elementPrevNext, "elementPrevNext");
|
|
1849
|
-
var Modal = class _Modal {
|
|
1850
|
-
constructor(opts) {
|
|
1851
|
-
this.opts = opts;
|
|
1852
|
-
opts ??= {};
|
|
1853
|
-
opts.closeOnBackdrop ??= true;
|
|
1854
|
-
const promptId = `modal-prompt-${Date.now()}`;
|
|
1855
|
-
const prompt = (CommonIsArray(opts.prompt) ? opts.prompt : [opts.prompt]).filter((i) => i != null) ?? [""];
|
|
1856
|
-
this.dialog = ElementCreate({
|
|
1857
|
-
tag: "dialog",
|
|
1858
|
-
classList: ["deeplib-modal"],
|
|
1859
|
-
attributes: {
|
|
1860
|
-
role: "dialog",
|
|
1861
|
-
"aria-modal": "true",
|
|
1862
|
-
"aria-labelledby": promptId
|
|
1863
|
-
},
|
|
1864
|
-
style: {
|
|
1865
|
-
fontFamily: CommonGetFontName()
|
|
1866
|
-
},
|
|
1867
|
-
children: [
|
|
1868
|
-
{
|
|
1869
|
-
tag: "div",
|
|
1870
|
-
classList: ["deeplib-modal-prompt-container"],
|
|
1871
|
-
children: [
|
|
1872
|
-
...prompt
|
|
1873
|
-
]
|
|
1874
|
-
},
|
|
1875
|
-
{
|
|
1876
|
-
tag: "div",
|
|
1877
|
-
classList: ["deeplib-modal-prompt"],
|
|
1878
|
-
attributes: {
|
|
1879
|
-
id: promptId
|
|
1880
|
-
},
|
|
1881
|
-
children: [
|
|
1882
|
-
opts.input ? this.renderInput(opts.input) : void 0
|
|
1883
|
-
]
|
|
1884
|
-
},
|
|
1885
|
-
this.renderButtons()
|
|
1886
|
-
]
|
|
1887
|
-
});
|
|
1888
|
-
this.blocker = this.createBlocker();
|
|
1889
|
-
this.renderButtons();
|
|
1890
|
-
document.body.append(this.createBlocker(), this.dialog);
|
|
1891
|
-
this.setupFocusTrap();
|
|
1892
|
-
if (opts.timeoutMs) {
|
|
1893
|
-
this.timeoutId = window.setTimeout(() => this.close("timeout"), opts.timeoutMs);
|
|
1894
|
-
}
|
|
1895
|
-
}
|
|
1896
|
-
static {
|
|
1897
|
-
__name(this, "Modal");
|
|
1898
|
-
}
|
|
1899
|
-
dialog;
|
|
1900
|
-
blocker;
|
|
1901
|
-
inputEl;
|
|
1902
|
-
timeoutId;
|
|
1903
|
-
/** Static modal queue. */
|
|
1904
|
-
static queue = [];
|
|
1905
|
-
/** Flag to indicate if a modal is currently being shown. */
|
|
1906
|
-
static processing = false;
|
|
1907
|
-
/**
|
|
1908
|
-
* Displays the modal and resolves with the chosen action and input value.
|
|
1909
|
-
*/
|
|
1910
|
-
show() {
|
|
1911
|
-
return _Modal.enqueue(this);
|
|
1912
|
-
}
|
|
1913
|
-
/**
|
|
1914
|
-
* Shows a simple alert modal with a single "OK" button.
|
|
1915
|
-
*/
|
|
1916
|
-
static async alert(msg, timeoutMs) {
|
|
1917
|
-
await new _Modal({
|
|
1918
|
-
prompt: msg,
|
|
1919
|
-
buttons: [{ action: "close", text: getText("modal.button.ok") }],
|
|
1920
|
-
timeoutMs,
|
|
1921
|
-
escapeAction: "close"
|
|
1922
|
-
}).show();
|
|
1923
|
-
}
|
|
1924
|
-
/**
|
|
1925
|
-
* Shows a confirmation modal with "Cancel" and "OK" buttons.
|
|
1926
|
-
* Returns true if "OK" is clicked.
|
|
1927
|
-
*/
|
|
1928
|
-
static async confirm(msg) {
|
|
1929
|
-
const [action] = await new _Modal({
|
|
1930
|
-
prompt: msg,
|
|
1931
|
-
buttons: [{ text: getText("modal.button.decline"), action: "decline" }, { text: getText("modal.button.confirm"), action: "confirm" }],
|
|
1932
|
-
escapeAction: "decline",
|
|
1933
|
-
enterAction: "confirm"
|
|
1934
|
-
}).show();
|
|
1935
|
-
return action === "confirm";
|
|
1936
|
-
}
|
|
1937
|
-
/**
|
|
1938
|
-
* Shows a prompt modal with an input field and "Submit"/"Cancel" buttons.
|
|
1939
|
-
* Returns the input value if submitted, otherwise null.
|
|
1940
|
-
*/
|
|
1941
|
-
static async prompt(msg, defaultValue = "") {
|
|
1942
|
-
const [action, value] = await new _Modal({
|
|
1943
|
-
prompt: msg,
|
|
1944
|
-
timeoutMs: 0,
|
|
1945
|
-
input: { type: "input", defaultValue },
|
|
1946
|
-
buttons: [{ text: getText("modal.button.cancel"), action: "cancel" }, { text: getText("modal.button.submit"), action: "submit" }],
|
|
1947
|
-
escapeAction: "cancel",
|
|
1948
|
-
enterAction: "submit"
|
|
1949
|
-
}).show();
|
|
1950
|
-
return action === "submit" ? value : null;
|
|
1951
|
-
}
|
|
1952
|
-
/** Creates the input element for the modal, applying configuration and validation. */
|
|
1953
|
-
renderInput(cfg) {
|
|
1954
|
-
const el = document.createElement(cfg.type);
|
|
1955
|
-
el.classList.add("deeplib-modal-input");
|
|
1956
|
-
if (cfg.placeholder) el.placeholder = cfg.placeholder;
|
|
1957
|
-
if (cfg.readOnly) el.readOnly = true;
|
|
1958
|
-
if (cfg.defaultValue) el.value = cfg.defaultValue;
|
|
1959
|
-
if (cfg.type === "textarea") el.rows = 5;
|
|
1960
|
-
el.addEventListener("input", () => {
|
|
1961
|
-
const err = cfg.validate?.(el.value);
|
|
1962
|
-
el.setCustomValidity(err || "");
|
|
1963
|
-
});
|
|
1964
|
-
this.inputEl = el;
|
|
1965
|
-
return el;
|
|
1966
|
-
}
|
|
1967
|
-
/** Creates modal action buttons from configuration. */
|
|
1968
|
-
renderButtons() {
|
|
1969
|
-
const container = document.createElement("div");
|
|
1970
|
-
container.classList.add("deeplib-modal-button-container");
|
|
1971
|
-
const btns = this.opts.buttons ? [...this.opts.buttons] : [];
|
|
1972
|
-
btns.forEach((b) => {
|
|
1973
|
-
const btn = advElement.createButton({
|
|
1974
|
-
id: `deeplib-modal-${b.action}`,
|
|
1975
|
-
onClick: /* @__PURE__ */ __name(() => this.close(b.action), "onClick"),
|
|
1976
|
-
options: {
|
|
1977
|
-
disabled: b.disabled,
|
|
1978
|
-
label: b.text
|
|
1979
|
-
}
|
|
1980
|
-
});
|
|
1981
|
-
container.append(btn);
|
|
1982
|
-
});
|
|
1983
|
-
return container;
|
|
1984
|
-
}
|
|
1985
|
-
/** Creates the modal backdrop blocker with optional click-to-close behavior. */
|
|
1986
|
-
createBlocker() {
|
|
1987
|
-
const blocker = document.createElement("div");
|
|
1988
|
-
blocker.classList.add("deeplib-modal-blocker");
|
|
1989
|
-
blocker.title = "Click to close";
|
|
1990
|
-
if (this.opts.closeOnBackdrop !== false)
|
|
1991
|
-
blocker.addEventListener("click", () => this.close("close"));
|
|
1992
|
-
return blocker;
|
|
1993
|
-
}
|
|
1994
|
-
/** Implements a focus trap to keep keyboard navigation inside the modal. */
|
|
1995
|
-
setupFocusTrap() {
|
|
1996
|
-
const focusable = 'button, [href], input, textarea, select, [tabindex]:not([tabindex="-1"])';
|
|
1997
|
-
const elements = Array.from(this.dialog.querySelectorAll(focusable));
|
|
1998
|
-
const first = elements[0];
|
|
1999
|
-
const last = elements[elements.length - 1];
|
|
2000
|
-
this.dialog.addEventListener("keydown", (e) => {
|
|
2001
|
-
if (e.key === "Tab") {
|
|
2002
|
-
if (elements.length === 0) {
|
|
2003
|
-
e.preventDefault();
|
|
2004
|
-
return;
|
|
2005
|
-
}
|
|
2006
|
-
if (e.shiftKey) {
|
|
2007
|
-
if (document.activeElement === first) {
|
|
2008
|
-
last.focus();
|
|
2009
|
-
e.preventDefault();
|
|
2010
|
-
}
|
|
2011
|
-
} else {
|
|
2012
|
-
if (document.activeElement === last) {
|
|
2013
|
-
first.focus();
|
|
2014
|
-
e.preventDefault();
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
} else if (e.key === "Escape") {
|
|
2018
|
-
e.stopPropagation();
|
|
2019
|
-
this.close(this.opts.escapeAction ?? "close");
|
|
2020
|
-
} else if (e.key === "Enter") {
|
|
2021
|
-
if (elements.some((el) => el === document.activeElement) && document.activeElement !== this.inputEl) return;
|
|
2022
|
-
e.preventDefault();
|
|
2023
|
-
e.stopPropagation();
|
|
2024
|
-
this.close(this.opts.enterAction ?? "submit");
|
|
2025
|
-
}
|
|
2026
|
-
});
|
|
2027
|
-
window.requestAnimationFrame(() => {
|
|
2028
|
-
(this.inputEl || first)?.focus();
|
|
2029
|
-
});
|
|
2030
|
-
}
|
|
2031
|
-
/** Closes the modal, cleans up DOM, resolves promise, and shows next queued modal. */
|
|
2032
|
-
close(action) {
|
|
2033
|
-
if (this.timeoutId) clearTimeout(this.timeoutId);
|
|
2034
|
-
this.dialog.close();
|
|
2035
|
-
this.dialog.remove();
|
|
2036
|
-
this.blocker.remove();
|
|
2037
|
-
document.body.querySelector(".deeplib-modal-blocker")?.remove();
|
|
2038
|
-
const value = this.inputEl?.value ?? "";
|
|
2039
|
-
this.resolve([action, value]);
|
|
2040
|
-
_Modal.dequeue();
|
|
2041
|
-
}
|
|
2042
|
-
/**
|
|
2043
|
-
* An internal function where we will save promise function.
|
|
2044
|
-
*/
|
|
2045
|
-
resolve = /* @__PURE__ */ __name(() => {
|
|
2046
|
-
}, "resolve");
|
|
2047
|
-
/** A function that adds a modal to the queue and returns a promise */
|
|
2048
|
-
static enqueue(modal) {
|
|
2049
|
-
_Modal.queue.push(modal);
|
|
2050
|
-
if (!_Modal.processing) _Modal.dequeue();
|
|
2051
|
-
return new Promise((resolve) => modal.resolve = resolve);
|
|
2052
|
-
}
|
|
2053
|
-
/** A function that processes the queue, removing the first modal */
|
|
2054
|
-
static dequeue() {
|
|
2055
|
-
const modal = _Modal.queue.shift();
|
|
2056
|
-
if (modal) {
|
|
2057
|
-
_Modal.processing = true;
|
|
2058
|
-
modal.dialog.show();
|
|
2059
|
-
} else {
|
|
2060
|
-
_Modal.processing = false;
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
};
|
|
2064
1673
|
|
|
2065
1674
|
// src/screens/main_menu.ts
|
|
2066
1675
|
var MainMenu = class _MainMenu extends BaseSubscreen {
|
|
@@ -2100,7 +1709,7 @@ var MainMenu = class _MainMenu extends BaseSubscreen {
|
|
|
2100
1709
|
ElementMenu.AppendButton(menu, exitButton);
|
|
2101
1710
|
}
|
|
2102
1711
|
for (const screen of this.subscreens) {
|
|
2103
|
-
if (screen.options.name
|
|
1712
|
+
if (screen.options.name === "mainmenu") continue;
|
|
2104
1713
|
const button = advElement.createButton({
|
|
2105
1714
|
id: `${screen.options.name}-button`,
|
|
2106
1715
|
onClick: /* @__PURE__ */ __name(() => {
|
|
@@ -2174,7 +1783,7 @@ var MainMenu = class _MainMenu extends BaseSubscreen {
|
|
|
2174
1783
|
}
|
|
2175
1784
|
if (_MainMenu.options.storageFullnessIndicator) {
|
|
2176
1785
|
const maxStorageCapacityKB = 180;
|
|
2177
|
-
const currentStorageCapacityKB = byteToKB(
|
|
1786
|
+
const currentStorageCapacityKB = byteToKB(modStorage.storageSize());
|
|
2178
1787
|
const fullness = (currentStorageCapacityKB / maxStorageCapacityKB * 100).toFixed(1);
|
|
2179
1788
|
const storageFullnessWrapper = advElement.createButton({
|
|
2180
1789
|
id: CommonGenerateUniqueID(),
|
|
@@ -2256,15 +1865,317 @@ var MainMenu = class _MainMenu extends BaseSubscreen {
|
|
|
2256
1865
|
}
|
|
2257
1866
|
};
|
|
2258
1867
|
|
|
2259
|
-
// src/
|
|
2260
|
-
var
|
|
1868
|
+
// src/utilities/translation.ts
|
|
1869
|
+
var Localization = class _Localization {
|
|
2261
1870
|
static {
|
|
2262
|
-
__name(this, "
|
|
1871
|
+
__name(this, "Localization");
|
|
2263
1872
|
}
|
|
2264
|
-
|
|
2265
|
-
static
|
|
2266
|
-
|
|
2267
|
-
}
|
|
1873
|
+
static LibTranslation = {};
|
|
1874
|
+
static ModTranslation = {};
|
|
1875
|
+
static PathToModTranslation;
|
|
1876
|
+
static PathToLibTranslation = `${PUBLIC_URL}/dl_translations/`;
|
|
1877
|
+
static DefaultLanguage = "en";
|
|
1878
|
+
/** Flag to prevent re-initialization */
|
|
1879
|
+
static initialized = false;
|
|
1880
|
+
/** Initialize the localization system by loading translation files. */
|
|
1881
|
+
static async init(initOptions) {
|
|
1882
|
+
if (_Localization.initialized) return;
|
|
1883
|
+
_Localization.initialized = true;
|
|
1884
|
+
_Localization.PathToModTranslation = (() => {
|
|
1885
|
+
if (!initOptions?.pathToTranslationsFolder) return void 0;
|
|
1886
|
+
return initOptions.pathToTranslationsFolder.endsWith("/") ? initOptions.pathToTranslationsFolder : `${initOptions.pathToTranslationsFolder}/`;
|
|
1887
|
+
})();
|
|
1888
|
+
_Localization.DefaultLanguage = initOptions?.defaultLanguage || _Localization.DefaultLanguage;
|
|
1889
|
+
const lang = initOptions?.fixedLanguage ? _Localization.DefaultLanguage : TranslationLanguage.toLowerCase();
|
|
1890
|
+
const libTranslation = await _Localization.fetchLanguageFile(_Localization.PathToLibTranslation, lang);
|
|
1891
|
+
if (lang === _Localization.DefaultLanguage) {
|
|
1892
|
+
_Localization.LibTranslation = libTranslation;
|
|
1893
|
+
} else {
|
|
1894
|
+
const fallbackTranslation = await _Localization.fetchLanguageFile(_Localization.PathToLibTranslation, _Localization.DefaultLanguage);
|
|
1895
|
+
_Localization.LibTranslation = { ...fallbackTranslation, ...libTranslation };
|
|
1896
|
+
}
|
|
1897
|
+
if (!_Localization.PathToModTranslation) return;
|
|
1898
|
+
const modTranslation = await _Localization.fetchLanguageFile(_Localization.PathToModTranslation, lang);
|
|
1899
|
+
if (lang === _Localization.DefaultLanguage) {
|
|
1900
|
+
_Localization.ModTranslation = modTranslation;
|
|
1901
|
+
} else {
|
|
1902
|
+
const fallbackTranslation = await _Localization.fetchLanguageFile(_Localization.PathToModTranslation, _Localization.DefaultLanguage);
|
|
1903
|
+
_Localization.ModTranslation = { ...fallbackTranslation, ...modTranslation };
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
/** Get a translated string from mod translations by source tag. */
|
|
1907
|
+
static getTextMod(srcTag) {
|
|
1908
|
+
return _Localization.ModTranslation?.[srcTag] || void 0;
|
|
1909
|
+
}
|
|
1910
|
+
/** Get a translated string from library translations by source tag. */
|
|
1911
|
+
static getTextLib(srcTag) {
|
|
1912
|
+
return _Localization.LibTranslation?.[srcTag] || void 0;
|
|
1913
|
+
}
|
|
1914
|
+
/**
|
|
1915
|
+
* Fetch and parse a language file from the given base URL and language code.
|
|
1916
|
+
* Falls back to default language if the requested language file is unavailable.
|
|
1917
|
+
*/
|
|
1918
|
+
static async fetchLanguageFile(baseUrl, lang) {
|
|
1919
|
+
const response = await fetch(`${baseUrl}${lang}.lang`);
|
|
1920
|
+
if (lang !== _Localization.DefaultLanguage && !response.ok) {
|
|
1921
|
+
return this.fetchLanguageFile(baseUrl, _Localization.DefaultLanguage);
|
|
1922
|
+
}
|
|
1923
|
+
if (!response.ok) {
|
|
1924
|
+
return {};
|
|
1925
|
+
}
|
|
1926
|
+
const langFileContent = await response.text();
|
|
1927
|
+
return this.parseLanguageFile(langFileContent);
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* Parse the raw content of a language file into a TranslationDict.
|
|
1931
|
+
* Ignores empty lines and comments starting with '#'.
|
|
1932
|
+
*/
|
|
1933
|
+
static parseLanguageFile(content) {
|
|
1934
|
+
const translations = {};
|
|
1935
|
+
const lines = content.split("\n");
|
|
1936
|
+
for (const line of lines) {
|
|
1937
|
+
const trimmed = line.trim();
|
|
1938
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
1939
|
+
const [key, ...rest] = trimmed.split("=");
|
|
1940
|
+
translations[key.trim()] = rest.join("=").trim();
|
|
1941
|
+
}
|
|
1942
|
+
return translations;
|
|
1943
|
+
}
|
|
1944
|
+
};
|
|
1945
|
+
var getText = /* @__PURE__ */ __name((srcTag) => {
|
|
1946
|
+
return Localization.getTextMod(srcTag) || Localization.getTextLib(srcTag) || srcTag;
|
|
1947
|
+
}, "getText");
|
|
1948
|
+
|
|
1949
|
+
// src/utilities/elements/modal.ts
|
|
1950
|
+
var Modal = class _Modal {
|
|
1951
|
+
constructor(opts) {
|
|
1952
|
+
this.opts = opts;
|
|
1953
|
+
opts ??= {};
|
|
1954
|
+
opts.closeOnBackdrop ??= true;
|
|
1955
|
+
const promptId = `modal-prompt-${Date.now()}`;
|
|
1956
|
+
const prompt = (CommonIsArray(opts.prompt) ? opts.prompt : [opts.prompt]).filter((i) => i !== null) ?? [""];
|
|
1957
|
+
this.dialog = ElementCreate({
|
|
1958
|
+
tag: "dialog",
|
|
1959
|
+
classList: ["deeplib-modal"],
|
|
1960
|
+
attributes: {
|
|
1961
|
+
id: this.opts.modalId ?? `modal-${Date.now()}`,
|
|
1962
|
+
role: "dialog",
|
|
1963
|
+
"aria-modal": "true",
|
|
1964
|
+
"aria-labelledby": promptId
|
|
1965
|
+
},
|
|
1966
|
+
style: {
|
|
1967
|
+
fontFamily: CommonGetFontName()
|
|
1968
|
+
},
|
|
1969
|
+
children: [
|
|
1970
|
+
{
|
|
1971
|
+
tag: "div",
|
|
1972
|
+
classList: ["deeplib-modal-prompt-container"],
|
|
1973
|
+
children: [
|
|
1974
|
+
...prompt
|
|
1975
|
+
]
|
|
1976
|
+
},
|
|
1977
|
+
{
|
|
1978
|
+
tag: "div",
|
|
1979
|
+
classList: ["deeplib-modal-prompt"],
|
|
1980
|
+
attributes: {
|
|
1981
|
+
id: promptId
|
|
1982
|
+
},
|
|
1983
|
+
children: [
|
|
1984
|
+
opts.input ? this.renderInput(opts.input) : void 0
|
|
1985
|
+
]
|
|
1986
|
+
},
|
|
1987
|
+
this.renderButtons()
|
|
1988
|
+
]
|
|
1989
|
+
});
|
|
1990
|
+
this.blocker = this.createBlocker();
|
|
1991
|
+
this.renderButtons();
|
|
1992
|
+
document.body.append(this.createBlocker(), this.dialog);
|
|
1993
|
+
this.setupFocusTrap();
|
|
1994
|
+
if (opts.timeoutMs) {
|
|
1995
|
+
this.timeoutId = window.setTimeout(() => this.close("timeout"), opts.timeoutMs);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
static {
|
|
1999
|
+
__name(this, "Modal");
|
|
2000
|
+
}
|
|
2001
|
+
dialog;
|
|
2002
|
+
blocker;
|
|
2003
|
+
inputEl;
|
|
2004
|
+
timeoutId;
|
|
2005
|
+
/** Static modal queue. */
|
|
2006
|
+
static queue = [];
|
|
2007
|
+
/** Flag to indicate if a modal is currently being shown. */
|
|
2008
|
+
static processing = false;
|
|
2009
|
+
/**
|
|
2010
|
+
* Displays the modal and resolves with the chosen action and input value.
|
|
2011
|
+
*/
|
|
2012
|
+
show() {
|
|
2013
|
+
return _Modal.enqueue(this);
|
|
2014
|
+
}
|
|
2015
|
+
/**
|
|
2016
|
+
* Shows a simple alert modal with a single "OK" button.
|
|
2017
|
+
*/
|
|
2018
|
+
static async alert(msg, opts = {}) {
|
|
2019
|
+
await new _Modal({
|
|
2020
|
+
prompt: msg,
|
|
2021
|
+
buttons: [{ action: "close", text: getText("modal.button.ok") }],
|
|
2022
|
+
timeoutMs: opts.timeoutMs,
|
|
2023
|
+
escapeAction: "close",
|
|
2024
|
+
modalId: opts.modalId
|
|
2025
|
+
}).show();
|
|
2026
|
+
}
|
|
2027
|
+
/**
|
|
2028
|
+
* Shows a confirmation modal with "Cancel" and "OK" buttons.
|
|
2029
|
+
* Returns true if "OK" is clicked.
|
|
2030
|
+
*/
|
|
2031
|
+
static async confirm(msg, opts = {}) {
|
|
2032
|
+
const [action] = await new _Modal({
|
|
2033
|
+
prompt: msg,
|
|
2034
|
+
buttons: [{ text: getText("modal.button.decline"), action: "decline" }, { text: getText("modal.button.confirm"), action: "confirm" }],
|
|
2035
|
+
escapeAction: "decline",
|
|
2036
|
+
enterAction: "confirm",
|
|
2037
|
+
modalId: opts.modalId
|
|
2038
|
+
}).show();
|
|
2039
|
+
return action === "confirm";
|
|
2040
|
+
}
|
|
2041
|
+
/**
|
|
2042
|
+
* Shows a prompt modal with an input field and "Submit"/"Cancel" buttons.
|
|
2043
|
+
* Returns the input value if submitted, otherwise null.
|
|
2044
|
+
*/
|
|
2045
|
+
static async prompt(msg, opts = {}) {
|
|
2046
|
+
const [action, value] = await new _Modal({
|
|
2047
|
+
prompt: msg,
|
|
2048
|
+
timeoutMs: 0,
|
|
2049
|
+
input: { type: "input", defaultValue: opts.defaultValue },
|
|
2050
|
+
buttons: [{ text: getText("modal.button.cancel"), action: "cancel" }, { text: getText("modal.button.submit"), action: "submit" }],
|
|
2051
|
+
escapeAction: "cancel",
|
|
2052
|
+
enterAction: "submit",
|
|
2053
|
+
modalId: opts.modalId
|
|
2054
|
+
}).show();
|
|
2055
|
+
return action === "submit" ? value : null;
|
|
2056
|
+
}
|
|
2057
|
+
/** Creates the input element for the modal, applying configuration and validation. */
|
|
2058
|
+
renderInput(cfg) {
|
|
2059
|
+
const el = document.createElement(cfg.type);
|
|
2060
|
+
el.classList.add("deeplib-modal-input");
|
|
2061
|
+
if (cfg.placeholder) el.placeholder = cfg.placeholder;
|
|
2062
|
+
if (cfg.readOnly) el.readOnly = true;
|
|
2063
|
+
if (cfg.defaultValue) el.value = cfg.defaultValue;
|
|
2064
|
+
if (cfg.type === "textarea") el.rows = 5;
|
|
2065
|
+
el.addEventListener("input", () => {
|
|
2066
|
+
const err = cfg.validate?.(el.value);
|
|
2067
|
+
el.setCustomValidity(err || "");
|
|
2068
|
+
});
|
|
2069
|
+
this.inputEl = el;
|
|
2070
|
+
return el;
|
|
2071
|
+
}
|
|
2072
|
+
/** Creates modal action buttons from configuration. */
|
|
2073
|
+
renderButtons() {
|
|
2074
|
+
const container = document.createElement("div");
|
|
2075
|
+
container.classList.add("deeplib-modal-button-container");
|
|
2076
|
+
const btns = this.opts.buttons ? [...this.opts.buttons] : [];
|
|
2077
|
+
btns.forEach((b) => {
|
|
2078
|
+
const btn = advElement.createButton({
|
|
2079
|
+
id: `deeplib-modal-${b.action}`,
|
|
2080
|
+
onClick: /* @__PURE__ */ __name(() => this.close(b.action), "onClick"),
|
|
2081
|
+
options: {
|
|
2082
|
+
disabled: b.disabled,
|
|
2083
|
+
label: b.text
|
|
2084
|
+
}
|
|
2085
|
+
});
|
|
2086
|
+
container.append(btn);
|
|
2087
|
+
});
|
|
2088
|
+
return container;
|
|
2089
|
+
}
|
|
2090
|
+
/** Creates the modal backdrop blocker with optional click-to-close behavior. */
|
|
2091
|
+
createBlocker() {
|
|
2092
|
+
const blocker = document.createElement("div");
|
|
2093
|
+
blocker.classList.add("deeplib-modal-blocker");
|
|
2094
|
+
blocker.title = "Click to close";
|
|
2095
|
+
if (this.opts.closeOnBackdrop !== false)
|
|
2096
|
+
blocker.addEventListener("click", () => this.close("close"));
|
|
2097
|
+
return blocker;
|
|
2098
|
+
}
|
|
2099
|
+
/** Implements a focus trap to keep keyboard navigation inside the modal. */
|
|
2100
|
+
setupFocusTrap() {
|
|
2101
|
+
const focusable = 'button, [href], input, textarea, select, [tabindex]:not([tabindex="-1"])';
|
|
2102
|
+
const elements = Array.from(this.dialog.querySelectorAll(focusable));
|
|
2103
|
+
const first = elements[0];
|
|
2104
|
+
const last = elements[elements.length - 1];
|
|
2105
|
+
this.dialog.addEventListener("keydown", (e) => {
|
|
2106
|
+
if (e.key === "Tab") {
|
|
2107
|
+
if (elements.length === 0) {
|
|
2108
|
+
e.preventDefault();
|
|
2109
|
+
return;
|
|
2110
|
+
}
|
|
2111
|
+
if (e.shiftKey) {
|
|
2112
|
+
if (document.activeElement === first) {
|
|
2113
|
+
last.focus();
|
|
2114
|
+
e.preventDefault();
|
|
2115
|
+
}
|
|
2116
|
+
} else {
|
|
2117
|
+
if (document.activeElement === last) {
|
|
2118
|
+
first.focus();
|
|
2119
|
+
e.preventDefault();
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
} else if (e.key === "Escape") {
|
|
2123
|
+
e.stopPropagation();
|
|
2124
|
+
this.close(this.opts.escapeAction ?? "close");
|
|
2125
|
+
} else if (e.key === "Enter") {
|
|
2126
|
+
if (elements.some((el) => el === document.activeElement) && document.activeElement !== this.inputEl) return;
|
|
2127
|
+
e.preventDefault();
|
|
2128
|
+
e.stopPropagation();
|
|
2129
|
+
this.close(this.opts.enterAction ?? "submit");
|
|
2130
|
+
}
|
|
2131
|
+
});
|
|
2132
|
+
window.requestAnimationFrame(() => {
|
|
2133
|
+
(this.inputEl || first)?.focus();
|
|
2134
|
+
});
|
|
2135
|
+
}
|
|
2136
|
+
/** Closes the modal, cleans up DOM, resolves promise, and shows next queued modal. */
|
|
2137
|
+
close(action) {
|
|
2138
|
+
if (this.timeoutId) clearTimeout(this.timeoutId);
|
|
2139
|
+
this.dialog.close();
|
|
2140
|
+
this.dialog.remove();
|
|
2141
|
+
this.blocker.remove();
|
|
2142
|
+
document.body.querySelector(".deeplib-modal-blocker")?.remove();
|
|
2143
|
+
const value = this.inputEl?.value ?? "";
|
|
2144
|
+
this.resolve([action, value]);
|
|
2145
|
+
_Modal.dequeue();
|
|
2146
|
+
}
|
|
2147
|
+
/**
|
|
2148
|
+
* An internal function where we will save promise function.
|
|
2149
|
+
*/
|
|
2150
|
+
resolve = /* @__PURE__ */ __name(() => {
|
|
2151
|
+
}, "resolve");
|
|
2152
|
+
/** A function that adds a modal to the queue and returns a promise */
|
|
2153
|
+
static enqueue(modal) {
|
|
2154
|
+
_Modal.queue.push(modal);
|
|
2155
|
+
if (!_Modal.processing) _Modal.dequeue();
|
|
2156
|
+
return new Promise((resolve) => modal.resolve = resolve);
|
|
2157
|
+
}
|
|
2158
|
+
/** A function that processes the queue, removing the first modal */
|
|
2159
|
+
static dequeue() {
|
|
2160
|
+
const modal = _Modal.queue.shift();
|
|
2161
|
+
if (modal) {
|
|
2162
|
+
_Modal.processing = true;
|
|
2163
|
+
modal.dialog.show();
|
|
2164
|
+
} else {
|
|
2165
|
+
_Modal.processing = false;
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
};
|
|
2169
|
+
|
|
2170
|
+
// src/screens/import_export.ts
|
|
2171
|
+
var GuiImportExport = class extends BaseSubscreen {
|
|
2172
|
+
static {
|
|
2173
|
+
__name(this, "GuiImportExport");
|
|
2174
|
+
}
|
|
2175
|
+
importExportOptions;
|
|
2176
|
+
static subscreenOptions = {
|
|
2177
|
+
name: "import-export"
|
|
2178
|
+
};
|
|
2268
2179
|
constructor(importExportOptions) {
|
|
2269
2180
|
super();
|
|
2270
2181
|
this.importExportOptions = importExportOptions;
|
|
@@ -2326,7 +2237,13 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2326
2237
|
/** Exports the mod data using the specified method. */
|
|
2327
2238
|
async dataExport(transferMethod) {
|
|
2328
2239
|
try {
|
|
2329
|
-
const
|
|
2240
|
+
const selected = await this.getSelectedModules(modules(), "export");
|
|
2241
|
+
if (!selected) return;
|
|
2242
|
+
if (selected.length === 0) {
|
|
2243
|
+
ToastManager.error("No modules selected for export.");
|
|
2244
|
+
return;
|
|
2245
|
+
}
|
|
2246
|
+
const data = this.buildExportPayload(selected);
|
|
2330
2247
|
if (transferMethod === "clipboard") {
|
|
2331
2248
|
await this.exportToClipboard(data);
|
|
2332
2249
|
} else if (transferMethod === "file") {
|
|
@@ -2339,34 +2256,22 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2339
2256
|
ToastManager.success("Data exported successfully.");
|
|
2340
2257
|
} catch (error) {
|
|
2341
2258
|
ToastManager.error("Data export failed.");
|
|
2342
|
-
|
|
2259
|
+
modLogger.error("Data export failed.", error);
|
|
2343
2260
|
}
|
|
2344
2261
|
}
|
|
2345
2262
|
/** Imports mod data using the specified method. */
|
|
2346
2263
|
async dataImport(transferMethod) {
|
|
2347
2264
|
try {
|
|
2348
|
-
|
|
2349
|
-
if (
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
}
|
|
2354
|
-
if (!importedData) {
|
|
2355
|
-
throw new Error("No data imported.");
|
|
2356
|
-
}
|
|
2357
|
-
const data = JSON.parse(LZString.decompressFromBase64(importedData) ?? "");
|
|
2358
|
-
if (!data) {
|
|
2359
|
-
throw new Error("Invalid data.");
|
|
2360
|
-
}
|
|
2361
|
-
for (const module of modules()) {
|
|
2362
|
-
module.registerDefaultSettings(data);
|
|
2363
|
-
}
|
|
2364
|
-
modStorage.playerStorage = data;
|
|
2265
|
+
const raw = transferMethod === "clipboard" ? await this.importFromClipboard() : await this.importFromFile();
|
|
2266
|
+
if (raw === null) return;
|
|
2267
|
+
if (!raw) throw new Error("No data");
|
|
2268
|
+
const importResult = await this.applyImportPayload(raw);
|
|
2269
|
+
if (!importResult) return;
|
|
2365
2270
|
this.importExportOptions.onImport?.();
|
|
2366
2271
|
ToastManager.success("Data imported successfully.");
|
|
2367
2272
|
} catch (error) {
|
|
2368
2273
|
ToastManager.error("Data import failed.");
|
|
2369
|
-
|
|
2274
|
+
modLogger.error("Data import failed.", error);
|
|
2370
2275
|
}
|
|
2371
2276
|
}
|
|
2372
2277
|
/** Saves data to a file using the browser's save dialog. */
|
|
@@ -2392,7 +2297,7 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2392
2297
|
throw new Error("File save cancelled or failed: " + error.message);
|
|
2393
2298
|
}
|
|
2394
2299
|
} else {
|
|
2395
|
-
const fileName = await Modal.prompt("Enter file name", suggestedName);
|
|
2300
|
+
const fileName = await Modal.prompt("Enter file name", { defaultValue: suggestedName });
|
|
2396
2301
|
if (fileName === null) {
|
|
2397
2302
|
return false;
|
|
2398
2303
|
} else if (fileName === "") {
|
|
@@ -2476,6 +2381,72 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2476
2381
|
throw new Error("Failed to read data from clipboard." + error);
|
|
2477
2382
|
});
|
|
2478
2383
|
}
|
|
2384
|
+
async getSelectedModules(modulesToChoose, transferDirection) {
|
|
2385
|
+
const modulesFiltered = modulesToChoose.filter((m) => hasGetter(m, "settings") && !!m.settings);
|
|
2386
|
+
const checkedModules = Object.fromEntries(
|
|
2387
|
+
modulesFiltered.map((m) => [m.constructor.name, true])
|
|
2388
|
+
);
|
|
2389
|
+
if (modulesFiltered.length === 0) {
|
|
2390
|
+
throw new Error("No modules to choose from.");
|
|
2391
|
+
}
|
|
2392
|
+
const checkboxes = modulesFiltered.map((m) => advElement.createCheckbox({
|
|
2393
|
+
id: m.constructor.name,
|
|
2394
|
+
label: getText(m.constructor.name),
|
|
2395
|
+
setElementValue: /* @__PURE__ */ __name(() => checkedModules[m.constructor.name], "setElementValue"),
|
|
2396
|
+
setSettingValue: /* @__PURE__ */ __name((val) => checkedModules[m.constructor.name] = val, "setSettingValue")
|
|
2397
|
+
}));
|
|
2398
|
+
const text = transferDirection === "import" ? "import_export.import.select_modules" : "import_export.export.select_modules";
|
|
2399
|
+
const response = await Modal.confirm([
|
|
2400
|
+
getText(text),
|
|
2401
|
+
ElementCreate({ tag: "br" }),
|
|
2402
|
+
getText("import_export.text.not_sure"),
|
|
2403
|
+
{
|
|
2404
|
+
tag: "div",
|
|
2405
|
+
classList: ["deeplib-modal-checkbox-container"],
|
|
2406
|
+
children: checkboxes
|
|
2407
|
+
}
|
|
2408
|
+
], { modalId: "deeplib-modal-import_export" });
|
|
2409
|
+
if (!response) {
|
|
2410
|
+
return null;
|
|
2411
|
+
}
|
|
2412
|
+
const ret = Object.entries(checkedModules).filter(([_, checked]) => checked).map(([id]) => getModule(id)).filter((m) => !!m);
|
|
2413
|
+
if (ret.length === 0) {
|
|
2414
|
+
throw new Error("No modules selected.");
|
|
2415
|
+
}
|
|
2416
|
+
return ret;
|
|
2417
|
+
}
|
|
2418
|
+
buildExportPayload(selectedModules) {
|
|
2419
|
+
const payload = {};
|
|
2420
|
+
for (const module of selectedModules) {
|
|
2421
|
+
if (!hasGetter(module, "settings") || module.settings === null) continue;
|
|
2422
|
+
payload[module.constructor.name] = module.settings;
|
|
2423
|
+
}
|
|
2424
|
+
return LZString.compressToBase64(JSON.stringify(payload));
|
|
2425
|
+
}
|
|
2426
|
+
async applyImportPayload(raw) {
|
|
2427
|
+
const decoded = JSON.parse(
|
|
2428
|
+
LZString.decompressFromBase64(raw) ?? ""
|
|
2429
|
+
);
|
|
2430
|
+
if (!decoded) {
|
|
2431
|
+
throw new Error("Invalid import format.");
|
|
2432
|
+
}
|
|
2433
|
+
const modules2 = Object.keys(decoded).map((id) => getModule(id)).filter((m) => !!m);
|
|
2434
|
+
const selectedModules = await this.getSelectedModules(modules2, "import");
|
|
2435
|
+
if (!selectedModules) {
|
|
2436
|
+
return false;
|
|
2437
|
+
}
|
|
2438
|
+
if (selectedModules.length === 0) {
|
|
2439
|
+
throw new Error("No modules selected.");
|
|
2440
|
+
}
|
|
2441
|
+
for (const module of selectedModules) {
|
|
2442
|
+
const data = decoded[module.constructor.name];
|
|
2443
|
+
if (!data) continue;
|
|
2444
|
+
const merged = deepMerge(module.defaultSettings, data);
|
|
2445
|
+
if (!merged) continue;
|
|
2446
|
+
module.settings = merged;
|
|
2447
|
+
}
|
|
2448
|
+
return true;
|
|
2449
|
+
}
|
|
2479
2450
|
};
|
|
2480
2451
|
|
|
2481
2452
|
// src/utilities/data.ts
|
|
@@ -2520,7 +2491,7 @@ var ModStorage = class _ModStorage {
|
|
|
2520
2491
|
const parsed = _ModStorage.dataDecompress(this.extensionStorage || "");
|
|
2521
2492
|
if (parsed === null || !Object.hasOwn(parsed, "Version")) {
|
|
2522
2493
|
this.playerStorage = {
|
|
2523
|
-
Version:
|
|
2494
|
+
Version: MOD_VERSION
|
|
2524
2495
|
};
|
|
2525
2496
|
} else {
|
|
2526
2497
|
this.playerStorage = parsed;
|
|
@@ -2535,6 +2506,9 @@ var ModStorage = class _ModStorage {
|
|
|
2535
2506
|
this.extensionStorage = _ModStorage.dataCompress(this.playerStorage);
|
|
2536
2507
|
ServerPlayerExtensionSettingsSync(this.modName);
|
|
2537
2508
|
}
|
|
2509
|
+
storageSize() {
|
|
2510
|
+
return _ModStorage.measureSize(this.extensionStorage);
|
|
2511
|
+
}
|
|
2538
2512
|
static dataDecompress(string) {
|
|
2539
2513
|
const d = LZString.decompressFromBase64(string);
|
|
2540
2514
|
let data = null;
|
|
@@ -2542,7 +2516,7 @@ var ModStorage = class _ModStorage {
|
|
|
2542
2516
|
const decoded = JSON.parse(d);
|
|
2543
2517
|
data = decoded;
|
|
2544
2518
|
} catch (error) {
|
|
2545
|
-
|
|
2519
|
+
modLogger.error(error);
|
|
2546
2520
|
}
|
|
2547
2521
|
return data;
|
|
2548
2522
|
}
|
|
@@ -2599,15 +2573,18 @@ var domUtil = {
|
|
|
2599
2573
|
function autoSetPosition(_, position) {
|
|
2600
2574
|
let xPos = void 0;
|
|
2601
2575
|
let yPos = void 0;
|
|
2576
|
+
let anchor = void 0;
|
|
2602
2577
|
if (Array.isArray(position)) {
|
|
2603
2578
|
xPos = position[0];
|
|
2604
2579
|
yPos = position[1];
|
|
2580
|
+
anchor = position[2];
|
|
2605
2581
|
} else if (typeof position === "function") {
|
|
2606
2582
|
const result = position();
|
|
2607
2583
|
xPos = result[0];
|
|
2608
2584
|
yPos = result[1];
|
|
2585
|
+
anchor = result[2];
|
|
2609
2586
|
}
|
|
2610
|
-
if (xPos !== void 0 && yPos !== void 0) ElementSetPosition(_, xPos, yPos);
|
|
2587
|
+
if (xPos !== void 0 && yPos !== void 0) ElementSetPosition(_, xPos, yPos, anchor);
|
|
2611
2588
|
}
|
|
2612
2589
|
__name(autoSetPosition, "autoSetPosition");
|
|
2613
2590
|
function autoSetSize(_, size) {
|
|
@@ -2842,9 +2819,6 @@ function sendActionMessage(msg, target = void 0, dictionary = []) {
|
|
|
2842
2819
|
__name(sendActionMessage, "sendActionMessage");
|
|
2843
2820
|
|
|
2844
2821
|
// src/utilities/sdk.ts
|
|
2845
|
-
var import_bondage_club_mod_sdk = __toESM(require_bcmodsdk(), 1);
|
|
2846
|
-
var rawSdk = import_bondage_club_mod_sdk.default;
|
|
2847
|
-
var bcModSdkRef = rawSdk.default ?? rawSdk;
|
|
2848
2822
|
var HookPriority = {
|
|
2849
2823
|
Observe: 0,
|
|
2850
2824
|
AddBehavior: 1,
|
|
@@ -2852,27 +2826,25 @@ var HookPriority = {
|
|
|
2852
2826
|
OverrideBehavior: 10,
|
|
2853
2827
|
Top: 100
|
|
2854
2828
|
};
|
|
2855
|
-
var ModSdkManager = class
|
|
2829
|
+
var ModSdkManager = class {
|
|
2856
2830
|
static {
|
|
2857
2831
|
__name(this, "ModSdkManager");
|
|
2858
2832
|
}
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
static ModInfo;
|
|
2833
|
+
SDK;
|
|
2834
|
+
patchedFunctions = /* @__PURE__ */ new Map();
|
|
2862
2835
|
/** Registers a mod with the SDK and stores mod information. */
|
|
2863
2836
|
constructor(info, options) {
|
|
2864
|
-
|
|
2865
|
-
_ModSdkManager.ModInfo = info;
|
|
2837
|
+
this.SDK = bcModSdk.registerMod(info, options);
|
|
2866
2838
|
}
|
|
2867
2839
|
/** Retrieves or initializes patch data for a given target function. */
|
|
2868
2840
|
initPatchableFunction(target) {
|
|
2869
|
-
let result =
|
|
2841
|
+
let result = this.patchedFunctions.get(target);
|
|
2870
2842
|
if (!result) {
|
|
2871
2843
|
result = {
|
|
2872
2844
|
name: target,
|
|
2873
2845
|
hooks: []
|
|
2874
2846
|
};
|
|
2875
|
-
|
|
2847
|
+
this.patchedFunctions.set(target, result);
|
|
2876
2848
|
}
|
|
2877
2849
|
return result;
|
|
2878
2850
|
}
|
|
@@ -2886,7 +2858,7 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2886
2858
|
if (data.hooks.some((h) => h.hook === hook)) {
|
|
2887
2859
|
return () => null;
|
|
2888
2860
|
}
|
|
2889
|
-
const removeCallback =
|
|
2861
|
+
const removeCallback = this.SDK.hookFunction(target, priority, hook);
|
|
2890
2862
|
data.hooks.push({
|
|
2891
2863
|
hook,
|
|
2892
2864
|
priority,
|
|
@@ -2902,13 +2874,13 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2902
2874
|
* **This method is DANGEROUS** to use and has high potential to conflict with other mods.
|
|
2903
2875
|
*/
|
|
2904
2876
|
patchFunction(target, patches) {
|
|
2905
|
-
|
|
2877
|
+
this.SDK.patchFunction(target, patches);
|
|
2906
2878
|
}
|
|
2907
2879
|
/**
|
|
2908
2880
|
* Removes all patches from a target function.
|
|
2909
2881
|
*/
|
|
2910
2882
|
unpatchFunction(target) {
|
|
2911
|
-
|
|
2883
|
+
this.SDK.removePatches(target);
|
|
2912
2884
|
}
|
|
2913
2885
|
/**
|
|
2914
2886
|
* Removes all hooks associated with a specific module from a target function.
|
|
@@ -2927,7 +2899,7 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2927
2899
|
* Removes all hooks associated with a specific module across all patched functions.
|
|
2928
2900
|
*/
|
|
2929
2901
|
removeAllHooksByModule(module) {
|
|
2930
|
-
for (const data of
|
|
2902
|
+
for (const data of this.patchedFunctions.values()) {
|
|
2931
2903
|
for (let i = data.hooks.length - 1; i >= 0; i--) {
|
|
2932
2904
|
if (data.hooks[i].module === module) {
|
|
2933
2905
|
data.hooks[i].removeCallback();
|
|
@@ -2937,6 +2909,12 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2937
2909
|
}
|
|
2938
2910
|
return true;
|
|
2939
2911
|
}
|
|
2912
|
+
/**
|
|
2913
|
+
* Unloads the mod removing all hooks and patches by it.
|
|
2914
|
+
*/
|
|
2915
|
+
unload() {
|
|
2916
|
+
this.SDK.unload();
|
|
2917
|
+
}
|
|
2940
2918
|
};
|
|
2941
2919
|
|
|
2942
2920
|
// src/utilities/style.ts
|
|
@@ -2989,87 +2967,6 @@ var Style = {
|
|
|
2989
2967
|
}
|
|
2990
2968
|
};
|
|
2991
2969
|
|
|
2992
|
-
// src/utilities/translation.ts
|
|
2993
|
-
var Localization = class _Localization {
|
|
2994
|
-
static {
|
|
2995
|
-
__name(this, "Localization");
|
|
2996
|
-
}
|
|
2997
|
-
static LibTranslation = {};
|
|
2998
|
-
static ModTranslation = {};
|
|
2999
|
-
static PathToModTranslation;
|
|
3000
|
-
static PathToLibTranslation = `${PUBLIC_URL}/dl_translations/`;
|
|
3001
|
-
static DefaultLanguage = "en";
|
|
3002
|
-
/** Flag to prevent re-initialization */
|
|
3003
|
-
static initialized = false;
|
|
3004
|
-
/** Initialize the localization system by loading translation files. */
|
|
3005
|
-
static async init(initOptions) {
|
|
3006
|
-
if (_Localization.initialized) return;
|
|
3007
|
-
_Localization.initialized = true;
|
|
3008
|
-
_Localization.PathToModTranslation = (() => {
|
|
3009
|
-
if (!initOptions?.pathToTranslationsFolder) return void 0;
|
|
3010
|
-
return initOptions.pathToTranslationsFolder.endsWith("/") ? initOptions.pathToTranslationsFolder : `${initOptions.pathToTranslationsFolder}/`;
|
|
3011
|
-
})();
|
|
3012
|
-
_Localization.DefaultLanguage = initOptions?.defaultLanguage || _Localization.DefaultLanguage;
|
|
3013
|
-
const lang = initOptions?.fixedLanguage ? _Localization.DefaultLanguage : TranslationLanguage.toLowerCase();
|
|
3014
|
-
const libTranslation = await _Localization.fetchLanguageFile(_Localization.PathToLibTranslation, lang);
|
|
3015
|
-
if (lang === _Localization.DefaultLanguage) {
|
|
3016
|
-
_Localization.LibTranslation = libTranslation;
|
|
3017
|
-
} else {
|
|
3018
|
-
const fallbackTranslation = await _Localization.fetchLanguageFile(_Localization.PathToLibTranslation, _Localization.DefaultLanguage);
|
|
3019
|
-
_Localization.LibTranslation = { ...fallbackTranslation, ...libTranslation };
|
|
3020
|
-
}
|
|
3021
|
-
if (!_Localization.PathToModTranslation) return;
|
|
3022
|
-
const modTranslation = await _Localization.fetchLanguageFile(_Localization.PathToModTranslation, lang);
|
|
3023
|
-
if (lang === _Localization.DefaultLanguage) {
|
|
3024
|
-
_Localization.ModTranslation = modTranslation;
|
|
3025
|
-
} else {
|
|
3026
|
-
const fallbackTranslation = await _Localization.fetchLanguageFile(_Localization.PathToModTranslation, _Localization.DefaultLanguage);
|
|
3027
|
-
_Localization.ModTranslation = { ...fallbackTranslation, ...modTranslation };
|
|
3028
|
-
}
|
|
3029
|
-
}
|
|
3030
|
-
/** Get a translated string from mod translations by source tag. */
|
|
3031
|
-
static getTextMod(srcTag) {
|
|
3032
|
-
return _Localization.ModTranslation?.[srcTag] || void 0;
|
|
3033
|
-
}
|
|
3034
|
-
/** Get a translated string from library translations by source tag. */
|
|
3035
|
-
static getTextLib(srcTag) {
|
|
3036
|
-
return _Localization.LibTranslation?.[srcTag] || void 0;
|
|
3037
|
-
}
|
|
3038
|
-
/**
|
|
3039
|
-
* Fetch and parse a language file from the given base URL and language code.
|
|
3040
|
-
* Falls back to default language if the requested language file is unavailable.
|
|
3041
|
-
*/
|
|
3042
|
-
static async fetchLanguageFile(baseUrl, lang) {
|
|
3043
|
-
const response = await fetch(`${baseUrl}${lang}.lang`);
|
|
3044
|
-
if (lang !== _Localization.DefaultLanguage && !response.ok) {
|
|
3045
|
-
return this.fetchLanguageFile(baseUrl, _Localization.DefaultLanguage);
|
|
3046
|
-
}
|
|
3047
|
-
if (!response.ok) {
|
|
3048
|
-
return {};
|
|
3049
|
-
}
|
|
3050
|
-
const langFileContent = await response.text();
|
|
3051
|
-
return this.parseLanguageFile(langFileContent);
|
|
3052
|
-
}
|
|
3053
|
-
/**
|
|
3054
|
-
* Parse the raw content of a language file into a TranslationDict.
|
|
3055
|
-
* Ignores empty lines and comments starting with '#'.
|
|
3056
|
-
*/
|
|
3057
|
-
static parseLanguageFile(content) {
|
|
3058
|
-
const translations = {};
|
|
3059
|
-
const lines = content.split("\n");
|
|
3060
|
-
for (const line of lines) {
|
|
3061
|
-
const trimmed = line.trim();
|
|
3062
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
3063
|
-
const [key, ...rest] = trimmed.split("=");
|
|
3064
|
-
translations[key.trim()] = rest.join("=").trim();
|
|
3065
|
-
}
|
|
3066
|
-
return translations;
|
|
3067
|
-
}
|
|
3068
|
-
};
|
|
3069
|
-
var getText = /* @__PURE__ */ __name((srcTag) => {
|
|
3070
|
-
return Localization.getTextMod(srcTag) || Localization.getTextLib(srcTag) || srcTag;
|
|
3071
|
-
}, "getText");
|
|
3072
|
-
|
|
3073
2970
|
// src/utilities/event_channel.ts
|
|
3074
2971
|
var EventChannel = class {
|
|
3075
2972
|
constructor(channelName) {
|
|
@@ -3140,6 +3037,7 @@ export {
|
|
|
3140
3037
|
HookPriority,
|
|
3141
3038
|
Localization,
|
|
3142
3039
|
Logger,
|
|
3040
|
+
MOD_NAME,
|
|
3143
3041
|
MainMenu,
|
|
3144
3042
|
ModSdkManager,
|
|
3145
3043
|
ModStorage,
|
|
@@ -3158,10 +3056,9 @@ export {
|
|
|
3158
3056
|
hasSetter,
|
|
3159
3057
|
initMod,
|
|
3160
3058
|
layout,
|
|
3161
|
-
|
|
3059
|
+
modLogger,
|
|
3162
3060
|
modStorage,
|
|
3163
3061
|
modules,
|
|
3164
|
-
modulesMap,
|
|
3165
3062
|
registerModule,
|
|
3166
3063
|
sdk,
|
|
3167
3064
|
sendActionMessage,
|