@oasiz/sdk 1.6.0 → 1.6.1
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/README.md +464 -85
- package/dist/index.cjs +1940 -228
- package/dist/index.d.cts +248 -102
- package/dist/index.d.ts +248 -102
- package/dist/index.js +1929 -217
- package/package.json +14 -4
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/character.ts
|
|
2
2
|
function isDevelopment() {
|
|
3
3
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
4
4
|
return nodeEnv !== "production";
|
|
@@ -9,72 +9,1014 @@ function getBridgeWindow() {
|
|
|
9
9
|
}
|
|
10
10
|
return window;
|
|
11
11
|
}
|
|
12
|
-
function
|
|
12
|
+
function warnMissingBridge(methodName) {
|
|
13
|
+
if (isDevelopment()) {
|
|
14
|
+
console.warn(
|
|
15
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function getPlayerCharacter() {
|
|
13
20
|
const bridge = getBridgeWindow();
|
|
21
|
+
if (typeof bridge?.__oasizGetPlayerCharacter !== "function") {
|
|
22
|
+
warnMissingBridge("getPlayerCharacter");
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const result = await bridge.__oasizGetPlayerCharacter();
|
|
27
|
+
return result ?? null;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (isDevelopment()) {
|
|
30
|
+
console.error("[oasiz/sdk] getPlayerCharacter failed:", error);
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/haptics.ts
|
|
37
|
+
function isDevelopment2() {
|
|
38
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
39
|
+
return nodeEnv !== "production";
|
|
40
|
+
}
|
|
41
|
+
function getBridgeWindow2() {
|
|
42
|
+
if (typeof window === "undefined") {
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
return window;
|
|
46
|
+
}
|
|
47
|
+
function triggerHaptic(type) {
|
|
48
|
+
const bridge = getBridgeWindow2();
|
|
14
49
|
if (typeof bridge?.triggerHaptic === "function") {
|
|
15
50
|
bridge.triggerHaptic(type);
|
|
16
51
|
return;
|
|
17
52
|
}
|
|
18
|
-
if (
|
|
53
|
+
if (isDevelopment2()) {
|
|
19
54
|
console.warn(
|
|
20
55
|
"[oasiz/sdk] triggerHaptic bridge is unavailable. This is expected in local development."
|
|
21
56
|
);
|
|
22
57
|
}
|
|
23
58
|
}
|
|
24
59
|
|
|
60
|
+
// src/log-overlay.ts
|
|
61
|
+
var CONSOLE_METHODS = [
|
|
62
|
+
"debug",
|
|
63
|
+
"log",
|
|
64
|
+
"info",
|
|
65
|
+
"warn",
|
|
66
|
+
"error"
|
|
67
|
+
];
|
|
68
|
+
var DEFAULT_MAX_ENTRIES = 200;
|
|
69
|
+
var DEFAULT_TITLE = "SDK Logs";
|
|
70
|
+
var OVERLAY_MARGIN = 12;
|
|
71
|
+
var DEFAULT_COLLAPSED_WIDTH = 156;
|
|
72
|
+
var DEFAULT_COLLAPSED_HEIGHT = 52;
|
|
73
|
+
var DEFAULT_EXPANDED_WIDTH = 565;
|
|
74
|
+
var DEFAULT_EXPANDED_HEIGHT = 372;
|
|
75
|
+
var DRAG_THRESHOLD_PX = 6;
|
|
76
|
+
var MIN_EXPANDED_WIDTH = 160;
|
|
77
|
+
var MIN_EXPANDED_HEIGHT = 110;
|
|
78
|
+
var RESIZE_HOTSPOT_PX = 28;
|
|
79
|
+
var TOP_DRAG_ZONE_PX = 44;
|
|
80
|
+
var NOOP_HANDLE = {
|
|
81
|
+
clear() {
|
|
82
|
+
},
|
|
83
|
+
destroy() {
|
|
84
|
+
},
|
|
85
|
+
hide() {
|
|
86
|
+
},
|
|
87
|
+
isVisible() {
|
|
88
|
+
return false;
|
|
89
|
+
},
|
|
90
|
+
show() {
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
function getBrowserWindow() {
|
|
94
|
+
if (typeof window === "undefined") {
|
|
95
|
+
return void 0;
|
|
96
|
+
}
|
|
97
|
+
return window;
|
|
98
|
+
}
|
|
99
|
+
function getDocument() {
|
|
100
|
+
if (typeof document === "undefined") {
|
|
101
|
+
return void 0;
|
|
102
|
+
}
|
|
103
|
+
return document;
|
|
104
|
+
}
|
|
105
|
+
function clampMaxEntries(value) {
|
|
106
|
+
if (!Number.isFinite(value)) {
|
|
107
|
+
return DEFAULT_MAX_ENTRIES;
|
|
108
|
+
}
|
|
109
|
+
return Math.max(10, Math.floor(value));
|
|
110
|
+
}
|
|
111
|
+
function createConsoleSnapshot() {
|
|
112
|
+
const fallback = console.log.bind(console);
|
|
113
|
+
return {
|
|
114
|
+
debug: typeof console.debug === "function" ? console.debug.bind(console) : fallback,
|
|
115
|
+
log: fallback,
|
|
116
|
+
info: typeof console.info === "function" ? console.info.bind(console) : fallback,
|
|
117
|
+
warn: typeof console.warn === "function" ? console.warn.bind(console) : fallback,
|
|
118
|
+
error: typeof console.error === "function" ? console.error.bind(console) : fallback
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function formatTimestamp(timestamp) {
|
|
122
|
+
const date = new Date(timestamp);
|
|
123
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
124
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
125
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
126
|
+
const milliseconds = String(date.getMilliseconds()).padStart(3, "0");
|
|
127
|
+
return "[" + hours + ":" + minutes + ":" + seconds + "." + milliseconds + "]";
|
|
128
|
+
}
|
|
129
|
+
function safeStringify(value) {
|
|
130
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
131
|
+
try {
|
|
132
|
+
return JSON.stringify(
|
|
133
|
+
value,
|
|
134
|
+
(_key, candidate) => {
|
|
135
|
+
if (typeof candidate === "bigint") {
|
|
136
|
+
return candidate.toString() + "n";
|
|
137
|
+
}
|
|
138
|
+
if (typeof candidate === "object" && candidate !== null) {
|
|
139
|
+
if (seen.has(candidate)) {
|
|
140
|
+
return "[Circular]";
|
|
141
|
+
}
|
|
142
|
+
seen.add(candidate);
|
|
143
|
+
}
|
|
144
|
+
return candidate;
|
|
145
|
+
},
|
|
146
|
+
2
|
|
147
|
+
) ?? String(value);
|
|
148
|
+
} catch {
|
|
149
|
+
return String(value);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function formatArg(value) {
|
|
153
|
+
if (typeof value === "string") {
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
if (value instanceof Error) {
|
|
157
|
+
if (value.stack) {
|
|
158
|
+
return value.stack;
|
|
159
|
+
}
|
|
160
|
+
return value.name + ": " + value.message;
|
|
161
|
+
}
|
|
162
|
+
if (typeof value === "undefined") {
|
|
163
|
+
return "undefined";
|
|
164
|
+
}
|
|
165
|
+
if (typeof value === "function") {
|
|
166
|
+
return "[Function " + (value.name || "anonymous") + "]";
|
|
167
|
+
}
|
|
168
|
+
return safeStringify(value);
|
|
169
|
+
}
|
|
170
|
+
function formatEntryMessage(args) {
|
|
171
|
+
const message = args.map(formatArg).join(" ");
|
|
172
|
+
if (message.length <= 4e3) {
|
|
173
|
+
return message;
|
|
174
|
+
}
|
|
175
|
+
return message.slice(0, 3997) + "...";
|
|
176
|
+
}
|
|
177
|
+
function createEntry(level, args, id) {
|
|
178
|
+
return {
|
|
179
|
+
id,
|
|
180
|
+
level,
|
|
181
|
+
message: formatEntryMessage(args),
|
|
182
|
+
timestamp: Date.now()
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function createButton(label) {
|
|
186
|
+
const button = document.createElement("button");
|
|
187
|
+
button.type = "button";
|
|
188
|
+
button.textContent = label;
|
|
189
|
+
button.style.cssText = [
|
|
190
|
+
"appearance:none",
|
|
191
|
+
"border:1px solid rgba(255,255,255,0.18)",
|
|
192
|
+
"background:rgba(255,255,255,0.06)",
|
|
193
|
+
"color:#f8fafc",
|
|
194
|
+
"border-radius:999px",
|
|
195
|
+
"padding:6px 10px",
|
|
196
|
+
"font:600 12px/1.1 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
|
|
197
|
+
"cursor:pointer"
|
|
198
|
+
].join(";");
|
|
199
|
+
return button;
|
|
200
|
+
}
|
|
201
|
+
function getLevelAccent(level) {
|
|
202
|
+
if (level === "error") {
|
|
203
|
+
return {
|
|
204
|
+
lineBackground: "rgba(255, 109, 122, 0.08)"
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (level === "warn") {
|
|
208
|
+
return {
|
|
209
|
+
lineBackground: "rgba(255, 196, 94, 0.07)"
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
if (level === "info") {
|
|
213
|
+
return {
|
|
214
|
+
lineBackground: "rgba(82, 187, 255, 0.07)"
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
if (level === "debug") {
|
|
218
|
+
return {
|
|
219
|
+
lineBackground: "rgba(166, 137, 255, 0.07)"
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
lineBackground: "rgba(117, 235, 191, 0.06)"
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function getViewportSize() {
|
|
227
|
+
const browserWindow = getBrowserWindow();
|
|
228
|
+
return {
|
|
229
|
+
width: Math.max(320, browserWindow?.innerWidth ?? 1280),
|
|
230
|
+
height: Math.max(240, browserWindow?.innerHeight ?? 720)
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function clampPanelSize(size) {
|
|
234
|
+
const viewport = getViewportSize();
|
|
235
|
+
const maxWidth = Math.max(MIN_EXPANDED_WIDTH, viewport.width - OVERLAY_MARGIN * 2);
|
|
236
|
+
const maxHeight = Math.max(
|
|
237
|
+
MIN_EXPANDED_HEIGHT,
|
|
238
|
+
viewport.height - OVERLAY_MARGIN * 2
|
|
239
|
+
);
|
|
240
|
+
return {
|
|
241
|
+
width: Math.min(maxWidth, Math.max(MIN_EXPANDED_WIDTH, size.width)),
|
|
242
|
+
height: Math.min(maxHeight, Math.max(MIN_EXPANDED_HEIGHT, size.height))
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function getOverlaySize(state) {
|
|
246
|
+
if (state.expanded && state.panelSize) {
|
|
247
|
+
return state.panelSize;
|
|
248
|
+
}
|
|
249
|
+
const rect = state.ui?.root && typeof state.ui.root.getBoundingClientRect === "function" ? state.ui.root.getBoundingClientRect() : null;
|
|
250
|
+
if (rect && Number.isFinite(rect.width) && Number.isFinite(rect.height)) {
|
|
251
|
+
return {
|
|
252
|
+
width: Math.max(1, rect.width),
|
|
253
|
+
height: Math.max(1, rect.height)
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
return state.expanded ? clampPanelSize({
|
|
257
|
+
width: DEFAULT_EXPANDED_WIDTH,
|
|
258
|
+
height: DEFAULT_EXPANDED_HEIGHT
|
|
259
|
+
}) : { width: DEFAULT_COLLAPSED_WIDTH, height: DEFAULT_COLLAPSED_HEIGHT };
|
|
260
|
+
}
|
|
261
|
+
function applyPanelSize(state) {
|
|
262
|
+
if (!state.ui) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (!state.expanded) {
|
|
266
|
+
state.ui.root.style.width = "auto";
|
|
267
|
+
state.ui.panel.style.width = "min(565px, calc(100vw - 24px))";
|
|
268
|
+
state.ui.panel.style.height = "auto";
|
|
269
|
+
state.ui.entries.style.maxHeight = "min(36vh, 280px)";
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (!state.panelSize) {
|
|
273
|
+
state.ui.root.style.width = "min(565px, calc(100vw - 24px))";
|
|
274
|
+
state.ui.panel.style.width = "min(565px, calc(100vw - 24px))";
|
|
275
|
+
state.ui.panel.style.height = "auto";
|
|
276
|
+
state.ui.entries.style.maxHeight = "min(36vh, 280px)";
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
const nextSize = clampPanelSize(
|
|
280
|
+
state.panelSize
|
|
281
|
+
);
|
|
282
|
+
state.panelSize = nextSize;
|
|
283
|
+
state.ui.root.style.width = nextSize.width + "px";
|
|
284
|
+
state.ui.panel.style.width = "100%";
|
|
285
|
+
state.ui.panel.style.height = nextSize.height + "px";
|
|
286
|
+
state.ui.entries.style.maxHeight = Math.max(72, nextSize.height - 88) + "px";
|
|
287
|
+
}
|
|
288
|
+
function clampPosition(point, state) {
|
|
289
|
+
const viewport = getViewportSize();
|
|
290
|
+
const size = getOverlaySize(state);
|
|
291
|
+
const maxX = Math.max(OVERLAY_MARGIN, viewport.width - size.width - OVERLAY_MARGIN);
|
|
292
|
+
const maxY = Math.max(
|
|
293
|
+
OVERLAY_MARGIN,
|
|
294
|
+
viewport.height - size.height - OVERLAY_MARGIN
|
|
295
|
+
);
|
|
296
|
+
return {
|
|
297
|
+
x: Math.min(maxX, Math.max(OVERLAY_MARGIN, point.x)),
|
|
298
|
+
y: Math.min(maxY, Math.max(OVERLAY_MARGIN, point.y))
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
function applyOverlayPosition(state) {
|
|
302
|
+
if (!state.ui) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (!state.position) {
|
|
306
|
+
const viewport = getViewportSize();
|
|
307
|
+
const size = getOverlaySize(state);
|
|
308
|
+
state.position = clampPosition(
|
|
309
|
+
{
|
|
310
|
+
x: viewport.width - size.width - OVERLAY_MARGIN,
|
|
311
|
+
y: viewport.height - size.height - OVERLAY_MARGIN
|
|
312
|
+
},
|
|
313
|
+
state
|
|
314
|
+
);
|
|
315
|
+
} else {
|
|
316
|
+
state.position = clampPosition(state.position, state);
|
|
317
|
+
}
|
|
318
|
+
state.ui.root.style.left = state.position.x + "px";
|
|
319
|
+
state.ui.root.style.top = state.position.y + "px";
|
|
320
|
+
}
|
|
321
|
+
function getPointFromMouseEvent(event) {
|
|
322
|
+
return { x: event.clientX, y: event.clientY };
|
|
323
|
+
}
|
|
324
|
+
function getPointFromTouchEvent(event) {
|
|
325
|
+
const touch = event.touches[0] ?? event.changedTouches[0];
|
|
326
|
+
if (!touch) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
return { x: touch.clientX, y: touch.clientY };
|
|
330
|
+
}
|
|
331
|
+
function stopDragging(state) {
|
|
332
|
+
if (state.isDragging || state.isResizing) {
|
|
333
|
+
state.suppressToggleClickUntil = Date.now() + 180;
|
|
334
|
+
}
|
|
335
|
+
state.isDragging = false;
|
|
336
|
+
state.dragStartPoint = null;
|
|
337
|
+
state.lastDragPoint = null;
|
|
338
|
+
state.removeDragListeners?.();
|
|
339
|
+
state.removeDragListeners = null;
|
|
340
|
+
if (state.ui) {
|
|
341
|
+
state.ui.panel.style.cursor = "default";
|
|
342
|
+
state.ui.dragZone.style.cursor = "grab";
|
|
343
|
+
state.ui.toggleButton.style.cursor = "grab";
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function stopResizing(state) {
|
|
347
|
+
if (state.isResizing) {
|
|
348
|
+
state.suppressToggleClickUntil = Date.now() + 180;
|
|
349
|
+
}
|
|
350
|
+
state.isResizing = false;
|
|
351
|
+
state.resizeStartPoint = null;
|
|
352
|
+
state.resizeStartSize = null;
|
|
353
|
+
state.removeResizeListeners?.();
|
|
354
|
+
state.removeResizeListeners = null;
|
|
355
|
+
}
|
|
356
|
+
function beginDragTracking(state, startPoint) {
|
|
357
|
+
const doc = getDocument();
|
|
358
|
+
if (!doc) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
stopResizing(state);
|
|
362
|
+
stopDragging(state);
|
|
363
|
+
state.dragMoved = false;
|
|
364
|
+
state.dragStartPoint = startPoint;
|
|
365
|
+
state.lastDragPoint = startPoint;
|
|
366
|
+
const handlePointerMove = (nextPoint) => {
|
|
367
|
+
if (!state.dragStartPoint || !state.lastDragPoint || !nextPoint) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (!state.isDragging) {
|
|
371
|
+
const deltaFromStartX = nextPoint.x - state.dragStartPoint.x;
|
|
372
|
+
const deltaFromStartY = nextPoint.y - state.dragStartPoint.y;
|
|
373
|
+
const distance = Math.sqrt(
|
|
374
|
+
deltaFromStartX * deltaFromStartX + deltaFromStartY * deltaFromStartY
|
|
375
|
+
);
|
|
376
|
+
if (distance < DRAG_THRESHOLD_PX) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
state.isDragging = true;
|
|
380
|
+
state.dragMoved = true;
|
|
381
|
+
if (state.ui) {
|
|
382
|
+
state.ui.panel.style.cursor = "grabbing";
|
|
383
|
+
state.ui.dragZone.style.cursor = "grabbing";
|
|
384
|
+
state.ui.toggleButton.style.cursor = "grabbing";
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const currentPosition = state.position ?? { x: OVERLAY_MARGIN, y: OVERLAY_MARGIN };
|
|
388
|
+
state.position = clampPosition(
|
|
389
|
+
{
|
|
390
|
+
x: currentPosition.x + (nextPoint.x - state.lastDragPoint.x),
|
|
391
|
+
y: currentPosition.y + (nextPoint.y - state.lastDragPoint.y)
|
|
392
|
+
},
|
|
393
|
+
state
|
|
394
|
+
);
|
|
395
|
+
state.lastDragPoint = nextPoint;
|
|
396
|
+
applyOverlayPosition(state);
|
|
397
|
+
};
|
|
398
|
+
const handleMouseMove = (event) => {
|
|
399
|
+
handlePointerMove(getPointFromMouseEvent(event));
|
|
400
|
+
};
|
|
401
|
+
const handleTouchMove = (event) => {
|
|
402
|
+
handlePointerMove(getPointFromTouchEvent(event));
|
|
403
|
+
};
|
|
404
|
+
const handleMouseUp = () => {
|
|
405
|
+
stopDragging(state);
|
|
406
|
+
};
|
|
407
|
+
const handleTouchEnd = () => {
|
|
408
|
+
stopDragging(state);
|
|
409
|
+
};
|
|
410
|
+
doc.addEventListener("mousemove", handleMouseMove);
|
|
411
|
+
doc.addEventListener("mouseup", handleMouseUp);
|
|
412
|
+
doc.addEventListener("touchmove", handleTouchMove, { passive: true });
|
|
413
|
+
doc.addEventListener("touchend", handleTouchEnd);
|
|
414
|
+
doc.addEventListener("touchcancel", handleTouchEnd);
|
|
415
|
+
state.removeDragListeners = () => {
|
|
416
|
+
doc.removeEventListener("mousemove", handleMouseMove);
|
|
417
|
+
doc.removeEventListener("mouseup", handleMouseUp);
|
|
418
|
+
doc.removeEventListener("touchmove", handleTouchMove);
|
|
419
|
+
doc.removeEventListener("touchend", handleTouchEnd);
|
|
420
|
+
doc.removeEventListener("touchcancel", handleTouchEnd);
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function startResizing(state, startPoint) {
|
|
424
|
+
const doc = getDocument();
|
|
425
|
+
if (!doc) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
stopDragging(state);
|
|
429
|
+
stopResizing(state);
|
|
430
|
+
state.isResizing = true;
|
|
431
|
+
state.resizeStartPoint = startPoint;
|
|
432
|
+
state.resizeStartSize = state.panelSize ?? clampPanelSize({ width: DEFAULT_EXPANDED_WIDTH, height: DEFAULT_EXPANDED_HEIGHT });
|
|
433
|
+
const handleResizeMove = (nextPoint) => {
|
|
434
|
+
if (!state.isResizing || !state.resizeStartPoint || !state.resizeStartSize || !nextPoint) {
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
state.panelSize = clampPanelSize({
|
|
438
|
+
width: state.resizeStartSize.width + (nextPoint.x - state.resizeStartPoint.x),
|
|
439
|
+
height: state.resizeStartSize.height + (nextPoint.y - state.resizeStartPoint.y)
|
|
440
|
+
});
|
|
441
|
+
applyPanelSize(state);
|
|
442
|
+
applyOverlayPosition(state);
|
|
443
|
+
};
|
|
444
|
+
const handleMouseMove = (event) => {
|
|
445
|
+
handleResizeMove(getPointFromMouseEvent(event));
|
|
446
|
+
};
|
|
447
|
+
const handleTouchMove = (event) => {
|
|
448
|
+
handleResizeMove(getPointFromTouchEvent(event));
|
|
449
|
+
};
|
|
450
|
+
const handleFinish = () => {
|
|
451
|
+
stopResizing(state);
|
|
452
|
+
};
|
|
453
|
+
doc.addEventListener("mousemove", handleMouseMove);
|
|
454
|
+
doc.addEventListener("mouseup", handleFinish);
|
|
455
|
+
doc.addEventListener("touchmove", handleTouchMove, { passive: true });
|
|
456
|
+
doc.addEventListener("touchend", handleFinish);
|
|
457
|
+
doc.addEventListener("touchcancel", handleFinish);
|
|
458
|
+
state.removeResizeListeners = () => {
|
|
459
|
+
doc.removeEventListener("mousemove", handleMouseMove);
|
|
460
|
+
doc.removeEventListener("mouseup", handleFinish);
|
|
461
|
+
doc.removeEventListener("touchmove", handleTouchMove);
|
|
462
|
+
doc.removeEventListener("touchend", handleFinish);
|
|
463
|
+
doc.removeEventListener("touchcancel", handleFinish);
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
function isInBottomRightResizeZone(element, point) {
|
|
467
|
+
const rect = element.getBoundingClientRect();
|
|
468
|
+
return point.x >= rect.right - RESIZE_HOTSPOT_PX && point.x <= rect.right && point.y >= rect.bottom - RESIZE_HOTSPOT_PX && point.y <= rect.bottom;
|
|
469
|
+
}
|
|
470
|
+
function canStartDragFromTarget(target) {
|
|
471
|
+
if (!(target instanceof Element)) {
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
if (target.closest("button") || target.closest("a") || target.closest("input") || target.closest("textarea") || target.closest("select")) {
|
|
475
|
+
return false;
|
|
476
|
+
}
|
|
477
|
+
return true;
|
|
478
|
+
}
|
|
479
|
+
function isInTopDragZone(element, point, zoneHeight) {
|
|
480
|
+
const rect = element.getBoundingClientRect();
|
|
481
|
+
return point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.top + zoneHeight;
|
|
482
|
+
}
|
|
483
|
+
function attachDragStartListeners(element, state, options = {}) {
|
|
484
|
+
element.addEventListener("mousedown", (event) => {
|
|
485
|
+
if (!options.allowInteractiveTarget && !canStartDragFromTarget(event.target)) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
const point = getPointFromMouseEvent(event);
|
|
489
|
+
if (typeof options.topZoneHeight === "number" && !isInTopDragZone(element, point, options.topZoneHeight)) {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
beginDragTracking(state, point);
|
|
493
|
+
});
|
|
494
|
+
element.addEventListener("touchstart", (event) => {
|
|
495
|
+
if (!options.allowInteractiveTarget && !canStartDragFromTarget(event.target)) {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const point = getPointFromTouchEvent(event);
|
|
499
|
+
if (!point) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
if (typeof options.topZoneHeight === "number" && !isInTopDragZone(element, point, options.topZoneHeight)) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
beginDragTracking(state, point);
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
function attachCollapsedToggleListeners(element, state) {
|
|
509
|
+
const startToggleInteraction = (startPoint) => {
|
|
510
|
+
const doc = getDocument();
|
|
511
|
+
if (!doc) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
beginDragTracking(state, startPoint);
|
|
515
|
+
const finishInteraction = () => {
|
|
516
|
+
releaseListeners();
|
|
517
|
+
if (state.dragMoved || Date.now() < state.suppressToggleClickUntil) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
state.expanded = true;
|
|
521
|
+
state.unreadCount = 0;
|
|
522
|
+
renderOverlay(state);
|
|
523
|
+
};
|
|
524
|
+
const releaseListeners = () => {
|
|
525
|
+
doc.removeEventListener("mouseup", finishInteraction);
|
|
526
|
+
doc.removeEventListener("touchend", finishInteraction);
|
|
527
|
+
doc.removeEventListener("touchcancel", finishInteraction);
|
|
528
|
+
};
|
|
529
|
+
doc.addEventListener("mouseup", finishInteraction);
|
|
530
|
+
doc.addEventListener("touchend", finishInteraction);
|
|
531
|
+
doc.addEventListener("touchcancel", finishInteraction);
|
|
532
|
+
};
|
|
533
|
+
element.addEventListener("mousedown", (event) => {
|
|
534
|
+
event.preventDefault();
|
|
535
|
+
startToggleInteraction(getPointFromMouseEvent(event));
|
|
536
|
+
});
|
|
537
|
+
element.addEventListener("touchstart", (event) => {
|
|
538
|
+
const point = getPointFromTouchEvent(event);
|
|
539
|
+
if (!point) {
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
event.preventDefault();
|
|
543
|
+
startToggleInteraction(point);
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
function attachPanelResizeListeners(element, state) {
|
|
547
|
+
element.addEventListener("mousedown", (event) => {
|
|
548
|
+
if (!state.expanded || !canStartDragFromTarget(event.target)) {
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
const point = getPointFromMouseEvent(event);
|
|
552
|
+
if (!isInBottomRightResizeZone(element, point)) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
event.preventDefault();
|
|
556
|
+
event.stopPropagation();
|
|
557
|
+
startResizing(state, point);
|
|
558
|
+
});
|
|
559
|
+
element.addEventListener("touchstart", (event) => {
|
|
560
|
+
if (!state.expanded || !canStartDragFromTarget(event.target)) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
const point = getPointFromTouchEvent(event);
|
|
564
|
+
if (!point || !isInBottomRightResizeZone(element, point)) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
event.preventDefault();
|
|
568
|
+
event.stopPropagation();
|
|
569
|
+
startResizing(state, point);
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
function createOverlayUi(state) {
|
|
573
|
+
const root = document.createElement("div");
|
|
574
|
+
root.style.cssText = [
|
|
575
|
+
"position:fixed",
|
|
576
|
+
"left:12px",
|
|
577
|
+
"top:12px",
|
|
578
|
+
"z-index:2147483647",
|
|
579
|
+
"display:flex",
|
|
580
|
+
"flex-direction:column",
|
|
581
|
+
"align-items:stretch",
|
|
582
|
+
"gap:8px",
|
|
583
|
+
"width:min(565px, calc(100vw - 24px))",
|
|
584
|
+
"pointer-events:none"
|
|
585
|
+
].join(";");
|
|
586
|
+
const toggleButton = createButton("Logs");
|
|
587
|
+
toggleButton.style.pointerEvents = "auto";
|
|
588
|
+
toggleButton.style.alignSelf = "flex-end";
|
|
589
|
+
toggleButton.style.display = "inline-flex";
|
|
590
|
+
toggleButton.style.alignItems = "center";
|
|
591
|
+
toggleButton.style.justifyContent = "center";
|
|
592
|
+
toggleButton.style.minHeight = "40px";
|
|
593
|
+
toggleButton.style.minWidth = "76px";
|
|
594
|
+
toggleButton.style.padding = "8px 14px";
|
|
595
|
+
toggleButton.style.textAlign = "center";
|
|
596
|
+
toggleButton.style.border = "1px solid rgba(122, 212, 255, 0.22)";
|
|
597
|
+
toggleButton.style.background = "linear-gradient(180deg, rgba(13,31,54,0.98), rgba(8,19,37,0.98))";
|
|
598
|
+
toggleButton.style.boxShadow = "0 18px 40px rgba(4,12,24,0.34)";
|
|
599
|
+
toggleButton.style.cursor = "grab";
|
|
600
|
+
toggleButton.style.touchAction = "none";
|
|
601
|
+
const panel = document.createElement("div");
|
|
602
|
+
panel.style.cssText = [
|
|
603
|
+
"position:relative",
|
|
604
|
+
"display:flex",
|
|
605
|
+
"flex-direction:column",
|
|
606
|
+
"width:min(565px, calc(100vw - 24px))",
|
|
607
|
+
"max-height:min(48vh, 372px)",
|
|
608
|
+
"border-radius:18px",
|
|
609
|
+
"border:1px solid rgba(116,167,255,0.16)",
|
|
610
|
+
"background:linear-gradient(180deg, rgba(9,19,37,0.98), rgba(5,12,24,0.98))",
|
|
611
|
+
"box-shadow:0 28px 64px rgba(2,8,18,0.46)",
|
|
612
|
+
"backdrop-filter:blur(16px)",
|
|
613
|
+
"overflow:hidden",
|
|
614
|
+
"cursor:default",
|
|
615
|
+
"pointer-events:auto"
|
|
616
|
+
].join(";");
|
|
617
|
+
const dragZone = document.createElement("div");
|
|
618
|
+
dragZone.style.cssText = [
|
|
619
|
+
"position:absolute",
|
|
620
|
+
"top:0",
|
|
621
|
+
"left:0",
|
|
622
|
+
"right:0",
|
|
623
|
+
"height:" + String(TOP_DRAG_ZONE_PX) + "px",
|
|
624
|
+
"z-index:1",
|
|
625
|
+
"cursor:grab",
|
|
626
|
+
"background:transparent",
|
|
627
|
+
"pointer-events:auto"
|
|
628
|
+
].join(";");
|
|
629
|
+
const controls = document.createElement("div");
|
|
630
|
+
controls.style.cssText = [
|
|
631
|
+
"position:absolute",
|
|
632
|
+
"top:22px",
|
|
633
|
+
"right:22px",
|
|
634
|
+
"z-index:2",
|
|
635
|
+
"display:flex",
|
|
636
|
+
"align-items:center",
|
|
637
|
+
"gap:8px",
|
|
638
|
+
"pointer-events:auto"
|
|
639
|
+
].join(";");
|
|
640
|
+
const clearButton = createButton("Clear");
|
|
641
|
+
clearButton.style.background = "rgba(255,255,255,0.1)";
|
|
642
|
+
clearButton.style.border = "1px solid rgba(255,255,255,0.16)";
|
|
643
|
+
clearButton.style.color = "#eef6ff";
|
|
644
|
+
clearButton.style.minHeight = "30px";
|
|
645
|
+
clearButton.style.padding = "4px 9px";
|
|
646
|
+
clearButton.style.fontSize = "11px";
|
|
647
|
+
clearButton.style.backdropFilter = "blur(8px)";
|
|
648
|
+
const collapseButton = createButton("Hide");
|
|
649
|
+
collapseButton.style.background = "rgba(113, 171, 255, 0.12)";
|
|
650
|
+
collapseButton.style.border = "1px solid rgba(113, 171, 255, 0.2)";
|
|
651
|
+
collapseButton.style.color = "#d9ebff";
|
|
652
|
+
collapseButton.style.minHeight = "30px";
|
|
653
|
+
collapseButton.style.padding = "4px 9px";
|
|
654
|
+
collapseButton.style.fontSize = "11px";
|
|
655
|
+
collapseButton.style.backdropFilter = "blur(8px)";
|
|
656
|
+
const body = document.createElement("div");
|
|
657
|
+
body.style.cssText = [
|
|
658
|
+
"position:relative",
|
|
659
|
+
"display:flex",
|
|
660
|
+
"flex-direction:column",
|
|
661
|
+
"padding:12px",
|
|
662
|
+
"background:linear-gradient(180deg, rgba(4,10,20,0.88), rgba(3,8,18,0.98))",
|
|
663
|
+
"flex:1 1 auto",
|
|
664
|
+
"min-height:0"
|
|
665
|
+
].join(";");
|
|
666
|
+
const entries = document.createElement("div");
|
|
667
|
+
entries.style.cssText = [
|
|
668
|
+
"display:flex",
|
|
669
|
+
"flex-direction:column",
|
|
670
|
+
"gap:0",
|
|
671
|
+
"overflow:auto",
|
|
672
|
+
"flex:1 1 auto",
|
|
673
|
+
"min-height:96px",
|
|
674
|
+
"max-height:min(36vh, 280px)",
|
|
675
|
+
"padding:0",
|
|
676
|
+
"border:1px solid rgba(115,153,212,0.14)",
|
|
677
|
+
"border-radius:12px",
|
|
678
|
+
"background:rgba(4,10,20,0.82)"
|
|
679
|
+
].join(";");
|
|
680
|
+
const emptyState = document.createElement("div");
|
|
681
|
+
emptyState.style.cssText = [
|
|
682
|
+
"display:flex",
|
|
683
|
+
"align-items:center",
|
|
684
|
+
"justify-content:center",
|
|
685
|
+
"flex:1 1 auto",
|
|
686
|
+
"min-height:96px",
|
|
687
|
+
"color:rgba(204,222,250,0.6)",
|
|
688
|
+
"font:500 12px/1.5 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
|
|
689
|
+
"text-align:center",
|
|
690
|
+
"padding:18px"
|
|
691
|
+
].join(";");
|
|
692
|
+
emptyState.textContent = "Console output will appear here.";
|
|
693
|
+
collapseButton.addEventListener("click", (event) => {
|
|
694
|
+
event.stopPropagation();
|
|
695
|
+
state.expanded = false;
|
|
696
|
+
renderOverlay(state);
|
|
697
|
+
});
|
|
698
|
+
clearButton.addEventListener("click", (event) => {
|
|
699
|
+
event.stopPropagation();
|
|
700
|
+
state.entries = [];
|
|
701
|
+
state.unreadCount = 0;
|
|
702
|
+
renderOverlay(state);
|
|
703
|
+
});
|
|
704
|
+
controls.appendChild(clearButton);
|
|
705
|
+
controls.appendChild(collapseButton);
|
|
706
|
+
entries.appendChild(emptyState);
|
|
707
|
+
body.appendChild(entries);
|
|
708
|
+
body.appendChild(controls);
|
|
709
|
+
panel.appendChild(dragZone);
|
|
710
|
+
panel.appendChild(body);
|
|
711
|
+
attachDragStartListeners(dragZone, state);
|
|
712
|
+
attachPanelResizeListeners(panel, state);
|
|
713
|
+
attachCollapsedToggleListeners(toggleButton, state);
|
|
714
|
+
root.appendChild(panel);
|
|
715
|
+
root.appendChild(toggleButton);
|
|
716
|
+
return {
|
|
717
|
+
body,
|
|
718
|
+
clearButton,
|
|
719
|
+
collapseButton,
|
|
720
|
+
controls,
|
|
721
|
+
dragZone,
|
|
722
|
+
emptyState,
|
|
723
|
+
entries,
|
|
724
|
+
panel,
|
|
725
|
+
root,
|
|
726
|
+
toggleButton
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function renderOverlay(state) {
|
|
730
|
+
if (!state.ui) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
state.ui.panel.style.display = state.expanded ? "flex" : "none";
|
|
734
|
+
state.ui.toggleButton.style.display = state.expanded ? "none" : "inline-flex";
|
|
735
|
+
state.ui.toggleButton.textContent = "Logs";
|
|
736
|
+
if (state.entries.length === 0) {
|
|
737
|
+
state.ui.entries.style.display = "flex";
|
|
738
|
+
state.ui.emptyState.style.display = "flex";
|
|
739
|
+
state.ui.entries.replaceChildren(state.ui.emptyState);
|
|
740
|
+
applyPanelSize(state);
|
|
741
|
+
applyOverlayPosition(state);
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
state.ui.entries.style.display = "flex";
|
|
745
|
+
state.ui.emptyState.style.display = "none";
|
|
746
|
+
const nextChildren = state.entries.map((entry) => {
|
|
747
|
+
const accent = getLevelAccent(entry.level);
|
|
748
|
+
const row = document.createElement("div");
|
|
749
|
+
row.style.cssText = [
|
|
750
|
+
"display:flex",
|
|
751
|
+
"align-items:flex-start",
|
|
752
|
+
"gap:0",
|
|
753
|
+
"padding:4px 12px",
|
|
754
|
+
"background:" + accent.lineBackground
|
|
755
|
+
].join(";");
|
|
756
|
+
const line = document.createElement("div");
|
|
757
|
+
line.textContent = formatTimestamp(entry.timestamp) + " " + entry.level.toUpperCase() + " " + entry.message;
|
|
758
|
+
line.style.cssText = [
|
|
759
|
+
"color:#ecf4ff",
|
|
760
|
+
"font:500 12px/1.5 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
|
|
761
|
+
"white-space:pre-wrap",
|
|
762
|
+
"word-break:break-word",
|
|
763
|
+
"flex:1 1 auto"
|
|
764
|
+
].join(";");
|
|
765
|
+
row.appendChild(line);
|
|
766
|
+
return row;
|
|
767
|
+
});
|
|
768
|
+
state.ui.entries.replaceChildren(...nextChildren);
|
|
769
|
+
state.ui.entries.scrollTop = state.ui.entries.scrollHeight;
|
|
770
|
+
applyPanelSize(state);
|
|
771
|
+
applyOverlayPosition(state);
|
|
772
|
+
}
|
|
773
|
+
function mountOverlay(state) {
|
|
774
|
+
const doc = getDocument();
|
|
775
|
+
if (!doc?.body || state.ui) {
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
state.ui = createOverlayUi(state);
|
|
779
|
+
doc.body.appendChild(state.ui.root);
|
|
780
|
+
applyPanelSize(state);
|
|
781
|
+
applyOverlayPosition(state);
|
|
782
|
+
renderOverlay(state);
|
|
783
|
+
}
|
|
784
|
+
function enqueueEntry(state, level, args) {
|
|
785
|
+
state.entries.push(createEntry(level, args, state.nextEntryId));
|
|
786
|
+
state.nextEntryId += 1;
|
|
787
|
+
if (state.entries.length > state.maxEntries) {
|
|
788
|
+
state.entries.splice(0, state.entries.length - state.maxEntries);
|
|
789
|
+
}
|
|
790
|
+
if (!state.expanded) {
|
|
791
|
+
state.unreadCount += 1;
|
|
792
|
+
}
|
|
793
|
+
renderOverlay(state);
|
|
794
|
+
}
|
|
795
|
+
function restoreConsole(snapshot) {
|
|
796
|
+
for (const method of CONSOLE_METHODS) {
|
|
797
|
+
console[method] = snapshot[method];
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
function patchConsole(state) {
|
|
801
|
+
for (const method of CONSOLE_METHODS) {
|
|
802
|
+
const original = state.originalConsole[method];
|
|
803
|
+
console[method] = (...args) => {
|
|
804
|
+
enqueueEntry(state, method, args);
|
|
805
|
+
original(...args);
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
function cleanupOverlay(browserWindow, state) {
|
|
810
|
+
restoreConsole(state.originalConsole);
|
|
811
|
+
stopResizing(state);
|
|
812
|
+
stopDragging(state);
|
|
813
|
+
if (state.domReadyHandler) {
|
|
814
|
+
getDocument()?.removeEventListener("DOMContentLoaded", state.domReadyHandler);
|
|
815
|
+
state.domReadyHandler = void 0;
|
|
816
|
+
}
|
|
817
|
+
if (state.resizeHandler && typeof browserWindow.removeEventListener === "function") {
|
|
818
|
+
browserWindow.removeEventListener("resize", state.resizeHandler);
|
|
819
|
+
state.resizeHandler = void 0;
|
|
820
|
+
}
|
|
821
|
+
state.ui?.root.remove();
|
|
822
|
+
state.ui = null;
|
|
823
|
+
delete browserWindow.__oasizLogOverlayController__;
|
|
824
|
+
delete browserWindow.__oasizLogOverlayState__;
|
|
825
|
+
}
|
|
826
|
+
function createController(browserWindow, state) {
|
|
827
|
+
return {
|
|
828
|
+
retain() {
|
|
829
|
+
state.refCount += 1;
|
|
830
|
+
this.ensureMounted();
|
|
831
|
+
},
|
|
832
|
+
ensureMounted() {
|
|
833
|
+
const doc = getDocument();
|
|
834
|
+
if (!doc) {
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
if (doc.body) {
|
|
838
|
+
mountOverlay(state);
|
|
839
|
+
applyOverlayPosition(state);
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
if (!state.domReadyHandler) {
|
|
843
|
+
state.domReadyHandler = () => {
|
|
844
|
+
mountOverlay(state);
|
|
845
|
+
state.domReadyHandler = void 0;
|
|
846
|
+
};
|
|
847
|
+
doc.addEventListener("DOMContentLoaded", state.domReadyHandler, {
|
|
848
|
+
once: true
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
},
|
|
852
|
+
clear() {
|
|
853
|
+
state.entries = [];
|
|
854
|
+
state.unreadCount = 0;
|
|
855
|
+
renderOverlay(state);
|
|
856
|
+
},
|
|
857
|
+
show() {
|
|
858
|
+
state.expanded = true;
|
|
859
|
+
state.unreadCount = 0;
|
|
860
|
+
renderOverlay(state);
|
|
861
|
+
},
|
|
862
|
+
hide() {
|
|
863
|
+
state.expanded = false;
|
|
864
|
+
renderOverlay(state);
|
|
865
|
+
},
|
|
866
|
+
isVisible() {
|
|
867
|
+
return state.expanded;
|
|
868
|
+
},
|
|
869
|
+
destroy() {
|
|
870
|
+
state.refCount = Math.max(0, state.refCount - 1);
|
|
871
|
+
if (state.refCount === 0) {
|
|
872
|
+
cleanupOverlay(browserWindow, state);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
function enableLogOverlay(options = {}) {
|
|
878
|
+
if (options.enabled === false) {
|
|
879
|
+
return NOOP_HANDLE;
|
|
880
|
+
}
|
|
881
|
+
const browserWindow = getBrowserWindow();
|
|
882
|
+
const doc = getDocument();
|
|
883
|
+
if (!browserWindow || !doc) {
|
|
884
|
+
return NOOP_HANDLE;
|
|
885
|
+
}
|
|
886
|
+
const existingController = browserWindow.__oasizLogOverlayController__;
|
|
887
|
+
const existingState = browserWindow.__oasizLogOverlayState__;
|
|
888
|
+
if (existingController && existingState) {
|
|
889
|
+
existingController.retain();
|
|
890
|
+
if (typeof options.maxEntries === "number") {
|
|
891
|
+
existingState.maxEntries = clampMaxEntries(options.maxEntries);
|
|
892
|
+
if (existingState.entries.length > existingState.maxEntries) {
|
|
893
|
+
existingState.entries.splice(
|
|
894
|
+
0,
|
|
895
|
+
existingState.entries.length - existingState.maxEntries
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
if (typeof options.collapsed === "boolean") {
|
|
900
|
+
existingState.expanded = !options.collapsed;
|
|
901
|
+
applyPanelSize(existingState);
|
|
902
|
+
if (existingState.expanded) {
|
|
903
|
+
existingState.unreadCount = 0;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
if (typeof options.title === "string" && options.title.trim().length > 0) {
|
|
907
|
+
existingState.title = options.title.trim();
|
|
908
|
+
}
|
|
909
|
+
existingController.ensureMounted();
|
|
910
|
+
renderOverlay(existingState);
|
|
911
|
+
return existingController;
|
|
912
|
+
}
|
|
913
|
+
const state = {
|
|
914
|
+
dragMoved: false,
|
|
915
|
+
dragStartPoint: null,
|
|
916
|
+
entries: [],
|
|
917
|
+
expanded: options.collapsed !== true,
|
|
918
|
+
isDragging: false,
|
|
919
|
+
isResizing: false,
|
|
920
|
+
lastDragPoint: null,
|
|
921
|
+
maxEntries: clampMaxEntries(options.maxEntries),
|
|
922
|
+
nextEntryId: 1,
|
|
923
|
+
originalConsole: createConsoleSnapshot(),
|
|
924
|
+
panelSize: null,
|
|
925
|
+
position: null,
|
|
926
|
+
refCount: 1,
|
|
927
|
+
removeDragListeners: null,
|
|
928
|
+
removeResizeListeners: null,
|
|
929
|
+
resizeStartPoint: null,
|
|
930
|
+
resizeStartSize: null,
|
|
931
|
+
suppressToggleClickUntil: 0,
|
|
932
|
+
title: typeof options.title === "string" && options.title.trim().length > 0 ? options.title.trim() : DEFAULT_TITLE,
|
|
933
|
+
resizeHandler: void 0,
|
|
934
|
+
ui: null,
|
|
935
|
+
unreadCount: 0
|
|
936
|
+
};
|
|
937
|
+
const controller = createController(browserWindow, state);
|
|
938
|
+
browserWindow.__oasizLogOverlayState__ = state;
|
|
939
|
+
browserWindow.__oasizLogOverlayController__ = controller;
|
|
940
|
+
patchConsole(state);
|
|
941
|
+
if (typeof browserWindow.addEventListener === "function") {
|
|
942
|
+
state.resizeHandler = () => {
|
|
943
|
+
applyOverlayPosition(state);
|
|
944
|
+
};
|
|
945
|
+
browserWindow.addEventListener("resize", state.resizeHandler);
|
|
946
|
+
}
|
|
947
|
+
controller.ensureMounted();
|
|
948
|
+
return controller;
|
|
949
|
+
}
|
|
950
|
+
|
|
25
951
|
// src/multiplayer.ts
|
|
26
|
-
function
|
|
952
|
+
function isDevelopment3() {
|
|
27
953
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
28
954
|
return nodeEnv !== "production";
|
|
29
955
|
}
|
|
30
|
-
function
|
|
956
|
+
function getBridgeWindow3() {
|
|
31
957
|
if (typeof window === "undefined") {
|
|
32
958
|
return void 0;
|
|
33
959
|
}
|
|
34
960
|
return window;
|
|
35
961
|
}
|
|
36
|
-
function shareRoomCode(roomCode) {
|
|
37
|
-
const bridge =
|
|
962
|
+
function shareRoomCode(roomCode, options) {
|
|
963
|
+
const bridge = getBridgeWindow3();
|
|
38
964
|
if (typeof bridge?.shareRoomCode === "function") {
|
|
39
|
-
bridge.shareRoomCode(roomCode);
|
|
965
|
+
bridge.shareRoomCode(roomCode, options);
|
|
40
966
|
return;
|
|
41
967
|
}
|
|
42
|
-
if (
|
|
968
|
+
if (isDevelopment3()) {
|
|
43
969
|
console.warn(
|
|
44
970
|
"[oasiz/sdk] shareRoomCode bridge is unavailable. This is expected in local development."
|
|
45
971
|
);
|
|
46
972
|
}
|
|
47
973
|
}
|
|
974
|
+
function openInviteModal() {
|
|
975
|
+
const bridge = getBridgeWindow3();
|
|
976
|
+
if (typeof bridge?.openInviteModal === "function") {
|
|
977
|
+
bridge.openInviteModal();
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
if (isDevelopment3()) {
|
|
981
|
+
console.warn(
|
|
982
|
+
"[oasiz/sdk] openInviteModal bridge is unavailable. This is expected in local development."
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
48
986
|
function getGameId() {
|
|
49
|
-
const bridge =
|
|
987
|
+
const bridge = getBridgeWindow3();
|
|
50
988
|
return bridge?.__GAME_ID__;
|
|
51
989
|
}
|
|
52
990
|
function getRoomCode() {
|
|
53
|
-
const bridge =
|
|
991
|
+
const bridge = getBridgeWindow3();
|
|
54
992
|
return bridge?.__ROOM_CODE__;
|
|
55
993
|
}
|
|
994
|
+
function getPlayerId() {
|
|
995
|
+
const bridge = getBridgeWindow3();
|
|
996
|
+
return bridge?.__PLAYER_ID__;
|
|
997
|
+
}
|
|
56
998
|
function getPlayerName() {
|
|
57
|
-
const bridge =
|
|
999
|
+
const bridge = getBridgeWindow3();
|
|
58
1000
|
return bridge?.__PLAYER_NAME__;
|
|
59
1001
|
}
|
|
60
1002
|
function getPlayerAvatar() {
|
|
61
|
-
const bridge =
|
|
1003
|
+
const bridge = getBridgeWindow3();
|
|
62
1004
|
return bridge?.__PLAYER_AVATAR__;
|
|
63
1005
|
}
|
|
64
1006
|
|
|
65
1007
|
// src/score.ts
|
|
66
|
-
function
|
|
1008
|
+
function isDevelopment4() {
|
|
67
1009
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
68
1010
|
return nodeEnv !== "production";
|
|
69
1011
|
}
|
|
70
|
-
function
|
|
71
|
-
if (
|
|
1012
|
+
function warnMissingBridge2(methodName) {
|
|
1013
|
+
if (isDevelopment4()) {
|
|
72
1014
|
console.warn(
|
|
73
1015
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
74
1016
|
);
|
|
75
1017
|
}
|
|
76
1018
|
}
|
|
77
|
-
function
|
|
1019
|
+
function getBridgeWindow4() {
|
|
78
1020
|
if (typeof window === "undefined") {
|
|
79
1021
|
return void 0;
|
|
80
1022
|
}
|
|
@@ -82,41 +1024,92 @@ function getBridgeWindow3() {
|
|
|
82
1024
|
}
|
|
83
1025
|
function submitScore(score) {
|
|
84
1026
|
if (!Number.isFinite(score)) {
|
|
85
|
-
if (
|
|
1027
|
+
if (isDevelopment4()) {
|
|
86
1028
|
console.warn("[oasiz/sdk] submitScore expected a finite number:", score);
|
|
87
1029
|
}
|
|
88
1030
|
return;
|
|
89
1031
|
}
|
|
90
|
-
const bridge =
|
|
1032
|
+
const bridge = getBridgeWindow4();
|
|
91
1033
|
const normalizedScore = Math.max(0, Math.floor(score));
|
|
92
1034
|
if (typeof bridge?.submitScore === "function") {
|
|
93
1035
|
bridge.submitScore(normalizedScore);
|
|
94
1036
|
return;
|
|
95
1037
|
}
|
|
96
|
-
|
|
1038
|
+
warnMissingBridge2("submitScore");
|
|
97
1039
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
1040
|
+
|
|
1041
|
+
// src/score-edit.ts
|
|
1042
|
+
function isDevelopment5() {
|
|
1043
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1044
|
+
return nodeEnv !== "production";
|
|
1045
|
+
}
|
|
1046
|
+
function getBridgeWindow5() {
|
|
1047
|
+
if (typeof window === "undefined") {
|
|
1048
|
+
return void 0;
|
|
1049
|
+
}
|
|
1050
|
+
return window;
|
|
1051
|
+
}
|
|
1052
|
+
function warnMissingBridge3(methodName) {
|
|
1053
|
+
if (isDevelopment5()) {
|
|
1054
|
+
console.warn(
|
|
1055
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1056
|
+
);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
async function editScore(payload, methodName) {
|
|
1060
|
+
const bridge = getBridgeWindow5();
|
|
1061
|
+
if (typeof bridge?.__oasizEditScore !== "function") {
|
|
1062
|
+
warnMissingBridge3(methodName);
|
|
1063
|
+
return null;
|
|
1064
|
+
}
|
|
1065
|
+
try {
|
|
1066
|
+
const result = await bridge.__oasizEditScore(payload);
|
|
1067
|
+
return result ?? null;
|
|
1068
|
+
} catch (error) {
|
|
1069
|
+
if (isDevelopment5()) {
|
|
1070
|
+
console.error("[oasiz/sdk] " + methodName + " failed:", error);
|
|
1071
|
+
}
|
|
1072
|
+
return null;
|
|
103
1073
|
}
|
|
104
|
-
|
|
1074
|
+
}
|
|
1075
|
+
async function addScore(delta) {
|
|
1076
|
+
if (!Number.isInteger(delta)) {
|
|
1077
|
+
if (isDevelopment5()) {
|
|
1078
|
+
console.warn("[oasiz/sdk] addScore expected an integer:", delta);
|
|
1079
|
+
}
|
|
1080
|
+
return null;
|
|
1081
|
+
}
|
|
1082
|
+
if (delta === 0) {
|
|
1083
|
+
return null;
|
|
1084
|
+
}
|
|
1085
|
+
return editScore({ delta }, "addScore");
|
|
1086
|
+
}
|
|
1087
|
+
async function setScore(score) {
|
|
1088
|
+
if (!Number.isInteger(score) || score < 0) {
|
|
1089
|
+
if (isDevelopment5()) {
|
|
1090
|
+
console.warn(
|
|
1091
|
+
"[oasiz/sdk] setScore expected a non-negative integer:",
|
|
1092
|
+
score
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
return null;
|
|
1096
|
+
}
|
|
1097
|
+
return editScore({ score }, "setScore");
|
|
105
1098
|
}
|
|
106
1099
|
|
|
107
1100
|
// src/share.ts
|
|
108
|
-
function
|
|
1101
|
+
function isDevelopment6() {
|
|
109
1102
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
110
1103
|
return nodeEnv !== "production";
|
|
111
1104
|
}
|
|
112
|
-
function
|
|
1105
|
+
function getBridgeWindow6() {
|
|
113
1106
|
if (typeof window === "undefined") {
|
|
114
1107
|
return void 0;
|
|
115
1108
|
}
|
|
116
1109
|
return window;
|
|
117
1110
|
}
|
|
118
|
-
function
|
|
119
|
-
if (
|
|
1111
|
+
function warnMissingBridge4(methodName) {
|
|
1112
|
+
if (isDevelopment6()) {
|
|
120
1113
|
console.warn(
|
|
121
1114
|
"[oasiz/sdk] " + methodName + " share bridge is unavailable. This is expected in local development."
|
|
122
1115
|
);
|
|
@@ -151,127 +1144,454 @@ function validateRequest(options) {
|
|
|
151
1144
|
"Share image must be an http(s) URL or a data:image/... base64 string."
|
|
152
1145
|
);
|
|
153
1146
|
}
|
|
154
|
-
return {
|
|
155
|
-
...hasText ? { text } : {},
|
|
156
|
-
...hasScore ? { score: options.score } : {},
|
|
157
|
-
...hasImage ? { image: options.image } : {}
|
|
158
|
-
};
|
|
1147
|
+
return {
|
|
1148
|
+
...hasText ? { text } : {},
|
|
1149
|
+
...hasScore ? { score: options.score } : {},
|
|
1150
|
+
...hasImage ? { image: options.image } : {}
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
async function share(options) {
|
|
1154
|
+
const request = validateRequest(options);
|
|
1155
|
+
const bridge = getBridgeWindow6();
|
|
1156
|
+
if (typeof bridge?.__oasizShareRequest !== "function") {
|
|
1157
|
+
warnMissingBridge4("__oasizShareRequest");
|
|
1158
|
+
throw new Error("Share bridge unavailable");
|
|
1159
|
+
}
|
|
1160
|
+
await bridge.__oasizShareRequest(request);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
// src/state.ts
|
|
1164
|
+
function isDevelopment7() {
|
|
1165
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1166
|
+
return nodeEnv !== "production";
|
|
1167
|
+
}
|
|
1168
|
+
function getBridgeWindow7() {
|
|
1169
|
+
if (typeof window === "undefined") {
|
|
1170
|
+
return void 0;
|
|
1171
|
+
}
|
|
1172
|
+
return window;
|
|
1173
|
+
}
|
|
1174
|
+
function isPlainObject(value) {
|
|
1175
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1176
|
+
return false;
|
|
1177
|
+
}
|
|
1178
|
+
const proto = Object.getPrototypeOf(value);
|
|
1179
|
+
return proto === Object.prototype || proto === null;
|
|
1180
|
+
}
|
|
1181
|
+
function warnMissingBridge5(methodName) {
|
|
1182
|
+
if (isDevelopment7()) {
|
|
1183
|
+
console.warn(
|
|
1184
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
function loadGameState() {
|
|
1189
|
+
const bridge = getBridgeWindow7();
|
|
1190
|
+
if (typeof bridge?.loadGameState !== "function") {
|
|
1191
|
+
warnMissingBridge5("loadGameState");
|
|
1192
|
+
return {};
|
|
1193
|
+
}
|
|
1194
|
+
const state = bridge.loadGameState();
|
|
1195
|
+
if (!isPlainObject(state)) {
|
|
1196
|
+
if (isDevelopment7()) {
|
|
1197
|
+
console.warn(
|
|
1198
|
+
"[oasiz/sdk] loadGameState returned invalid data. Falling back to empty object."
|
|
1199
|
+
);
|
|
1200
|
+
}
|
|
1201
|
+
return {};
|
|
1202
|
+
}
|
|
1203
|
+
return state;
|
|
1204
|
+
}
|
|
1205
|
+
function saveGameState(state) {
|
|
1206
|
+
if (!isPlainObject(state)) {
|
|
1207
|
+
if (isDevelopment7()) {
|
|
1208
|
+
console.warn("[oasiz/sdk] saveGameState expected a plain object:", state);
|
|
1209
|
+
}
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
const bridge = getBridgeWindow7();
|
|
1213
|
+
if (typeof bridge?.saveGameState === "function") {
|
|
1214
|
+
bridge.saveGameState(state);
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
warnMissingBridge5("saveGameState");
|
|
1218
|
+
}
|
|
1219
|
+
function flushGameState() {
|
|
1220
|
+
const bridge = getBridgeWindow7();
|
|
1221
|
+
if (typeof bridge?.flushGameState === "function") {
|
|
1222
|
+
bridge.flushGameState();
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1225
|
+
warnMissingBridge5("flushGameState");
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
// src/lifecycle.ts
|
|
1229
|
+
function isDevelopment8() {
|
|
1230
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1231
|
+
return nodeEnv !== "production";
|
|
1232
|
+
}
|
|
1233
|
+
function addLifecycleListener(eventName, callback) {
|
|
1234
|
+
if (typeof window === "undefined") {
|
|
1235
|
+
if (isDevelopment8()) {
|
|
1236
|
+
console.warn(
|
|
1237
|
+
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
1238
|
+
);
|
|
1239
|
+
}
|
|
1240
|
+
return () => {
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
const handler = () => callback();
|
|
1244
|
+
window.addEventListener(eventName, handler);
|
|
1245
|
+
return () => window.removeEventListener(eventName, handler);
|
|
1246
|
+
}
|
|
1247
|
+
function onPause(callback) {
|
|
1248
|
+
return addLifecycleListener("oasiz:pause", callback);
|
|
1249
|
+
}
|
|
1250
|
+
function onResume(callback) {
|
|
1251
|
+
return addLifecycleListener("oasiz:resume", callback);
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// src/layout.ts
|
|
1255
|
+
var INSET_SIDES = ["top", "right", "bottom", "left"];
|
|
1256
|
+
var SIDE_TO_AXIS = {
|
|
1257
|
+
top: "vertical",
|
|
1258
|
+
right: "horizontal",
|
|
1259
|
+
bottom: "vertical",
|
|
1260
|
+
left: "horizontal"
|
|
1261
|
+
};
|
|
1262
|
+
function createInsetEdges(value) {
|
|
1263
|
+
return {
|
|
1264
|
+
top: value,
|
|
1265
|
+
right: value,
|
|
1266
|
+
bottom: value,
|
|
1267
|
+
left: value
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
function isDevelopment9() {
|
|
1271
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1272
|
+
return nodeEnv !== "production";
|
|
1273
|
+
}
|
|
1274
|
+
function getBridgeWindow8() {
|
|
1275
|
+
if (typeof window === "undefined") {
|
|
1276
|
+
return void 0;
|
|
1277
|
+
}
|
|
1278
|
+
return window;
|
|
1279
|
+
}
|
|
1280
|
+
function warnMissingBridge6(methodName) {
|
|
1281
|
+
if (isDevelopment9()) {
|
|
1282
|
+
console.warn(
|
|
1283
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
function isRecord(value) {
|
|
1288
|
+
return typeof value === "object" && value !== null;
|
|
1289
|
+
}
|
|
1290
|
+
function toFiniteNumber(value) {
|
|
1291
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1292
|
+
if (typeof value !== "string") {
|
|
1293
|
+
return void 0;
|
|
1294
|
+
}
|
|
1295
|
+
const parsed = Number.parseFloat(value.trim());
|
|
1296
|
+
if (!Number.isFinite(parsed)) {
|
|
1297
|
+
return void 0;
|
|
1298
|
+
}
|
|
1299
|
+
return parsed;
|
|
1300
|
+
}
|
|
1301
|
+
return value;
|
|
1302
|
+
}
|
|
1303
|
+
function clampInsetPixels(value) {
|
|
1304
|
+
const numeric = toFiniteNumber(value);
|
|
1305
|
+
if (typeof numeric === "undefined") {
|
|
1306
|
+
return void 0;
|
|
1307
|
+
}
|
|
1308
|
+
return Math.max(0, numeric);
|
|
1309
|
+
}
|
|
1310
|
+
function normalizeInsetPercent(value) {
|
|
1311
|
+
const numeric = toFiniteNumber(value);
|
|
1312
|
+
if (typeof numeric === "undefined") {
|
|
1313
|
+
return void 0;
|
|
1314
|
+
}
|
|
1315
|
+
return Math.min(100, Math.max(0, numeric));
|
|
1316
|
+
}
|
|
1317
|
+
function getViewportSize2(bridge, axis) {
|
|
1318
|
+
const visualViewportSize = axis === "vertical" ? bridge.visualViewport?.height : bridge.visualViewport?.width;
|
|
1319
|
+
if (typeof visualViewportSize === "number" && Number.isFinite(visualViewportSize) && visualViewportSize > 0) {
|
|
1320
|
+
return visualViewportSize;
|
|
1321
|
+
}
|
|
1322
|
+
const innerSize = axis === "vertical" ? bridge.innerHeight : bridge.innerWidth;
|
|
1323
|
+
if (typeof innerSize === "number" && Number.isFinite(innerSize) && innerSize > 0) {
|
|
1324
|
+
return innerSize;
|
|
1325
|
+
}
|
|
1326
|
+
const documentSize = axis === "vertical" ? bridge.document?.documentElement?.clientHeight : bridge.document?.documentElement?.clientWidth;
|
|
1327
|
+
if (typeof documentSize === "number" && Number.isFinite(documentSize) && documentSize > 0) {
|
|
1328
|
+
return documentSize;
|
|
1329
|
+
}
|
|
1330
|
+
const bodySize = axis === "vertical" ? bridge.document?.body?.clientHeight : bridge.document?.body?.clientWidth;
|
|
1331
|
+
if (typeof bodySize === "number" && Number.isFinite(bodySize) && bodySize > 0) {
|
|
1332
|
+
return bodySize;
|
|
1333
|
+
}
|
|
1334
|
+
return 0;
|
|
1335
|
+
}
|
|
1336
|
+
function readCssSafeAreaValue(bridge, cssValue) {
|
|
1337
|
+
const doc = bridge.document;
|
|
1338
|
+
const root = doc?.body ?? doc?.documentElement;
|
|
1339
|
+
if (!doc || !root || typeof doc.createElement !== "function" || typeof root.appendChild !== "function" || typeof bridge.getComputedStyle !== "function") {
|
|
1340
|
+
return 0;
|
|
1341
|
+
}
|
|
1342
|
+
const probe = doc.createElement("div");
|
|
1343
|
+
probe.style.position = "fixed";
|
|
1344
|
+
probe.style.top = "0";
|
|
1345
|
+
probe.style.left = "0";
|
|
1346
|
+
probe.style.width = "0";
|
|
1347
|
+
probe.style.height = "0";
|
|
1348
|
+
probe.style.visibility = "hidden";
|
|
1349
|
+
probe.style.pointerEvents = "none";
|
|
1350
|
+
probe.style.paddingTop = cssValue;
|
|
1351
|
+
root.appendChild(probe);
|
|
1352
|
+
try {
|
|
1353
|
+
return clampInsetPixels(bridge.getComputedStyle(probe).paddingTop) ?? 0;
|
|
1354
|
+
} finally {
|
|
1355
|
+
if (typeof probe.remove === "function") {
|
|
1356
|
+
probe.remove();
|
|
1357
|
+
} else {
|
|
1358
|
+
probe.parentNode?.removeChild(probe);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
function readCssSafeAreaPixels(bridge, side) {
|
|
1363
|
+
const envPixels = readCssSafeAreaValue(
|
|
1364
|
+
bridge,
|
|
1365
|
+
"env(safe-area-inset-" + side + ")"
|
|
1366
|
+
);
|
|
1367
|
+
if (envPixels > 0) {
|
|
1368
|
+
return envPixels;
|
|
1369
|
+
}
|
|
1370
|
+
return readCssSafeAreaValue(
|
|
1371
|
+
bridge,
|
|
1372
|
+
"constant(safe-area-inset-" + side + ")"
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
function getDevicePixelRatio(bridge) {
|
|
1376
|
+
const dpr = bridge.devicePixelRatio;
|
|
1377
|
+
if (typeof dpr !== "number" || !Number.isFinite(dpr) || dpr <= 0) {
|
|
1378
|
+
return 1;
|
|
1379
|
+
}
|
|
1380
|
+
return dpr;
|
|
1381
|
+
}
|
|
1382
|
+
function roughlyEqualPixels(a, b) {
|
|
1383
|
+
return Math.abs(a - b) <= 2;
|
|
1384
|
+
}
|
|
1385
|
+
function normalizeInsetPixels(value, bridge, side) {
|
|
1386
|
+
const pixels = clampInsetPixels(value);
|
|
1387
|
+
if (typeof pixels === "undefined") {
|
|
1388
|
+
return void 0;
|
|
1389
|
+
}
|
|
1390
|
+
const cssEnvPixels = readCssSafeAreaPixels(bridge, side);
|
|
1391
|
+
if (pixels <= 0) {
|
|
1392
|
+
return cssEnvPixels;
|
|
1393
|
+
}
|
|
1394
|
+
const dpr = getDevicePixelRatio(bridge);
|
|
1395
|
+
if (cssEnvPixels > 0 && dpr > 1 && roughlyEqualPixels(pixels / dpr, cssEnvPixels)) {
|
|
1396
|
+
return cssEnvPixels;
|
|
1397
|
+
}
|
|
1398
|
+
return pixels;
|
|
159
1399
|
}
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
warnMissingBridge2("__oasizShareRequest");
|
|
165
|
-
throw new Error("Share bridge unavailable");
|
|
1400
|
+
function pixelsToPercentOfViewport(pixels, bridge, side) {
|
|
1401
|
+
const size = getViewportSize2(bridge, SIDE_TO_AXIS[side]);
|
|
1402
|
+
if (size <= 0) {
|
|
1403
|
+
return 0;
|
|
166
1404
|
}
|
|
167
|
-
|
|
1405
|
+
return normalizeInsetPercent(pixels / size * 100) ?? 0;
|
|
168
1406
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
1407
|
+
function percentToPixelsOfViewport(percent, bridge, side) {
|
|
1408
|
+
const size = getViewportSize2(bridge, SIDE_TO_AXIS[side]);
|
|
1409
|
+
if (size <= 0) {
|
|
1410
|
+
return 0;
|
|
1411
|
+
}
|
|
1412
|
+
return percent / 100 * size;
|
|
174
1413
|
}
|
|
175
|
-
function
|
|
176
|
-
|
|
1414
|
+
function cssSafeAreaPercent(bridge, side) {
|
|
1415
|
+
return pixelsToPercentOfViewport(readCssSafeAreaPixels(bridge, side), bridge, side);
|
|
1416
|
+
}
|
|
1417
|
+
function resolvePercentValue(value, bridge, side) {
|
|
1418
|
+
const percent = normalizeInsetPercent(value);
|
|
1419
|
+
if (typeof percent === "undefined") {
|
|
177
1420
|
return void 0;
|
|
178
1421
|
}
|
|
179
|
-
return
|
|
1422
|
+
return percent > 0 ? percent : cssSafeAreaPercent(bridge, side);
|
|
180
1423
|
}
|
|
181
|
-
function
|
|
182
|
-
|
|
183
|
-
|
|
1424
|
+
function resolvePixelValue(value, bridge, side) {
|
|
1425
|
+
const numeric = toFiniteNumber(value);
|
|
1426
|
+
if (typeof numeric === "undefined") {
|
|
1427
|
+
return void 0;
|
|
184
1428
|
}
|
|
185
|
-
|
|
186
|
-
return proto === Object.prototype || proto === null;
|
|
1429
|
+
return normalizeInsetPixels(numeric, bridge, side);
|
|
187
1430
|
}
|
|
188
|
-
function
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
1431
|
+
function sideSuffix(side) {
|
|
1432
|
+
switch (side) {
|
|
1433
|
+
case "top":
|
|
1434
|
+
return "Top";
|
|
1435
|
+
case "right":
|
|
1436
|
+
return "Right";
|
|
1437
|
+
case "bottom":
|
|
1438
|
+
return "Bottom";
|
|
1439
|
+
case "left":
|
|
1440
|
+
return "Left";
|
|
193
1441
|
}
|
|
194
1442
|
}
|
|
195
|
-
function
|
|
196
|
-
const
|
|
197
|
-
if (typeof
|
|
198
|
-
|
|
199
|
-
return {};
|
|
1443
|
+
function callBridgeFunction(bridge, name) {
|
|
1444
|
+
const fn = bridge[name];
|
|
1445
|
+
if (typeof fn !== "function") {
|
|
1446
|
+
return void 0;
|
|
200
1447
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
return {};
|
|
1448
|
+
try {
|
|
1449
|
+
return fn.call(bridge);
|
|
1450
|
+
} catch (error) {
|
|
1451
|
+
console.error("[oasiz/sdk] " + String(name) + " failed:", error);
|
|
1452
|
+
return void 0;
|
|
209
1453
|
}
|
|
210
|
-
return state;
|
|
211
1454
|
}
|
|
212
|
-
function
|
|
213
|
-
if (!
|
|
214
|
-
|
|
215
|
-
console.warn("[oasiz/sdk] saveGameState expected a plain object:", state);
|
|
216
|
-
}
|
|
217
|
-
return;
|
|
1455
|
+
function readInsetObjectValue(value, side, group) {
|
|
1456
|
+
if (!isRecord(value)) {
|
|
1457
|
+
return void 0;
|
|
218
1458
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
bridge.saveGameState(state);
|
|
222
|
-
return;
|
|
1459
|
+
if (group) {
|
|
1460
|
+
return isRecord(value[group]) ? value[group][side] : void 0;
|
|
223
1461
|
}
|
|
224
|
-
|
|
1462
|
+
return value[side];
|
|
225
1463
|
}
|
|
226
|
-
function
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
1464
|
+
function firstDefined(...values) {
|
|
1465
|
+
return values.find((value) => typeof value !== "undefined");
|
|
1466
|
+
}
|
|
1467
|
+
function readHostInsetSources(bridge) {
|
|
1468
|
+
return {
|
|
1469
|
+
globalPixels: bridge.__OASIZ_VIEWPORT_INSETS__,
|
|
1470
|
+
globalPercent: bridge.__OASIZ_VIEWPORT_INSETS_PERCENT__,
|
|
1471
|
+
methodPixels: callBridgeFunction(bridge, "getViewportInsets"),
|
|
1472
|
+
methodPercent: callBridgeFunction(bridge, "getViewportInsetsPercent")
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function readIndividualPercentValue(bridge, side) {
|
|
1476
|
+
const suffix = sideSuffix(side);
|
|
1477
|
+
return firstDefined(
|
|
1478
|
+
callBridgeFunction(
|
|
1479
|
+
bridge,
|
|
1480
|
+
"getSafeArea" + suffix + "Percent"
|
|
1481
|
+
),
|
|
1482
|
+
bridge["__OASIZ_SAFE_AREA_" + side.toUpperCase() + "_PERCENT__"]
|
|
1483
|
+
);
|
|
1484
|
+
}
|
|
1485
|
+
function readIndividualPixelValue(bridge, side) {
|
|
1486
|
+
const suffix = sideSuffix(side);
|
|
1487
|
+
return firstDefined(
|
|
1488
|
+
callBridgeFunction(
|
|
1489
|
+
bridge,
|
|
1490
|
+
"getSafeArea" + suffix
|
|
1491
|
+
),
|
|
1492
|
+
bridge["__OASIZ_SAFE_AREA_" + side.toUpperCase() + "__"]
|
|
1493
|
+
);
|
|
1494
|
+
}
|
|
1495
|
+
function resolveInsetSide(bridge, sources, side) {
|
|
1496
|
+
const percentCandidate = firstDefined(
|
|
1497
|
+
readInsetObjectValue(sources.methodPercent, side, "percent"),
|
|
1498
|
+
readInsetObjectValue(sources.methodPercent, side),
|
|
1499
|
+
readInsetObjectValue(sources.globalPercent, side, "percent"),
|
|
1500
|
+
readInsetObjectValue(sources.globalPercent, side),
|
|
1501
|
+
readInsetObjectValue(sources.methodPixels, side, "percent"),
|
|
1502
|
+
readInsetObjectValue(sources.globalPixels, side, "percent"),
|
|
1503
|
+
readIndividualPercentValue(bridge, side)
|
|
1504
|
+
);
|
|
1505
|
+
const percent = resolvePercentValue(percentCandidate, bridge, side);
|
|
1506
|
+
if (typeof percent !== "undefined") {
|
|
1507
|
+
return {
|
|
1508
|
+
pixels: percentToPixelsOfViewport(percent, bridge, side),
|
|
1509
|
+
percent
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
const pixelCandidate = firstDefined(
|
|
1513
|
+
readInsetObjectValue(sources.methodPixels, side, "pixels"),
|
|
1514
|
+
readInsetObjectValue(sources.methodPixels, side),
|
|
1515
|
+
readInsetObjectValue(sources.globalPixels, side, "pixels"),
|
|
1516
|
+
readInsetObjectValue(sources.globalPixels, side),
|
|
1517
|
+
readIndividualPixelValue(bridge, side)
|
|
1518
|
+
);
|
|
1519
|
+
const pixels = resolvePixelValue(pixelCandidate, bridge, side);
|
|
1520
|
+
if (typeof pixels !== "undefined") {
|
|
1521
|
+
return {
|
|
1522
|
+
pixels,
|
|
1523
|
+
percent: pixelsToPercentOfViewport(pixels, bridge, side)
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
const cssPixels = readCssSafeAreaPixels(bridge, side);
|
|
1527
|
+
return {
|
|
1528
|
+
pixels: cssPixels,
|
|
1529
|
+
percent: pixelsToPercentOfViewport(cssPixels, bridge, side)
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
function getViewportInsets() {
|
|
1533
|
+
const bridge = getBridgeWindow8();
|
|
1534
|
+
if (!bridge) {
|
|
1535
|
+
return {
|
|
1536
|
+
pixels: createInsetEdges(0),
|
|
1537
|
+
percent: createInsetEdges(0)
|
|
1538
|
+
};
|
|
1539
|
+
}
|
|
1540
|
+
const sources = readHostInsetSources(bridge);
|
|
1541
|
+
const pixels = createInsetEdges(0);
|
|
1542
|
+
const percent = createInsetEdges(0);
|
|
1543
|
+
for (const side of INSET_SIDES) {
|
|
1544
|
+
const resolved = resolveInsetSide(bridge, sources, side);
|
|
1545
|
+
pixels[side] = resolved.pixels;
|
|
1546
|
+
percent[side] = resolved.percent;
|
|
231
1547
|
}
|
|
232
|
-
|
|
1548
|
+
return { pixels, percent };
|
|
233
1549
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
1550
|
+
function getSafeAreaTop() {
|
|
1551
|
+
const bridge = getBridgeWindow8();
|
|
1552
|
+
if (!bridge) {
|
|
1553
|
+
return 0;
|
|
1554
|
+
}
|
|
1555
|
+
const top = getViewportInsets().percent.top;
|
|
1556
|
+
if (top <= 0) {
|
|
1557
|
+
warnMissingBridge6("getSafeAreaTop");
|
|
1558
|
+
}
|
|
1559
|
+
return top;
|
|
239
1560
|
}
|
|
240
|
-
function
|
|
241
|
-
if (typeof
|
|
242
|
-
if (
|
|
1561
|
+
function setLeaderboardVisible(visible) {
|
|
1562
|
+
if (typeof visible !== "boolean") {
|
|
1563
|
+
if (isDevelopment9()) {
|
|
243
1564
|
console.warn(
|
|
244
|
-
"[oasiz/sdk]
|
|
1565
|
+
"[oasiz/sdk] setLeaderboardVisible expected a boolean:",
|
|
1566
|
+
visible
|
|
245
1567
|
);
|
|
246
1568
|
}
|
|
247
|
-
return
|
|
248
|
-
};
|
|
1569
|
+
return;
|
|
249
1570
|
}
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
function onResume(callback) {
|
|
258
|
-
return addLifecycleListener("oasiz:resume", callback);
|
|
1571
|
+
const bridge = getBridgeWindow8();
|
|
1572
|
+
if (typeof bridge?.__oasizSetLeaderboardVisible === "function") {
|
|
1573
|
+
bridge.__oasizSetLeaderboardVisible(visible);
|
|
1574
|
+
return;
|
|
1575
|
+
}
|
|
1576
|
+
warnMissingBridge6("__oasizSetLeaderboardVisible");
|
|
259
1577
|
}
|
|
260
1578
|
|
|
261
1579
|
// src/navigation.ts
|
|
1580
|
+
var BACK_BUTTON_TEST_STATE_KEY = "__oasizBackButtonTest";
|
|
262
1581
|
var activeBackListeners = 0;
|
|
263
|
-
|
|
1582
|
+
var activeBackButtonTestingHandle;
|
|
1583
|
+
function isDevelopment10() {
|
|
264
1584
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
265
1585
|
return nodeEnv !== "production";
|
|
266
1586
|
}
|
|
267
|
-
function
|
|
1587
|
+
function getBridgeWindow9() {
|
|
268
1588
|
if (typeof window === "undefined") {
|
|
269
1589
|
return void 0;
|
|
270
1590
|
}
|
|
271
1591
|
return window;
|
|
272
1592
|
}
|
|
273
|
-
function
|
|
274
|
-
if (
|
|
1593
|
+
function warnMissingBridge7(methodName) {
|
|
1594
|
+
if (isDevelopment10()) {
|
|
275
1595
|
console.warn(
|
|
276
1596
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
277
1597
|
);
|
|
@@ -285,9 +1605,19 @@ function normalizeNavigationError(error) {
|
|
|
285
1605
|
typeof error === "string" ? error : "Back button callback failed."
|
|
286
1606
|
);
|
|
287
1607
|
}
|
|
1608
|
+
function isRecord2(value) {
|
|
1609
|
+
return typeof value === "object" && value !== null;
|
|
1610
|
+
}
|
|
1611
|
+
function dispatchNavigationEvent(eventName) {
|
|
1612
|
+
const bridge = getBridgeWindow9();
|
|
1613
|
+
if (!bridge || typeof bridge.dispatchEvent !== "function") {
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
bridge.dispatchEvent(new Event(eventName));
|
|
1617
|
+
}
|
|
288
1618
|
function addNavigationListener(eventName, callback) {
|
|
289
1619
|
if (typeof window === "undefined") {
|
|
290
|
-
if (
|
|
1620
|
+
if (isDevelopment10()) {
|
|
291
1621
|
console.warn(
|
|
292
1622
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
293
1623
|
);
|
|
@@ -299,6 +1629,151 @@ function addNavigationListener(eventName, callback) {
|
|
|
299
1629
|
window.addEventListener(eventName, handler);
|
|
300
1630
|
return () => window.removeEventListener(eventName, handler);
|
|
301
1631
|
}
|
|
1632
|
+
function enableBackButtonTesting(options = {}) {
|
|
1633
|
+
activeBackButtonTestingHandle?.destroy();
|
|
1634
|
+
const bridge = getBridgeWindow9();
|
|
1635
|
+
if (!bridge) {
|
|
1636
|
+
if (isDevelopment10()) {
|
|
1637
|
+
console.warn(
|
|
1638
|
+
"[oasiz/sdk] enableBackButtonTesting requires a browser window."
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
return {
|
|
1642
|
+
destroy: () => {
|
|
1643
|
+
},
|
|
1644
|
+
isBackOverrideActive: () => false,
|
|
1645
|
+
triggerBack: () => {
|
|
1646
|
+
},
|
|
1647
|
+
triggerLeave: () => {
|
|
1648
|
+
}
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1651
|
+
const bridgeWindow = bridge;
|
|
1652
|
+
const keyboard = options.keyboard ?? true;
|
|
1653
|
+
const browserHistory = options.browserHistory ?? true;
|
|
1654
|
+
const log = options.log === true;
|
|
1655
|
+
const previousSetBackOverride = bridgeWindow.__oasizSetBackOverride;
|
|
1656
|
+
const previousLeaveGame = bridgeWindow.__oasizLeaveGame;
|
|
1657
|
+
let destroyed = false;
|
|
1658
|
+
let backOverrideActive = false;
|
|
1659
|
+
let historyTrapArmed = false;
|
|
1660
|
+
function maybeLog(message) {
|
|
1661
|
+
if (log) {
|
|
1662
|
+
console.info("[oasiz/sdk] " + message);
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
function canUseHistoryTrap() {
|
|
1666
|
+
return browserHistory && typeof bridgeWindow.history?.pushState === "function" && typeof bridgeWindow.history?.replaceState === "function" && typeof bridgeWindow.location?.href === "string";
|
|
1667
|
+
}
|
|
1668
|
+
function ensureHistoryTrap() {
|
|
1669
|
+
if (!backOverrideActive || historyTrapArmed || !canUseHistoryTrap()) {
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
try {
|
|
1673
|
+
const currentState = isRecord2(bridgeWindow.history.state) ? bridgeWindow.history.state : {};
|
|
1674
|
+
bridgeWindow.history.replaceState(
|
|
1675
|
+
{ ...currentState, [BACK_BUTTON_TEST_STATE_KEY]: "base" },
|
|
1676
|
+
"",
|
|
1677
|
+
bridgeWindow.location.href
|
|
1678
|
+
);
|
|
1679
|
+
bridgeWindow.history.pushState(
|
|
1680
|
+
{ [BACK_BUTTON_TEST_STATE_KEY]: "trap" },
|
|
1681
|
+
"",
|
|
1682
|
+
bridgeWindow.location.href
|
|
1683
|
+
);
|
|
1684
|
+
historyTrapArmed = true;
|
|
1685
|
+
maybeLog("Local browser Back testing is armed.");
|
|
1686
|
+
} catch (error) {
|
|
1687
|
+
historyTrapArmed = false;
|
|
1688
|
+
if (log) {
|
|
1689
|
+
console.warn("[oasiz/sdk] Failed to arm browser Back testing:", error);
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
function triggerBack() {
|
|
1694
|
+
dispatchNavigationEvent("oasiz:back");
|
|
1695
|
+
}
|
|
1696
|
+
function triggerLeave() {
|
|
1697
|
+
dispatchNavigationEvent("oasiz:leave");
|
|
1698
|
+
}
|
|
1699
|
+
function setBackOverride(active) {
|
|
1700
|
+
backOverrideActive = active;
|
|
1701
|
+
if (active) {
|
|
1702
|
+
ensureHistoryTrap();
|
|
1703
|
+
}
|
|
1704
|
+
if (typeof previousSetBackOverride === "function") {
|
|
1705
|
+
previousSetBackOverride(active);
|
|
1706
|
+
}
|
|
1707
|
+
maybeLog("Back override " + (active ? "enabled" : "disabled") + ".");
|
|
1708
|
+
}
|
|
1709
|
+
function stopBackEvent(event) {
|
|
1710
|
+
event.preventDefault();
|
|
1711
|
+
event.stopPropagation();
|
|
1712
|
+
event.stopImmediatePropagation?.();
|
|
1713
|
+
}
|
|
1714
|
+
const handleKeyDown = (event) => {
|
|
1715
|
+
if (!backOverrideActive || event.key !== "Escape") {
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
stopBackEvent(event);
|
|
1719
|
+
triggerBack();
|
|
1720
|
+
};
|
|
1721
|
+
const handlePopState = (event) => {
|
|
1722
|
+
if (!backOverrideActive) {
|
|
1723
|
+
historyTrapArmed = false;
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1726
|
+
stopBackEvent(event);
|
|
1727
|
+
triggerBack();
|
|
1728
|
+
historyTrapArmed = false;
|
|
1729
|
+
ensureHistoryTrap();
|
|
1730
|
+
};
|
|
1731
|
+
const testLeaveGame = () => {
|
|
1732
|
+
triggerLeave();
|
|
1733
|
+
if (typeof previousLeaveGame === "function") {
|
|
1734
|
+
previousLeaveGame();
|
|
1735
|
+
}
|
|
1736
|
+
};
|
|
1737
|
+
bridgeWindow.__oasizSetBackOverride = setBackOverride;
|
|
1738
|
+
bridgeWindow.__oasizLeaveGame = testLeaveGame;
|
|
1739
|
+
if (keyboard) {
|
|
1740
|
+
bridgeWindow.addEventListener("keydown", handleKeyDown);
|
|
1741
|
+
}
|
|
1742
|
+
if (browserHistory) {
|
|
1743
|
+
bridgeWindow.addEventListener("popstate", handlePopState);
|
|
1744
|
+
}
|
|
1745
|
+
if (activeBackListeners > 0) {
|
|
1746
|
+
setBackOverride(true);
|
|
1747
|
+
}
|
|
1748
|
+
maybeLog("Back button testing bridge installed.");
|
|
1749
|
+
const handle = {
|
|
1750
|
+
destroy: () => {
|
|
1751
|
+
if (destroyed) return;
|
|
1752
|
+
destroyed = true;
|
|
1753
|
+
if (keyboard) {
|
|
1754
|
+
bridgeWindow.removeEventListener("keydown", handleKeyDown);
|
|
1755
|
+
}
|
|
1756
|
+
if (browserHistory) {
|
|
1757
|
+
bridgeWindow.removeEventListener("popstate", handlePopState);
|
|
1758
|
+
}
|
|
1759
|
+
if (bridgeWindow.__oasizSetBackOverride === setBackOverride) {
|
|
1760
|
+
bridgeWindow.__oasizSetBackOverride = previousSetBackOverride;
|
|
1761
|
+
}
|
|
1762
|
+
if (bridgeWindow.__oasizLeaveGame === testLeaveGame) {
|
|
1763
|
+
bridgeWindow.__oasizLeaveGame = previousLeaveGame;
|
|
1764
|
+
}
|
|
1765
|
+
if (activeBackButtonTestingHandle === handle) {
|
|
1766
|
+
activeBackButtonTestingHandle = void 0;
|
|
1767
|
+
}
|
|
1768
|
+
maybeLog("Back button testing bridge removed.");
|
|
1769
|
+
},
|
|
1770
|
+
isBackOverrideActive: () => backOverrideActive,
|
|
1771
|
+
triggerBack,
|
|
1772
|
+
triggerLeave
|
|
1773
|
+
};
|
|
1774
|
+
activeBackButtonTestingHandle = handle;
|
|
1775
|
+
return handle;
|
|
1776
|
+
}
|
|
302
1777
|
function onBackButton(callback) {
|
|
303
1778
|
const off = addNavigationListener("oasiz:back", () => {
|
|
304
1779
|
try {
|
|
@@ -308,24 +1783,24 @@ function onBackButton(callback) {
|
|
|
308
1783
|
throw normalizeNavigationError(error);
|
|
309
1784
|
}
|
|
310
1785
|
});
|
|
311
|
-
const bridge =
|
|
1786
|
+
const bridge = getBridgeWindow9();
|
|
312
1787
|
activeBackListeners += 1;
|
|
313
1788
|
if (activeBackListeners === 1) {
|
|
314
1789
|
if (typeof bridge?.__oasizSetBackOverride === "function") {
|
|
315
1790
|
bridge.__oasizSetBackOverride(true);
|
|
316
1791
|
} else {
|
|
317
|
-
|
|
1792
|
+
warnMissingBridge7("__oasizSetBackOverride");
|
|
318
1793
|
}
|
|
319
1794
|
}
|
|
320
1795
|
return () => {
|
|
321
1796
|
off();
|
|
322
1797
|
activeBackListeners = Math.max(0, activeBackListeners - 1);
|
|
323
1798
|
if (activeBackListeners === 0) {
|
|
324
|
-
const currentBridge =
|
|
1799
|
+
const currentBridge = getBridgeWindow9();
|
|
325
1800
|
if (typeof currentBridge?.__oasizSetBackOverride === "function") {
|
|
326
1801
|
currentBridge.__oasizSetBackOverride(false);
|
|
327
1802
|
} else {
|
|
328
|
-
|
|
1803
|
+
warnMissingBridge7("__oasizSetBackOverride");
|
|
329
1804
|
}
|
|
330
1805
|
}
|
|
331
1806
|
};
|
|
@@ -334,176 +1809,413 @@ function onLeaveGame(callback) {
|
|
|
334
1809
|
return addNavigationListener("oasiz:leave", callback);
|
|
335
1810
|
}
|
|
336
1811
|
function leaveGame() {
|
|
337
|
-
const bridge =
|
|
1812
|
+
const bridge = getBridgeWindow9();
|
|
338
1813
|
if (typeof bridge?.__oasizLeaveGame === "function") {
|
|
339
1814
|
bridge.__oasizLeaveGame();
|
|
340
1815
|
return;
|
|
341
1816
|
}
|
|
342
|
-
|
|
1817
|
+
warnMissingBridge7("__oasizLeaveGame");
|
|
343
1818
|
}
|
|
344
1819
|
|
|
345
|
-
// src/
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
}
|
|
350
|
-
|
|
1820
|
+
// src/performance.ts
|
|
1821
|
+
var DEFAULT_GRAPHICS_PERFORMANCE = {
|
|
1822
|
+
fps: 45,
|
|
1823
|
+
tier: "medium"
|
|
1824
|
+
};
|
|
1825
|
+
var TIER_DEFAULT_FPS = {
|
|
1826
|
+
minimal: 24,
|
|
1827
|
+
low: 30,
|
|
1828
|
+
medium: 45,
|
|
1829
|
+
high: 60
|
|
1830
|
+
};
|
|
1831
|
+
var cachedEstimatedGraphicsPerformance;
|
|
1832
|
+
function getBridgeWindow10() {
|
|
351
1833
|
if (typeof window === "undefined") {
|
|
352
1834
|
return void 0;
|
|
353
1835
|
}
|
|
354
1836
|
return window;
|
|
355
1837
|
}
|
|
356
|
-
function
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
1838
|
+
function isRecord3(value) {
|
|
1839
|
+
return typeof value === "object" && value !== null;
|
|
1840
|
+
}
|
|
1841
|
+
function toFiniteNumber2(value) {
|
|
1842
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1843
|
+
return value;
|
|
1844
|
+
}
|
|
1845
|
+
if (typeof value === "string") {
|
|
1846
|
+
const parsed = Number.parseFloat(value.trim());
|
|
1847
|
+
if (Number.isFinite(parsed)) {
|
|
1848
|
+
return parsed;
|
|
1849
|
+
}
|
|
361
1850
|
}
|
|
1851
|
+
return void 0;
|
|
362
1852
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
1853
|
+
function clampScore(value) {
|
|
1854
|
+
return Math.min(100, Math.max(0, Math.round(value)));
|
|
1855
|
+
}
|
|
1856
|
+
function clampFps(value) {
|
|
1857
|
+
return Math.min(240, Math.max(1, Math.round(value)));
|
|
1858
|
+
}
|
|
1859
|
+
function tierFromScore(score) {
|
|
1860
|
+
if (score < 25) return "minimal";
|
|
1861
|
+
if (score < 40) return "low";
|
|
1862
|
+
if (score < 70) return "medium";
|
|
1863
|
+
return "high";
|
|
1864
|
+
}
|
|
1865
|
+
function tierFromFps(fps) {
|
|
1866
|
+
if (fps < 30) return "minimal";
|
|
1867
|
+
if (fps < 45) return "low";
|
|
1868
|
+
if (fps < 58) return "medium";
|
|
1869
|
+
return "high";
|
|
1870
|
+
}
|
|
1871
|
+
function fpsFromScore(score) {
|
|
1872
|
+
return TIER_DEFAULT_FPS[tierFromScore(score)];
|
|
1873
|
+
}
|
|
1874
|
+
function normalizeTier(value) {
|
|
1875
|
+
if (typeof value !== "string") {
|
|
1876
|
+
return void 0;
|
|
368
1877
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
1878
|
+
const normalized = value.trim().toLowerCase();
|
|
1879
|
+
if (normalized === "minimal" || normalized === "safe") return "minimal";
|
|
1880
|
+
if (normalized === "high") return "high";
|
|
1881
|
+
if (normalized === "medium") return "medium";
|
|
1882
|
+
if (normalized === "low") return "low";
|
|
1883
|
+
return void 0;
|
|
373
1884
|
}
|
|
374
|
-
|
|
375
|
-
return
|
|
1885
|
+
function firstDefined2(...values) {
|
|
1886
|
+
return values.find((value) => typeof value !== "undefined");
|
|
376
1887
|
}
|
|
377
|
-
function
|
|
378
|
-
if (typeof
|
|
379
|
-
return
|
|
380
|
-
};
|
|
1888
|
+
function normalizeMetric(value) {
|
|
1889
|
+
if (typeof value === "undefined" || value === null) {
|
|
1890
|
+
return void 0;
|
|
381
1891
|
}
|
|
382
|
-
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
1892
|
+
if (typeof value === "number" || typeof value === "string") {
|
|
1893
|
+
const numeric = toFiniteNumber2(value);
|
|
1894
|
+
if (typeof numeric !== "undefined") {
|
|
1895
|
+
const fps2 = clampFps(numeric);
|
|
1896
|
+
return { fps: fps2, tier: tierFromFps(fps2) };
|
|
1897
|
+
}
|
|
1898
|
+
const tier2 = normalizeTier(value);
|
|
1899
|
+
if (tier2) {
|
|
1900
|
+
return { fps: TIER_DEFAULT_FPS[tier2], tier: tier2 };
|
|
1901
|
+
}
|
|
1902
|
+
return void 0;
|
|
1903
|
+
}
|
|
1904
|
+
if (!isRecord3(value)) {
|
|
1905
|
+
return void 0;
|
|
1906
|
+
}
|
|
1907
|
+
const fpsCandidate = firstDefined2(
|
|
1908
|
+
value.fps,
|
|
1909
|
+
value.targetFps,
|
|
1910
|
+
value.frameRate,
|
|
1911
|
+
value.framesPerSecond
|
|
1912
|
+
);
|
|
1913
|
+
const legacyScoreCandidate = firstDefined2(
|
|
1914
|
+
value.score,
|
|
1915
|
+
value.metric,
|
|
1916
|
+
value.value,
|
|
1917
|
+
value.performance,
|
|
1918
|
+
value.performanceScore,
|
|
1919
|
+
value.graphicsScore
|
|
1920
|
+
);
|
|
1921
|
+
const tierCandidate = firstDefined2(
|
|
1922
|
+
value.tier,
|
|
1923
|
+
value.graphicsTier,
|
|
1924
|
+
value.performanceTier,
|
|
1925
|
+
value.qualityTier,
|
|
1926
|
+
value.recommendedTier
|
|
1927
|
+
);
|
|
1928
|
+
const tier = normalizeTier(tierCandidate);
|
|
1929
|
+
const fpsNumeric = toFiniteNumber2(fpsCandidate);
|
|
1930
|
+
const scoreNumeric = toFiniteNumber2(legacyScoreCandidate);
|
|
1931
|
+
if (typeof fpsNumeric === "undefined" && typeof scoreNumeric === "undefined" && !tier) {
|
|
1932
|
+
return void 0;
|
|
1933
|
+
}
|
|
1934
|
+
const fps = clampFps(
|
|
1935
|
+
typeof fpsNumeric !== "undefined" ? fpsNumeric : typeof scoreNumeric !== "undefined" ? fpsFromScore(clampScore(scoreNumeric)) : TIER_DEFAULT_FPS[tier]
|
|
1936
|
+
);
|
|
1937
|
+
return {
|
|
1938
|
+
fps,
|
|
1939
|
+
tier: tier ?? tierFromFps(fps)
|
|
389
1940
|
};
|
|
390
1941
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
}
|
|
1942
|
+
function callBridgeMetric(bridge, name) {
|
|
1943
|
+
const fn = bridge[name];
|
|
1944
|
+
if (typeof fn !== "function") {
|
|
1945
|
+
return void 0;
|
|
1946
|
+
}
|
|
1947
|
+
try {
|
|
1948
|
+
return fn.call(bridge);
|
|
1949
|
+
} catch (error) {
|
|
1950
|
+
console.error("[oasiz/sdk] " + String(name) + " failed:", error);
|
|
1951
|
+
return void 0;
|
|
1952
|
+
}
|
|
396
1953
|
}
|
|
397
|
-
|
|
398
|
-
const
|
|
399
|
-
|
|
1954
|
+
function readHostGraphicsPerformance(bridge) {
|
|
1955
|
+
const candidates = [
|
|
1956
|
+
callBridgeMetric(bridge, "getGraphicsPerformance"),
|
|
1957
|
+
callBridgeMetric(bridge, "getGraphicsPerformanceMetric"),
|
|
1958
|
+
callBridgeMetric(bridge, "getPerformanceMetric"),
|
|
1959
|
+
bridge.__OASIZ_GRAPHICS_PERFORMANCE__,
|
|
1960
|
+
bridge.__OASIZ_PERFORMANCE_METRIC__
|
|
1961
|
+
];
|
|
1962
|
+
for (const candidate of candidates) {
|
|
1963
|
+
const metric = normalizeMetric(candidate);
|
|
1964
|
+
if (metric) {
|
|
1965
|
+
return metric;
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
return void 0;
|
|
400
1969
|
}
|
|
401
|
-
|
|
402
|
-
const
|
|
403
|
-
return
|
|
1970
|
+
function getDevicePixelRatio2(bridge) {
|
|
1971
|
+
const dpr = bridge.devicePixelRatio;
|
|
1972
|
+
return typeof dpr === "number" && Number.isFinite(dpr) && dpr > 0 ? dpr : 1;
|
|
404
1973
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return state.entitlements.find((item) => item.productId === productId)?.owned === true;
|
|
1974
|
+
function getNavigatorValue(bridge) {
|
|
1975
|
+
return bridge.navigator;
|
|
408
1976
|
}
|
|
409
|
-
|
|
410
|
-
const
|
|
411
|
-
|
|
1977
|
+
function parseIosMajorVersion(userAgent) {
|
|
1978
|
+
const match = /\bOS (\d+)_/i.exec(userAgent);
|
|
1979
|
+
if (!match) {
|
|
1980
|
+
return void 0;
|
|
1981
|
+
}
|
|
1982
|
+
const parsed = Number.parseInt(match[1] ?? "", 10);
|
|
1983
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
412
1984
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
quantity
|
|
417
|
-
});
|
|
1985
|
+
function isAppleMobileDevice(bridge) {
|
|
1986
|
+
const userAgent = bridge.navigator?.userAgent ?? "";
|
|
1987
|
+
return /iP(hone|ad|od)/i.test(userAgent) || /Macintosh/i.test(userAgent) && (bridge.navigator?.maxTouchPoints ?? 0) > 1;
|
|
418
1988
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
1989
|
+
function getLongestScreenEdge(bridge) {
|
|
1990
|
+
const screenWidth = bridge.screen?.width;
|
|
1991
|
+
const screenHeight = bridge.screen?.height;
|
|
1992
|
+
const innerWidth = bridge.innerWidth;
|
|
1993
|
+
const innerHeight = bridge.innerHeight;
|
|
1994
|
+
return Math.max(
|
|
1995
|
+
typeof screenWidth === "number" ? screenWidth : 0,
|
|
1996
|
+
typeof screenHeight === "number" ? screenHeight : 0,
|
|
1997
|
+
typeof innerWidth === "number" ? innerWidth : 0,
|
|
1998
|
+
typeof innerHeight === "number" ? innerHeight : 0
|
|
1999
|
+
);
|
|
424
2000
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
2001
|
+
function isCoarsePointer(bridge) {
|
|
2002
|
+
try {
|
|
2003
|
+
return bridge.matchMedia?.("(pointer: coarse)").matches === true;
|
|
2004
|
+
} catch {
|
|
2005
|
+
return false;
|
|
2006
|
+
}
|
|
428
2007
|
}
|
|
429
|
-
function
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
2008
|
+
function getWebGlInfo(bridge) {
|
|
2009
|
+
const canvas = bridge.document?.createElement?.("canvas");
|
|
2010
|
+
if (!canvas || typeof canvas.getContext !== "function") {
|
|
2011
|
+
return { webglVersion: 0 };
|
|
2012
|
+
}
|
|
2013
|
+
const gl2 = canvas.getContext("webgl2");
|
|
2014
|
+
const gl = gl2 ?? canvas.getContext("webgl") ?? canvas.getContext("experimental-webgl");
|
|
2015
|
+
if (!gl) {
|
|
2016
|
+
return { webglVersion: 0 };
|
|
2017
|
+
}
|
|
2018
|
+
const context = gl;
|
|
2019
|
+
let maxTextureSize;
|
|
2020
|
+
let renderer;
|
|
2021
|
+
try {
|
|
2022
|
+
const value = context.getParameter(context.MAX_TEXTURE_SIZE);
|
|
2023
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2024
|
+
maxTextureSize = value;
|
|
2025
|
+
}
|
|
2026
|
+
} catch {
|
|
2027
|
+
}
|
|
2028
|
+
try {
|
|
2029
|
+
const debugInfo = context.getExtension("WEBGL_debug_renderer_info");
|
|
2030
|
+
const rendererParam = debugInfo?.UNMASKED_RENDERER_WEBGL ?? context.RENDERER;
|
|
2031
|
+
const value = context.getParameter(rendererParam);
|
|
2032
|
+
if (typeof value === "string") {
|
|
2033
|
+
renderer = value;
|
|
2034
|
+
}
|
|
2035
|
+
} catch {
|
|
2036
|
+
}
|
|
2037
|
+
return {
|
|
2038
|
+
maxTextureSize,
|
|
2039
|
+
renderer,
|
|
2040
|
+
webglVersion: gl2 ? 2 : 1
|
|
2041
|
+
};
|
|
433
2042
|
}
|
|
434
|
-
function
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
}
|
|
2043
|
+
function applyMemoryScore(score, memory) {
|
|
2044
|
+
if (typeof memory !== "number" || !Number.isFinite(memory) || memory <= 0) {
|
|
2045
|
+
return score;
|
|
2046
|
+
}
|
|
2047
|
+
if (memory <= 1) return score - 18;
|
|
2048
|
+
if (memory <= 2) return score - 10;
|
|
2049
|
+
if (memory >= 8) return score + 16;
|
|
2050
|
+
if (memory >= 6) return score + 10;
|
|
2051
|
+
return score;
|
|
2052
|
+
}
|
|
2053
|
+
function applyCoreScore(score, cores) {
|
|
2054
|
+
if (typeof cores !== "number" || !Number.isFinite(cores) || cores <= 0) {
|
|
2055
|
+
return score;
|
|
2056
|
+
}
|
|
2057
|
+
if (cores <= 2) return score - 12;
|
|
2058
|
+
if (cores <= 4) return score;
|
|
2059
|
+
if (cores >= 8) return score + 12;
|
|
2060
|
+
return score + 8;
|
|
2061
|
+
}
|
|
2062
|
+
function applyWebGlScore(score, info) {
|
|
2063
|
+
let next = score;
|
|
2064
|
+
if (info.webglVersion === 2) {
|
|
2065
|
+
next += 16;
|
|
2066
|
+
} else if (info.webglVersion === 1) {
|
|
2067
|
+
next += 6;
|
|
2068
|
+
} else {
|
|
2069
|
+
next -= 25;
|
|
2070
|
+
}
|
|
2071
|
+
if (typeof info.maxTextureSize === "number") {
|
|
2072
|
+
if (info.maxTextureSize >= 8192) next += 10;
|
|
2073
|
+
else if (info.maxTextureSize >= 4096) next += 3;
|
|
2074
|
+
else next -= 8;
|
|
2075
|
+
}
|
|
2076
|
+
const renderer = info.renderer?.toLowerCase() ?? "";
|
|
2077
|
+
if (/swiftshader|llvmpipe|software/.test(renderer)) {
|
|
2078
|
+
next = Math.min(next, 35);
|
|
2079
|
+
} else if (/\bm[1-9]\b|apple gpu|a1[6-9]|rtx|radeon|adreno 7|adreno 8/.test(renderer)) {
|
|
2080
|
+
next += 8;
|
|
2081
|
+
}
|
|
2082
|
+
return next;
|
|
2083
|
+
}
|
|
2084
|
+
function applyMobileCostScore(score, bridge) {
|
|
2085
|
+
if (!isCoarsePointer(bridge)) {
|
|
2086
|
+
return score;
|
|
2087
|
+
}
|
|
2088
|
+
const dpr = getDevicePixelRatio2(bridge);
|
|
2089
|
+
const width = bridge.screen?.width ?? bridge.innerWidth ?? 0;
|
|
2090
|
+
const height = bridge.screen?.height ?? bridge.innerHeight ?? 0;
|
|
2091
|
+
const physicalPixels = width * height * dpr * dpr;
|
|
2092
|
+
if (physicalPixels > 4e6) {
|
|
2093
|
+
return score - 5;
|
|
2094
|
+
}
|
|
2095
|
+
return score;
|
|
2096
|
+
}
|
|
2097
|
+
function applyAppleMobileRules(score, bridge) {
|
|
2098
|
+
if (!isAppleMobileDevice(bridge)) {
|
|
2099
|
+
return score;
|
|
2100
|
+
}
|
|
2101
|
+
const userAgent = bridge.navigator?.userAgent ?? "";
|
|
2102
|
+
const iosMajorVersion = parseIosMajorVersion(userAgent);
|
|
2103
|
+
const highDensityDisplay = getDevicePixelRatio2(bridge) >= 3;
|
|
2104
|
+
const longestScreenEdge = getLongestScreenEdge(bridge);
|
|
2105
|
+
if (typeof iosMajorVersion === "number" && iosMajorVersion < 15) {
|
|
2106
|
+
return Math.min(score, 35);
|
|
2107
|
+
}
|
|
2108
|
+
if (highDensityDisplay && longestScreenEdge >= 430 && (typeof iosMajorVersion === "undefined" || iosMajorVersion >= 17)) {
|
|
2109
|
+
return Math.max(score, 78);
|
|
2110
|
+
}
|
|
2111
|
+
if (highDensityDisplay && longestScreenEdge >= 414 && (typeof iosMajorVersion === "undefined" || iosMajorVersion >= 16)) {
|
|
2112
|
+
return Math.max(score, 62);
|
|
2113
|
+
}
|
|
2114
|
+
return Math.min(score, 48);
|
|
2115
|
+
}
|
|
2116
|
+
function estimateGraphicsPerformance(bridge) {
|
|
2117
|
+
const navigatorValue = getNavigatorValue(bridge);
|
|
2118
|
+
let score = 45;
|
|
2119
|
+
score = applyMemoryScore(score, navigatorValue?.deviceMemory);
|
|
2120
|
+
score = applyCoreScore(score, navigatorValue?.hardwareConcurrency);
|
|
2121
|
+
score = applyWebGlScore(score, getWebGlInfo(bridge));
|
|
2122
|
+
score = applyMobileCostScore(score, bridge);
|
|
2123
|
+
score = applyAppleMobileRules(score, bridge);
|
|
2124
|
+
const normalizedScore = clampScore(score);
|
|
2125
|
+
return {
|
|
2126
|
+
fps: fpsFromScore(normalizedScore),
|
|
2127
|
+
tier: tierFromScore(normalizedScore)
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2130
|
+
function getGraphicsPerformance() {
|
|
2131
|
+
const bridge = getBridgeWindow10();
|
|
2132
|
+
if (!bridge) {
|
|
2133
|
+
return { ...DEFAULT_GRAPHICS_PERFORMANCE };
|
|
2134
|
+
}
|
|
2135
|
+
const hostMetric = readHostGraphicsPerformance(bridge);
|
|
2136
|
+
if (hostMetric) {
|
|
2137
|
+
return hostMetric;
|
|
2138
|
+
}
|
|
2139
|
+
cachedEstimatedGraphicsPerformance ??= estimateGraphicsPerformance(bridge);
|
|
2140
|
+
return { ...cachedEstimatedGraphicsPerformance };
|
|
438
2141
|
}
|
|
439
2142
|
|
|
440
2143
|
// src/index.ts
|
|
441
2144
|
var oasiz = {
|
|
442
2145
|
submitScore,
|
|
443
|
-
|
|
2146
|
+
addScore,
|
|
2147
|
+
setScore,
|
|
2148
|
+
getPlayerCharacter,
|
|
444
2149
|
share,
|
|
445
2150
|
triggerHaptic,
|
|
2151
|
+
enableLogOverlay,
|
|
446
2152
|
loadGameState,
|
|
447
2153
|
saveGameState,
|
|
448
2154
|
flushGameState,
|
|
449
2155
|
shareRoomCode,
|
|
2156
|
+
openInviteModal,
|
|
450
2157
|
onPause,
|
|
451
2158
|
onResume,
|
|
2159
|
+
getSafeAreaTop,
|
|
2160
|
+
getViewportInsets,
|
|
2161
|
+
setLeaderboardVisible,
|
|
2162
|
+
getGraphicsPerformance,
|
|
2163
|
+
enableBackButtonTesting,
|
|
452
2164
|
onBackButton,
|
|
453
2165
|
onLeaveGame,
|
|
454
2166
|
leaveGame,
|
|
455
|
-
store: {
|
|
456
|
-
syncProducts,
|
|
457
|
-
getProducts,
|
|
458
|
-
getEntitlements,
|
|
459
|
-
hasEntitlement,
|
|
460
|
-
getQuantity,
|
|
461
|
-
purchase,
|
|
462
|
-
consume,
|
|
463
|
-
getJemBalance,
|
|
464
|
-
onEntitlementsChanged,
|
|
465
|
-
onJemBalanceChanged
|
|
466
|
-
},
|
|
467
2167
|
get gameId() {
|
|
468
2168
|
return getGameId();
|
|
469
2169
|
},
|
|
470
2170
|
get roomCode() {
|
|
471
2171
|
return getRoomCode();
|
|
472
2172
|
},
|
|
2173
|
+
get playerId() {
|
|
2174
|
+
return getPlayerId();
|
|
2175
|
+
},
|
|
473
2176
|
get playerName() {
|
|
474
2177
|
return getPlayerName();
|
|
475
2178
|
},
|
|
476
2179
|
get playerAvatar() {
|
|
477
2180
|
return getPlayerAvatar();
|
|
2181
|
+
},
|
|
2182
|
+
get safeAreaTop() {
|
|
2183
|
+
return getSafeAreaTop();
|
|
2184
|
+
},
|
|
2185
|
+
get viewportInsets() {
|
|
2186
|
+
return getViewportInsets();
|
|
2187
|
+
},
|
|
2188
|
+
get graphicsPerformance() {
|
|
2189
|
+
return getGraphicsPerformance();
|
|
478
2190
|
}
|
|
479
2191
|
};
|
|
480
2192
|
export {
|
|
481
|
-
|
|
482
|
-
|
|
2193
|
+
addScore,
|
|
2194
|
+
enableBackButtonTesting,
|
|
2195
|
+
enableLogOverlay,
|
|
483
2196
|
flushGameState,
|
|
484
|
-
getEntitlements,
|
|
485
2197
|
getGameId,
|
|
486
|
-
|
|
2198
|
+
getGraphicsPerformance,
|
|
487
2199
|
getPlayerAvatar,
|
|
2200
|
+
getPlayerCharacter,
|
|
2201
|
+
getPlayerId,
|
|
488
2202
|
getPlayerName,
|
|
489
|
-
getProducts,
|
|
490
|
-
getQuantity,
|
|
491
2203
|
getRoomCode,
|
|
492
|
-
|
|
2204
|
+
getSafeAreaTop,
|
|
2205
|
+
getViewportInsets,
|
|
493
2206
|
leaveGame,
|
|
494
2207
|
loadGameState,
|
|
495
2208
|
oasiz,
|
|
496
2209
|
onBackButton,
|
|
497
|
-
onEntitlementsChanged,
|
|
498
|
-
onJemBalanceChanged,
|
|
499
2210
|
onLeaveGame,
|
|
500
2211
|
onPause,
|
|
501
2212
|
onResume,
|
|
502
|
-
|
|
2213
|
+
openInviteModal,
|
|
503
2214
|
saveGameState,
|
|
2215
|
+
setLeaderboardVisible,
|
|
2216
|
+
setScore,
|
|
504
2217
|
share,
|
|
505
2218
|
shareRoomCode,
|
|
506
2219
|
submitScore,
|
|
507
|
-
syncProducts,
|
|
508
2220
|
triggerHaptic
|
|
509
2221
|
};
|