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