bc-deeplib 2.4.1 → 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 +136 -107
- package/dist/deeplib.js +503 -607
- 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.
|
|
@@ -271,7 +68,7 @@ var BaseModule = class {
|
|
|
271
68
|
const defaults = this.defaultSettings;
|
|
272
69
|
if (!storage || !defaults) return;
|
|
273
70
|
if (Object.entries(this.defaultSettings).length === 0) return;
|
|
274
|
-
target[storage] = deepMerge(this.defaultSettings, target[storage], { concatArrays: false });
|
|
71
|
+
target[storage] = deepMerge(this.defaultSettings, target[storage], { concatArrays: false, matchingOnly: true });
|
|
275
72
|
}
|
|
276
73
|
/**
|
|
277
74
|
* Provides default settings for this 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. */
|
|
@@ -1439,7 +1263,7 @@ function isPlainObject(value) {
|
|
|
1439
1263
|
return value !== null && typeof value === "object" && Object.getPrototypeOf(value) === Object.prototype && !Array.isArray(value);
|
|
1440
1264
|
}
|
|
1441
1265
|
__name(isPlainObject, "isPlainObject");
|
|
1442
|
-
function deepMerge(target, source, options = { concatArrays: true }) {
|
|
1266
|
+
function deepMerge(target, source, options = { concatArrays: true, matchingOnly: false }) {
|
|
1443
1267
|
if (target === void 0) return source;
|
|
1444
1268
|
if (source === void 0) return target;
|
|
1445
1269
|
if (Array.isArray(target) && Array.isArray(source) && options.concatArrays) {
|
|
@@ -1447,10 +1271,9 @@ function deepMerge(target, source, options = { concatArrays: true }) {
|
|
|
1447
1271
|
}
|
|
1448
1272
|
if (isPlainObject(target) && isPlainObject(source)) {
|
|
1449
1273
|
const result = { ...target };
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
}
|
|
1274
|
+
const keys = options.matchingOnly ? Object.keys(source).filter((k) => k in target) : Object.keys(source);
|
|
1275
|
+
for (const key of keys) {
|
|
1276
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
1454
1277
|
result[key] = key in target ? deepMerge(target[key], source[key], options) : source[key];
|
|
1455
1278
|
}
|
|
1456
1279
|
return result;
|
|
@@ -1481,7 +1304,7 @@ function exportToGlobal(name, value) {
|
|
|
1481
1304
|
current[keys[keys.length - 1]] = value;
|
|
1482
1305
|
}
|
|
1483
1306
|
__name(exportToGlobal, "exportToGlobal");
|
|
1484
|
-
function
|
|
1307
|
+
function hasGetter(obj, prop) {
|
|
1485
1308
|
while (obj && obj !== Object.prototype) {
|
|
1486
1309
|
const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
|
|
1487
1310
|
if (descriptor?.get) return true;
|
|
@@ -1489,8 +1312,8 @@ function hasGetter3(obj, prop) {
|
|
|
1489
1312
|
}
|
|
1490
1313
|
return false;
|
|
1491
1314
|
}
|
|
1492
|
-
__name(
|
|
1493
|
-
function
|
|
1315
|
+
__name(hasGetter, "hasGetter");
|
|
1316
|
+
function hasSetter(obj, prop) {
|
|
1494
1317
|
while (obj && obj !== Object.prototype) {
|
|
1495
1318
|
const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
|
|
1496
1319
|
if (descriptor?.set) return true;
|
|
@@ -1498,7 +1321,7 @@ function hasSetter3(obj, prop) {
|
|
|
1498
1321
|
}
|
|
1499
1322
|
return false;
|
|
1500
1323
|
}
|
|
1501
|
-
__name(
|
|
1324
|
+
__name(hasSetter, "hasSetter");
|
|
1502
1325
|
var byteToKB = /* @__PURE__ */ __name((nByte) => Math.round(nByte / 100) / 10, "byteToKB");
|
|
1503
1326
|
|
|
1504
1327
|
// src/utilities/elements/elements.ts
|
|
@@ -1847,221 +1670,6 @@ function elementPrevNext(options) {
|
|
|
1847
1670
|
return retElem;
|
|
1848
1671
|
}
|
|
1849
1672
|
__name(elementPrevNext, "elementPrevNext");
|
|
1850
|
-
var Modal = class _Modal {
|
|
1851
|
-
constructor(opts) {
|
|
1852
|
-
this.opts = opts;
|
|
1853
|
-
opts ??= {};
|
|
1854
|
-
opts.closeOnBackdrop ??= true;
|
|
1855
|
-
const promptId = `modal-prompt-${Date.now()}`;
|
|
1856
|
-
const prompt = (CommonIsArray(opts.prompt) ? opts.prompt : [opts.prompt]).filter((i) => i != null) ?? [""];
|
|
1857
|
-
this.dialog = ElementCreate({
|
|
1858
|
-
tag: "dialog",
|
|
1859
|
-
classList: ["deeplib-modal"],
|
|
1860
|
-
attributes: {
|
|
1861
|
-
role: "dialog",
|
|
1862
|
-
"aria-modal": "true",
|
|
1863
|
-
"aria-labelledby": promptId
|
|
1864
|
-
},
|
|
1865
|
-
style: {
|
|
1866
|
-
fontFamily: CommonGetFontName()
|
|
1867
|
-
},
|
|
1868
|
-
children: [
|
|
1869
|
-
{
|
|
1870
|
-
tag: "div",
|
|
1871
|
-
classList: ["deeplib-modal-prompt-container"],
|
|
1872
|
-
children: [
|
|
1873
|
-
...prompt
|
|
1874
|
-
]
|
|
1875
|
-
},
|
|
1876
|
-
{
|
|
1877
|
-
tag: "div",
|
|
1878
|
-
classList: ["deeplib-modal-prompt"],
|
|
1879
|
-
attributes: {
|
|
1880
|
-
id: promptId
|
|
1881
|
-
},
|
|
1882
|
-
children: [
|
|
1883
|
-
opts.input ? this.renderInput(opts.input) : void 0
|
|
1884
|
-
]
|
|
1885
|
-
},
|
|
1886
|
-
this.renderButtons()
|
|
1887
|
-
]
|
|
1888
|
-
});
|
|
1889
|
-
this.blocker = this.createBlocker();
|
|
1890
|
-
this.renderButtons();
|
|
1891
|
-
document.body.append(this.createBlocker(), this.dialog);
|
|
1892
|
-
this.setupFocusTrap();
|
|
1893
|
-
if (opts.timeoutMs) {
|
|
1894
|
-
this.timeoutId = window.setTimeout(() => this.close("timeout"), opts.timeoutMs);
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
static {
|
|
1898
|
-
__name(this, "Modal");
|
|
1899
|
-
}
|
|
1900
|
-
dialog;
|
|
1901
|
-
blocker;
|
|
1902
|
-
inputEl;
|
|
1903
|
-
timeoutId;
|
|
1904
|
-
/** Static modal queue. */
|
|
1905
|
-
static queue = [];
|
|
1906
|
-
/** Flag to indicate if a modal is currently being shown. */
|
|
1907
|
-
static processing = false;
|
|
1908
|
-
/**
|
|
1909
|
-
* Displays the modal and resolves with the chosen action and input value.
|
|
1910
|
-
*/
|
|
1911
|
-
show() {
|
|
1912
|
-
return _Modal.enqueue(this);
|
|
1913
|
-
}
|
|
1914
|
-
/**
|
|
1915
|
-
* Shows a simple alert modal with a single "OK" button.
|
|
1916
|
-
*/
|
|
1917
|
-
static async alert(msg, timeoutMs) {
|
|
1918
|
-
await new _Modal({
|
|
1919
|
-
prompt: msg,
|
|
1920
|
-
buttons: [{ action: "close", text: getText("modal.button.ok") }],
|
|
1921
|
-
timeoutMs,
|
|
1922
|
-
escapeAction: "close"
|
|
1923
|
-
}).show();
|
|
1924
|
-
}
|
|
1925
|
-
/**
|
|
1926
|
-
* Shows a confirmation modal with "Cancel" and "OK" buttons.
|
|
1927
|
-
* Returns true if "OK" is clicked.
|
|
1928
|
-
*/
|
|
1929
|
-
static async confirm(msg) {
|
|
1930
|
-
const [action] = await new _Modal({
|
|
1931
|
-
prompt: msg,
|
|
1932
|
-
buttons: [{ text: getText("modal.button.decline"), action: "decline" }, { text: getText("modal.button.confirm"), action: "confirm" }],
|
|
1933
|
-
escapeAction: "decline",
|
|
1934
|
-
enterAction: "confirm"
|
|
1935
|
-
}).show();
|
|
1936
|
-
return action === "confirm";
|
|
1937
|
-
}
|
|
1938
|
-
/**
|
|
1939
|
-
* Shows a prompt modal with an input field and "Submit"/"Cancel" buttons.
|
|
1940
|
-
* Returns the input value if submitted, otherwise null.
|
|
1941
|
-
*/
|
|
1942
|
-
static async prompt(msg, defaultValue = "") {
|
|
1943
|
-
const [action, value] = await new _Modal({
|
|
1944
|
-
prompt: msg,
|
|
1945
|
-
timeoutMs: 0,
|
|
1946
|
-
input: { type: "input", defaultValue },
|
|
1947
|
-
buttons: [{ text: getText("modal.button.cancel"), action: "cancel" }, { text: getText("modal.button.submit"), action: "submit" }],
|
|
1948
|
-
escapeAction: "cancel",
|
|
1949
|
-
enterAction: "submit"
|
|
1950
|
-
}).show();
|
|
1951
|
-
return action === "submit" ? value : null;
|
|
1952
|
-
}
|
|
1953
|
-
/** Creates the input element for the modal, applying configuration and validation. */
|
|
1954
|
-
renderInput(cfg) {
|
|
1955
|
-
const el = document.createElement(cfg.type);
|
|
1956
|
-
el.classList.add("deeplib-modal-input");
|
|
1957
|
-
if (cfg.placeholder) el.placeholder = cfg.placeholder;
|
|
1958
|
-
if (cfg.readOnly) el.readOnly = true;
|
|
1959
|
-
if (cfg.defaultValue) el.value = cfg.defaultValue;
|
|
1960
|
-
if (cfg.type === "textarea") el.rows = 5;
|
|
1961
|
-
el.addEventListener("input", () => {
|
|
1962
|
-
const err = cfg.validate?.(el.value);
|
|
1963
|
-
el.setCustomValidity(err || "");
|
|
1964
|
-
});
|
|
1965
|
-
this.inputEl = el;
|
|
1966
|
-
return el;
|
|
1967
|
-
}
|
|
1968
|
-
/** Creates modal action buttons from configuration. */
|
|
1969
|
-
renderButtons() {
|
|
1970
|
-
const container = document.createElement("div");
|
|
1971
|
-
container.classList.add("deeplib-modal-button-container");
|
|
1972
|
-
const btns = this.opts.buttons ? [...this.opts.buttons] : [];
|
|
1973
|
-
btns.forEach((b) => {
|
|
1974
|
-
const btn = advElement.createButton({
|
|
1975
|
-
id: `deeplib-modal-${b.action}`,
|
|
1976
|
-
onClick: /* @__PURE__ */ __name(() => this.close(b.action), "onClick"),
|
|
1977
|
-
options: {
|
|
1978
|
-
disabled: b.disabled,
|
|
1979
|
-
label: b.text
|
|
1980
|
-
}
|
|
1981
|
-
});
|
|
1982
|
-
container.append(btn);
|
|
1983
|
-
});
|
|
1984
|
-
return container;
|
|
1985
|
-
}
|
|
1986
|
-
/** Creates the modal backdrop blocker with optional click-to-close behavior. */
|
|
1987
|
-
createBlocker() {
|
|
1988
|
-
const blocker = document.createElement("div");
|
|
1989
|
-
blocker.classList.add("deeplib-modal-blocker");
|
|
1990
|
-
blocker.title = "Click to close";
|
|
1991
|
-
if (this.opts.closeOnBackdrop !== false)
|
|
1992
|
-
blocker.addEventListener("click", () => this.close("close"));
|
|
1993
|
-
return blocker;
|
|
1994
|
-
}
|
|
1995
|
-
/** Implements a focus trap to keep keyboard navigation inside the modal. */
|
|
1996
|
-
setupFocusTrap() {
|
|
1997
|
-
const focusable = 'button, [href], input, textarea, select, [tabindex]:not([tabindex="-1"])';
|
|
1998
|
-
const elements = Array.from(this.dialog.querySelectorAll(focusable));
|
|
1999
|
-
const first = elements[0];
|
|
2000
|
-
const last = elements[elements.length - 1];
|
|
2001
|
-
this.dialog.addEventListener("keydown", (e) => {
|
|
2002
|
-
if (e.key === "Tab") {
|
|
2003
|
-
if (elements.length === 0) {
|
|
2004
|
-
e.preventDefault();
|
|
2005
|
-
return;
|
|
2006
|
-
}
|
|
2007
|
-
if (e.shiftKey) {
|
|
2008
|
-
if (document.activeElement === first) {
|
|
2009
|
-
last.focus();
|
|
2010
|
-
e.preventDefault();
|
|
2011
|
-
}
|
|
2012
|
-
} else {
|
|
2013
|
-
if (document.activeElement === last) {
|
|
2014
|
-
first.focus();
|
|
2015
|
-
e.preventDefault();
|
|
2016
|
-
}
|
|
2017
|
-
}
|
|
2018
|
-
} else if (e.key === "Escape") {
|
|
2019
|
-
e.stopPropagation();
|
|
2020
|
-
this.close(this.opts.escapeAction ?? "close");
|
|
2021
|
-
} else if (e.key === "Enter") {
|
|
2022
|
-
if (elements.some((el) => el === document.activeElement) && document.activeElement !== this.inputEl) return;
|
|
2023
|
-
e.preventDefault();
|
|
2024
|
-
e.stopPropagation();
|
|
2025
|
-
this.close(this.opts.enterAction ?? "submit");
|
|
2026
|
-
}
|
|
2027
|
-
});
|
|
2028
|
-
window.requestAnimationFrame(() => {
|
|
2029
|
-
(this.inputEl || first)?.focus();
|
|
2030
|
-
});
|
|
2031
|
-
}
|
|
2032
|
-
/** Closes the modal, cleans up DOM, resolves promise, and shows next queued modal. */
|
|
2033
|
-
close(action) {
|
|
2034
|
-
if (this.timeoutId) clearTimeout(this.timeoutId);
|
|
2035
|
-
this.dialog.close();
|
|
2036
|
-
this.dialog.remove();
|
|
2037
|
-
this.blocker.remove();
|
|
2038
|
-
document.body.querySelector(".deeplib-modal-blocker")?.remove();
|
|
2039
|
-
const value = this.inputEl?.value ?? "";
|
|
2040
|
-
this.resolve([action, value]);
|
|
2041
|
-
_Modal.dequeue();
|
|
2042
|
-
}
|
|
2043
|
-
/**
|
|
2044
|
-
* An internal function where we will save promise function.
|
|
2045
|
-
*/
|
|
2046
|
-
resolve = /* @__PURE__ */ __name(() => {
|
|
2047
|
-
}, "resolve");
|
|
2048
|
-
/** A function that adds a modal to the queue and returns a promise */
|
|
2049
|
-
static enqueue(modal) {
|
|
2050
|
-
_Modal.queue.push(modal);
|
|
2051
|
-
if (!_Modal.processing) _Modal.dequeue();
|
|
2052
|
-
return new Promise((resolve) => modal.resolve = resolve);
|
|
2053
|
-
}
|
|
2054
|
-
/** A function that processes the queue, removing the first modal */
|
|
2055
|
-
static dequeue() {
|
|
2056
|
-
const modal = _Modal.queue.shift();
|
|
2057
|
-
if (modal) {
|
|
2058
|
-
_Modal.processing = true;
|
|
2059
|
-
modal.dialog.show();
|
|
2060
|
-
} else {
|
|
2061
|
-
_Modal.processing = false;
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
};
|
|
2065
1673
|
|
|
2066
1674
|
// src/screens/main_menu.ts
|
|
2067
1675
|
var MainMenu = class _MainMenu extends BaseSubscreen {
|
|
@@ -2101,7 +1709,7 @@ var MainMenu = class _MainMenu extends BaseSubscreen {
|
|
|
2101
1709
|
ElementMenu.AppendButton(menu, exitButton);
|
|
2102
1710
|
}
|
|
2103
1711
|
for (const screen of this.subscreens) {
|
|
2104
|
-
if (screen.options.name
|
|
1712
|
+
if (screen.options.name === "mainmenu") continue;
|
|
2105
1713
|
const button = advElement.createButton({
|
|
2106
1714
|
id: `${screen.options.name}-button`,
|
|
2107
1715
|
onClick: /* @__PURE__ */ __name(() => {
|
|
@@ -2175,7 +1783,7 @@ var MainMenu = class _MainMenu extends BaseSubscreen {
|
|
|
2175
1783
|
}
|
|
2176
1784
|
if (_MainMenu.options.storageFullnessIndicator) {
|
|
2177
1785
|
const maxStorageCapacityKB = 180;
|
|
2178
|
-
const currentStorageCapacityKB = byteToKB(
|
|
1786
|
+
const currentStorageCapacityKB = byteToKB(modStorage.storageSize());
|
|
2179
1787
|
const fullness = (currentStorageCapacityKB / maxStorageCapacityKB * 100).toFixed(1);
|
|
2180
1788
|
const storageFullnessWrapper = advElement.createButton({
|
|
2181
1789
|
id: CommonGenerateUniqueID(),
|
|
@@ -2257,14 +1865,316 @@ var MainMenu = class _MainMenu extends BaseSubscreen {
|
|
|
2257
1865
|
}
|
|
2258
1866
|
};
|
|
2259
1867
|
|
|
2260
|
-
// src/
|
|
2261
|
-
var
|
|
1868
|
+
// src/utilities/translation.ts
|
|
1869
|
+
var Localization = class _Localization {
|
|
2262
1870
|
static {
|
|
2263
|
-
__name(this, "
|
|
1871
|
+
__name(this, "Localization");
|
|
2264
1872
|
}
|
|
2265
|
-
|
|
2266
|
-
static
|
|
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"
|
|
2268
2178
|
};
|
|
2269
2179
|
constructor(importExportOptions) {
|
|
2270
2180
|
super();
|
|
@@ -2327,7 +2237,13 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2327
2237
|
/** Exports the mod data using the specified method. */
|
|
2328
2238
|
async dataExport(transferMethod) {
|
|
2329
2239
|
try {
|
|
2330
|
-
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);
|
|
2331
2247
|
if (transferMethod === "clipboard") {
|
|
2332
2248
|
await this.exportToClipboard(data);
|
|
2333
2249
|
} else if (transferMethod === "file") {
|
|
@@ -2340,34 +2256,22 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2340
2256
|
ToastManager.success("Data exported successfully.");
|
|
2341
2257
|
} catch (error) {
|
|
2342
2258
|
ToastManager.error("Data export failed.");
|
|
2343
|
-
|
|
2259
|
+
modLogger.error("Data export failed.", error);
|
|
2344
2260
|
}
|
|
2345
2261
|
}
|
|
2346
2262
|
/** Imports mod data using the specified method. */
|
|
2347
2263
|
async dataImport(transferMethod) {
|
|
2348
2264
|
try {
|
|
2349
|
-
|
|
2350
|
-
if (
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
}
|
|
2355
|
-
if (!importedData) {
|
|
2356
|
-
throw new Error("No data imported.");
|
|
2357
|
-
}
|
|
2358
|
-
const data = JSON.parse(LZString.decompressFromBase64(importedData) ?? "");
|
|
2359
|
-
if (!data) {
|
|
2360
|
-
throw new Error("Invalid data.");
|
|
2361
|
-
}
|
|
2362
|
-
for (const module of modules()) {
|
|
2363
|
-
module.registerDefaultSettings(data);
|
|
2364
|
-
}
|
|
2365
|
-
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;
|
|
2366
2270
|
this.importExportOptions.onImport?.();
|
|
2367
2271
|
ToastManager.success("Data imported successfully.");
|
|
2368
2272
|
} catch (error) {
|
|
2369
2273
|
ToastManager.error("Data import failed.");
|
|
2370
|
-
|
|
2274
|
+
modLogger.error("Data import failed.", error);
|
|
2371
2275
|
}
|
|
2372
2276
|
}
|
|
2373
2277
|
/** Saves data to a file using the browser's save dialog. */
|
|
@@ -2393,7 +2297,7 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2393
2297
|
throw new Error("File save cancelled or failed: " + error.message);
|
|
2394
2298
|
}
|
|
2395
2299
|
} else {
|
|
2396
|
-
const fileName = await Modal.prompt("Enter file name", suggestedName);
|
|
2300
|
+
const fileName = await Modal.prompt("Enter file name", { defaultValue: suggestedName });
|
|
2397
2301
|
if (fileName === null) {
|
|
2398
2302
|
return false;
|
|
2399
2303
|
} else if (fileName === "") {
|
|
@@ -2477,6 +2381,72 @@ var GuiImportExport = class extends BaseSubscreen {
|
|
|
2477
2381
|
throw new Error("Failed to read data from clipboard." + error);
|
|
2478
2382
|
});
|
|
2479
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
|
+
}
|
|
2480
2450
|
};
|
|
2481
2451
|
|
|
2482
2452
|
// src/utilities/data.ts
|
|
@@ -2521,7 +2491,7 @@ var ModStorage = class _ModStorage {
|
|
|
2521
2491
|
const parsed = _ModStorage.dataDecompress(this.extensionStorage || "");
|
|
2522
2492
|
if (parsed === null || !Object.hasOwn(parsed, "Version")) {
|
|
2523
2493
|
this.playerStorage = {
|
|
2524
|
-
Version:
|
|
2494
|
+
Version: MOD_VERSION
|
|
2525
2495
|
};
|
|
2526
2496
|
} else {
|
|
2527
2497
|
this.playerStorage = parsed;
|
|
@@ -2536,6 +2506,9 @@ var ModStorage = class _ModStorage {
|
|
|
2536
2506
|
this.extensionStorage = _ModStorage.dataCompress(this.playerStorage);
|
|
2537
2507
|
ServerPlayerExtensionSettingsSync(this.modName);
|
|
2538
2508
|
}
|
|
2509
|
+
storageSize() {
|
|
2510
|
+
return _ModStorage.measureSize(this.extensionStorage);
|
|
2511
|
+
}
|
|
2539
2512
|
static dataDecompress(string) {
|
|
2540
2513
|
const d = LZString.decompressFromBase64(string);
|
|
2541
2514
|
let data = null;
|
|
@@ -2543,7 +2516,7 @@ var ModStorage = class _ModStorage {
|
|
|
2543
2516
|
const decoded = JSON.parse(d);
|
|
2544
2517
|
data = decoded;
|
|
2545
2518
|
} catch (error) {
|
|
2546
|
-
|
|
2519
|
+
modLogger.error(error);
|
|
2547
2520
|
}
|
|
2548
2521
|
return data;
|
|
2549
2522
|
}
|
|
@@ -2600,15 +2573,18 @@ var domUtil = {
|
|
|
2600
2573
|
function autoSetPosition(_, position) {
|
|
2601
2574
|
let xPos = void 0;
|
|
2602
2575
|
let yPos = void 0;
|
|
2576
|
+
let anchor = void 0;
|
|
2603
2577
|
if (Array.isArray(position)) {
|
|
2604
2578
|
xPos = position[0];
|
|
2605
2579
|
yPos = position[1];
|
|
2580
|
+
anchor = position[2];
|
|
2606
2581
|
} else if (typeof position === "function") {
|
|
2607
2582
|
const result = position();
|
|
2608
2583
|
xPos = result[0];
|
|
2609
2584
|
yPos = result[1];
|
|
2585
|
+
anchor = result[2];
|
|
2610
2586
|
}
|
|
2611
|
-
if (xPos !== void 0 && yPos !== void 0) ElementSetPosition(_, xPos, yPos);
|
|
2587
|
+
if (xPos !== void 0 && yPos !== void 0) ElementSetPosition(_, xPos, yPos, anchor);
|
|
2612
2588
|
}
|
|
2613
2589
|
__name(autoSetPosition, "autoSetPosition");
|
|
2614
2590
|
function autoSetSize(_, size) {
|
|
@@ -2843,9 +2819,6 @@ function sendActionMessage(msg, target = void 0, dictionary = []) {
|
|
|
2843
2819
|
__name(sendActionMessage, "sendActionMessage");
|
|
2844
2820
|
|
|
2845
2821
|
// src/utilities/sdk.ts
|
|
2846
|
-
var import_bondage_club_mod_sdk = __toESM(require_bcmodsdk(), 1);
|
|
2847
|
-
var rawSdk = import_bondage_club_mod_sdk.default;
|
|
2848
|
-
var bcModSdkRef = rawSdk.default ?? rawSdk;
|
|
2849
2822
|
var HookPriority = {
|
|
2850
2823
|
Observe: 0,
|
|
2851
2824
|
AddBehavior: 1,
|
|
@@ -2853,27 +2826,25 @@ var HookPriority = {
|
|
|
2853
2826
|
OverrideBehavior: 10,
|
|
2854
2827
|
Top: 100
|
|
2855
2828
|
};
|
|
2856
|
-
var ModSdkManager = class
|
|
2829
|
+
var ModSdkManager = class {
|
|
2857
2830
|
static {
|
|
2858
2831
|
__name(this, "ModSdkManager");
|
|
2859
2832
|
}
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
static ModInfo;
|
|
2833
|
+
SDK;
|
|
2834
|
+
patchedFunctions = /* @__PURE__ */ new Map();
|
|
2863
2835
|
/** Registers a mod with the SDK and stores mod information. */
|
|
2864
2836
|
constructor(info, options) {
|
|
2865
|
-
|
|
2866
|
-
_ModSdkManager.ModInfo = info;
|
|
2837
|
+
this.SDK = bcModSdk.registerMod(info, options);
|
|
2867
2838
|
}
|
|
2868
2839
|
/** Retrieves or initializes patch data for a given target function. */
|
|
2869
2840
|
initPatchableFunction(target) {
|
|
2870
|
-
let result =
|
|
2841
|
+
let result = this.patchedFunctions.get(target);
|
|
2871
2842
|
if (!result) {
|
|
2872
2843
|
result = {
|
|
2873
2844
|
name: target,
|
|
2874
2845
|
hooks: []
|
|
2875
2846
|
};
|
|
2876
|
-
|
|
2847
|
+
this.patchedFunctions.set(target, result);
|
|
2877
2848
|
}
|
|
2878
2849
|
return result;
|
|
2879
2850
|
}
|
|
@@ -2887,7 +2858,7 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2887
2858
|
if (data.hooks.some((h) => h.hook === hook)) {
|
|
2888
2859
|
return () => null;
|
|
2889
2860
|
}
|
|
2890
|
-
const removeCallback =
|
|
2861
|
+
const removeCallback = this.SDK.hookFunction(target, priority, hook);
|
|
2891
2862
|
data.hooks.push({
|
|
2892
2863
|
hook,
|
|
2893
2864
|
priority,
|
|
@@ -2903,13 +2874,13 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2903
2874
|
* **This method is DANGEROUS** to use and has high potential to conflict with other mods.
|
|
2904
2875
|
*/
|
|
2905
2876
|
patchFunction(target, patches) {
|
|
2906
|
-
|
|
2877
|
+
this.SDK.patchFunction(target, patches);
|
|
2907
2878
|
}
|
|
2908
2879
|
/**
|
|
2909
2880
|
* Removes all patches from a target function.
|
|
2910
2881
|
*/
|
|
2911
2882
|
unpatchFunction(target) {
|
|
2912
|
-
|
|
2883
|
+
this.SDK.removePatches(target);
|
|
2913
2884
|
}
|
|
2914
2885
|
/**
|
|
2915
2886
|
* Removes all hooks associated with a specific module from a target function.
|
|
@@ -2928,7 +2899,7 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2928
2899
|
* Removes all hooks associated with a specific module across all patched functions.
|
|
2929
2900
|
*/
|
|
2930
2901
|
removeAllHooksByModule(module) {
|
|
2931
|
-
for (const data of
|
|
2902
|
+
for (const data of this.patchedFunctions.values()) {
|
|
2932
2903
|
for (let i = data.hooks.length - 1; i >= 0; i--) {
|
|
2933
2904
|
if (data.hooks[i].module === module) {
|
|
2934
2905
|
data.hooks[i].removeCallback();
|
|
@@ -2938,6 +2909,12 @@ var ModSdkManager = class _ModSdkManager {
|
|
|
2938
2909
|
}
|
|
2939
2910
|
return true;
|
|
2940
2911
|
}
|
|
2912
|
+
/**
|
|
2913
|
+
* Unloads the mod removing all hooks and patches by it.
|
|
2914
|
+
*/
|
|
2915
|
+
unload() {
|
|
2916
|
+
this.SDK.unload();
|
|
2917
|
+
}
|
|
2941
2918
|
};
|
|
2942
2919
|
|
|
2943
2920
|
// src/utilities/style.ts
|
|
@@ -2990,87 +2967,6 @@ var Style = {
|
|
|
2990
2967
|
}
|
|
2991
2968
|
};
|
|
2992
2969
|
|
|
2993
|
-
// src/utilities/translation.ts
|
|
2994
|
-
var Localization = class _Localization {
|
|
2995
|
-
static {
|
|
2996
|
-
__name(this, "Localization");
|
|
2997
|
-
}
|
|
2998
|
-
static LibTranslation = {};
|
|
2999
|
-
static ModTranslation = {};
|
|
3000
|
-
static PathToModTranslation;
|
|
3001
|
-
static PathToLibTranslation = `${PUBLIC_URL}/dl_translations/`;
|
|
3002
|
-
static DefaultLanguage = "en";
|
|
3003
|
-
/** Flag to prevent re-initialization */
|
|
3004
|
-
static initialized = false;
|
|
3005
|
-
/** Initialize the localization system by loading translation files. */
|
|
3006
|
-
static async init(initOptions) {
|
|
3007
|
-
if (_Localization.initialized) return;
|
|
3008
|
-
_Localization.initialized = true;
|
|
3009
|
-
_Localization.PathToModTranslation = (() => {
|
|
3010
|
-
if (!initOptions?.pathToTranslationsFolder) return void 0;
|
|
3011
|
-
return initOptions.pathToTranslationsFolder.endsWith("/") ? initOptions.pathToTranslationsFolder : `${initOptions.pathToTranslationsFolder}/`;
|
|
3012
|
-
})();
|
|
3013
|
-
_Localization.DefaultLanguage = initOptions?.defaultLanguage || _Localization.DefaultLanguage;
|
|
3014
|
-
const lang = initOptions?.fixedLanguage ? _Localization.DefaultLanguage : TranslationLanguage.toLowerCase();
|
|
3015
|
-
const libTranslation = await _Localization.fetchLanguageFile(_Localization.PathToLibTranslation, lang);
|
|
3016
|
-
if (lang === _Localization.DefaultLanguage) {
|
|
3017
|
-
_Localization.LibTranslation = libTranslation;
|
|
3018
|
-
} else {
|
|
3019
|
-
const fallbackTranslation = await _Localization.fetchLanguageFile(_Localization.PathToLibTranslation, _Localization.DefaultLanguage);
|
|
3020
|
-
_Localization.LibTranslation = { ...fallbackTranslation, ...libTranslation };
|
|
3021
|
-
}
|
|
3022
|
-
if (!_Localization.PathToModTranslation) return;
|
|
3023
|
-
const modTranslation = await _Localization.fetchLanguageFile(_Localization.PathToModTranslation, lang);
|
|
3024
|
-
if (lang === _Localization.DefaultLanguage) {
|
|
3025
|
-
_Localization.ModTranslation = modTranslation;
|
|
3026
|
-
} else {
|
|
3027
|
-
const fallbackTranslation = await _Localization.fetchLanguageFile(_Localization.PathToModTranslation, _Localization.DefaultLanguage);
|
|
3028
|
-
_Localization.ModTranslation = { ...fallbackTranslation, ...modTranslation };
|
|
3029
|
-
}
|
|
3030
|
-
}
|
|
3031
|
-
/** Get a translated string from mod translations by source tag. */
|
|
3032
|
-
static getTextMod(srcTag) {
|
|
3033
|
-
return _Localization.ModTranslation?.[srcTag] || void 0;
|
|
3034
|
-
}
|
|
3035
|
-
/** Get a translated string from library translations by source tag. */
|
|
3036
|
-
static getTextLib(srcTag) {
|
|
3037
|
-
return _Localization.LibTranslation?.[srcTag] || void 0;
|
|
3038
|
-
}
|
|
3039
|
-
/**
|
|
3040
|
-
* Fetch and parse a language file from the given base URL and language code.
|
|
3041
|
-
* Falls back to default language if the requested language file is unavailable.
|
|
3042
|
-
*/
|
|
3043
|
-
static async fetchLanguageFile(baseUrl, lang) {
|
|
3044
|
-
const response = await fetch(`${baseUrl}${lang}.lang`);
|
|
3045
|
-
if (lang !== _Localization.DefaultLanguage && !response.ok) {
|
|
3046
|
-
return this.fetchLanguageFile(baseUrl, _Localization.DefaultLanguage);
|
|
3047
|
-
}
|
|
3048
|
-
if (!response.ok) {
|
|
3049
|
-
return {};
|
|
3050
|
-
}
|
|
3051
|
-
const langFileContent = await response.text();
|
|
3052
|
-
return this.parseLanguageFile(langFileContent);
|
|
3053
|
-
}
|
|
3054
|
-
/**
|
|
3055
|
-
* Parse the raw content of a language file into a TranslationDict.
|
|
3056
|
-
* Ignores empty lines and comments starting with '#'.
|
|
3057
|
-
*/
|
|
3058
|
-
static parseLanguageFile(content) {
|
|
3059
|
-
const translations = {};
|
|
3060
|
-
const lines = content.split("\n");
|
|
3061
|
-
for (const line of lines) {
|
|
3062
|
-
const trimmed = line.trim();
|
|
3063
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
3064
|
-
const [key, ...rest] = trimmed.split("=");
|
|
3065
|
-
translations[key.trim()] = rest.join("=").trim();
|
|
3066
|
-
}
|
|
3067
|
-
return translations;
|
|
3068
|
-
}
|
|
3069
|
-
};
|
|
3070
|
-
var getText = /* @__PURE__ */ __name((srcTag) => {
|
|
3071
|
-
return Localization.getTextMod(srcTag) || Localization.getTextLib(srcTag) || srcTag;
|
|
3072
|
-
}, "getText");
|
|
3073
|
-
|
|
3074
2970
|
// src/utilities/event_channel.ts
|
|
3075
2971
|
var EventChannel = class {
|
|
3076
2972
|
constructor(channelName) {
|
|
@@ -3141,6 +3037,7 @@ export {
|
|
|
3141
3037
|
HookPriority,
|
|
3142
3038
|
Localization,
|
|
3143
3039
|
Logger,
|
|
3040
|
+
MOD_NAME,
|
|
3144
3041
|
MainMenu,
|
|
3145
3042
|
ModSdkManager,
|
|
3146
3043
|
ModStorage,
|
|
@@ -3155,14 +3052,13 @@ export {
|
|
|
3155
3052
|
exportToGlobal,
|
|
3156
3053
|
getModule,
|
|
3157
3054
|
getText,
|
|
3158
|
-
|
|
3159
|
-
|
|
3055
|
+
hasGetter,
|
|
3056
|
+
hasSetter,
|
|
3160
3057
|
initMod,
|
|
3161
3058
|
layout,
|
|
3162
|
-
|
|
3059
|
+
modLogger,
|
|
3163
3060
|
modStorage,
|
|
3164
3061
|
modules,
|
|
3165
|
-
modulesMap,
|
|
3166
3062
|
registerModule,
|
|
3167
3063
|
sdk,
|
|
3168
3064
|
sendActionMessage,
|