@oasiz/sdk 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -464
- package/dist/index.cjs +231 -1943
- package/dist/index.d.cts +102 -248
- package/dist/index.d.ts +102 -248
- package/dist/index.js +220 -1932
- package/package.json +4 -14
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
|
-
|
|
25
|
-
enableLogOverlay: () => enableLogOverlay,
|
|
23
|
+
consume: () => consume,
|
|
24
|
+
emitScoreConfig: () => emitScoreConfig,
|
|
26
25
|
flushGameState: () => flushGameState,
|
|
26
|
+
getEntitlements: () => getEntitlements,
|
|
27
27
|
getGameId: () => getGameId,
|
|
28
|
-
|
|
28
|
+
getJemBalance: () => getJemBalance,
|
|
29
29
|
getPlayerAvatar: () => getPlayerAvatar,
|
|
30
|
-
getPlayerCharacter: () => getPlayerCharacter,
|
|
31
|
-
getPlayerId: () => getPlayerId,
|
|
32
30
|
getPlayerName: () => getPlayerName,
|
|
31
|
+
getProducts: () => getProducts,
|
|
32
|
+
getQuantity: () => getQuantity,
|
|
33
33
|
getRoomCode: () => getRoomCode,
|
|
34
|
-
|
|
35
|
-
getViewportInsets: () => getViewportInsets,
|
|
34
|
+
hasEntitlement: () => hasEntitlement,
|
|
36
35
|
leaveGame: () => leaveGame,
|
|
37
36
|
loadGameState: () => loadGameState,
|
|
38
37
|
oasiz: () => oasiz,
|
|
39
38
|
onBackButton: () => onBackButton,
|
|
39
|
+
onEntitlementsChanged: () => onEntitlementsChanged,
|
|
40
|
+
onJemBalanceChanged: () => onJemBalanceChanged,
|
|
40
41
|
onLeaveGame: () => onLeaveGame,
|
|
41
42
|
onPause: () => onPause,
|
|
42
43
|
onResume: () => onResume,
|
|
43
|
-
|
|
44
|
+
purchase: () => purchase,
|
|
44
45
|
saveGameState: () => saveGameState,
|
|
45
|
-
setLeaderboardVisible: () => setLeaderboardVisible,
|
|
46
|
-
setScore: () => setScore,
|
|
47
46
|
share: () => share,
|
|
48
47
|
shareRoomCode: () => shareRoomCode,
|
|
49
48
|
submitScore: () => submitScore,
|
|
49
|
+
syncProducts: () => syncProducts,
|
|
50
50
|
triggerHaptic: () => triggerHaptic
|
|
51
51
|
});
|
|
52
52
|
module.exports = __toCommonJS(index_exports);
|
|
53
53
|
|
|
54
|
-
// src/
|
|
54
|
+
// src/haptics.ts
|
|
55
55
|
function isDevelopment() {
|
|
56
56
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
57
57
|
return nodeEnv !== "production";
|
|
@@ -62,1014 +62,72 @@ function getBridgeWindow() {
|
|
|
62
62
|
}
|
|
63
63
|
return window;
|
|
64
64
|
}
|
|
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() {
|
|
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
65
|
function triggerHaptic(type) {
|
|
101
|
-
const bridge =
|
|
66
|
+
const bridge = getBridgeWindow();
|
|
102
67
|
if (typeof bridge?.triggerHaptic === "function") {
|
|
103
68
|
bridge.triggerHaptic(type);
|
|
104
69
|
return;
|
|
105
70
|
}
|
|
106
|
-
if (
|
|
71
|
+
if (isDevelopment()) {
|
|
107
72
|
console.warn(
|
|
108
73
|
"[oasiz/sdk] triggerHaptic bridge is unavailable. This is expected in local development."
|
|
109
74
|
);
|
|
110
75
|
}
|
|
111
76
|
}
|
|
112
77
|
|
|
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
|
-
|
|
1004
78
|
// src/multiplayer.ts
|
|
1005
|
-
function
|
|
79
|
+
function isDevelopment2() {
|
|
1006
80
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1007
81
|
return nodeEnv !== "production";
|
|
1008
82
|
}
|
|
1009
|
-
function
|
|
83
|
+
function getBridgeWindow2() {
|
|
1010
84
|
if (typeof window === "undefined") {
|
|
1011
85
|
return void 0;
|
|
1012
86
|
}
|
|
1013
87
|
return window;
|
|
1014
88
|
}
|
|
1015
|
-
function shareRoomCode(roomCode
|
|
1016
|
-
const bridge =
|
|
89
|
+
function shareRoomCode(roomCode) {
|
|
90
|
+
const bridge = getBridgeWindow2();
|
|
1017
91
|
if (typeof bridge?.shareRoomCode === "function") {
|
|
1018
|
-
bridge.shareRoomCode(roomCode
|
|
92
|
+
bridge.shareRoomCode(roomCode);
|
|
1019
93
|
return;
|
|
1020
94
|
}
|
|
1021
|
-
if (
|
|
95
|
+
if (isDevelopment2()) {
|
|
1022
96
|
console.warn(
|
|
1023
97
|
"[oasiz/sdk] shareRoomCode bridge is unavailable. This is expected in local development."
|
|
1024
98
|
);
|
|
1025
99
|
}
|
|
1026
100
|
}
|
|
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
|
-
}
|
|
1039
101
|
function getGameId() {
|
|
1040
|
-
const bridge =
|
|
102
|
+
const bridge = getBridgeWindow2();
|
|
1041
103
|
return bridge?.__GAME_ID__;
|
|
1042
104
|
}
|
|
1043
105
|
function getRoomCode() {
|
|
1044
|
-
const bridge =
|
|
106
|
+
const bridge = getBridgeWindow2();
|
|
1045
107
|
return bridge?.__ROOM_CODE__;
|
|
1046
108
|
}
|
|
1047
|
-
function getPlayerId() {
|
|
1048
|
-
const bridge = getBridgeWindow3();
|
|
1049
|
-
return bridge?.__PLAYER_ID__;
|
|
1050
|
-
}
|
|
1051
109
|
function getPlayerName() {
|
|
1052
|
-
const bridge =
|
|
110
|
+
const bridge = getBridgeWindow2();
|
|
1053
111
|
return bridge?.__PLAYER_NAME__;
|
|
1054
112
|
}
|
|
1055
113
|
function getPlayerAvatar() {
|
|
1056
|
-
const bridge =
|
|
114
|
+
const bridge = getBridgeWindow2();
|
|
1057
115
|
return bridge?.__PLAYER_AVATAR__;
|
|
1058
116
|
}
|
|
1059
117
|
|
|
1060
118
|
// src/score.ts
|
|
1061
|
-
function
|
|
119
|
+
function isDevelopment3() {
|
|
1062
120
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1063
121
|
return nodeEnv !== "production";
|
|
1064
122
|
}
|
|
1065
|
-
function
|
|
1066
|
-
if (
|
|
123
|
+
function warnMissingBridge(methodName) {
|
|
124
|
+
if (isDevelopment3()) {
|
|
1067
125
|
console.warn(
|
|
1068
126
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1069
127
|
);
|
|
1070
128
|
}
|
|
1071
129
|
}
|
|
1072
|
-
function
|
|
130
|
+
function getBridgeWindow3() {
|
|
1073
131
|
if (typeof window === "undefined") {
|
|
1074
132
|
return void 0;
|
|
1075
133
|
}
|
|
@@ -1077,92 +135,41 @@ function getBridgeWindow4() {
|
|
|
1077
135
|
}
|
|
1078
136
|
function submitScore(score) {
|
|
1079
137
|
if (!Number.isFinite(score)) {
|
|
1080
|
-
if (
|
|
138
|
+
if (isDevelopment3()) {
|
|
1081
139
|
console.warn("[oasiz/sdk] submitScore expected a finite number:", score);
|
|
1082
140
|
}
|
|
1083
141
|
return;
|
|
1084
142
|
}
|
|
1085
|
-
const bridge =
|
|
143
|
+
const bridge = getBridgeWindow3();
|
|
1086
144
|
const normalizedScore = Math.max(0, Math.floor(score));
|
|
1087
145
|
if (typeof bridge?.submitScore === "function") {
|
|
1088
146
|
bridge.submitScore(normalizedScore);
|
|
1089
147
|
return;
|
|
1090
148
|
}
|
|
1091
|
-
|
|
149
|
+
warnMissingBridge("submitScore");
|
|
1092
150
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
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;
|
|
1126
|
-
}
|
|
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;
|
|
151
|
+
function emitScoreConfig(config) {
|
|
152
|
+
const bridge = getBridgeWindow3();
|
|
153
|
+
if (typeof bridge?.emitScoreConfig === "function") {
|
|
154
|
+
bridge.emitScoreConfig(config);
|
|
155
|
+
return;
|
|
1149
156
|
}
|
|
1150
|
-
|
|
157
|
+
warnMissingBridge("emitScoreConfig");
|
|
1151
158
|
}
|
|
1152
159
|
|
|
1153
160
|
// src/share.ts
|
|
1154
|
-
function
|
|
161
|
+
function isDevelopment4() {
|
|
1155
162
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1156
163
|
return nodeEnv !== "production";
|
|
1157
164
|
}
|
|
1158
|
-
function
|
|
165
|
+
function getBridgeWindow4() {
|
|
1159
166
|
if (typeof window === "undefined") {
|
|
1160
167
|
return void 0;
|
|
1161
168
|
}
|
|
1162
169
|
return window;
|
|
1163
170
|
}
|
|
1164
|
-
function
|
|
1165
|
-
if (
|
|
171
|
+
function warnMissingBridge2(methodName) {
|
|
172
|
+
if (isDevelopment4()) {
|
|
1166
173
|
console.warn(
|
|
1167
174
|
"[oasiz/sdk] " + methodName + " share bridge is unavailable. This is expected in local development."
|
|
1168
175
|
);
|
|
@@ -1193,458 +200,131 @@ function validateRequest(options) {
|
|
|
1193
200
|
}
|
|
1194
201
|
}
|
|
1195
202
|
if (hasImage && !isValidImageReference(options.image)) {
|
|
1196
|
-
throw new Error(
|
|
1197
|
-
"Share image must be an http(s) URL or a data:image/... base64 string."
|
|
1198
|
-
);
|
|
1199
|
-
}
|
|
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;
|
|
1452
|
-
}
|
|
1453
|
-
function pixelsToPercentOfViewport(pixels, bridge, side) {
|
|
1454
|
-
const size = getViewportSize2(bridge, SIDE_TO_AXIS[side]);
|
|
1455
|
-
if (size <= 0) {
|
|
1456
|
-
return 0;
|
|
203
|
+
throw new Error(
|
|
204
|
+
"Share image must be an http(s) URL or a data:image/... base64 string."
|
|
205
|
+
);
|
|
1457
206
|
}
|
|
1458
|
-
return
|
|
207
|
+
return {
|
|
208
|
+
...hasText ? { text } : {},
|
|
209
|
+
...hasScore ? { score: options.score } : {},
|
|
210
|
+
...hasImage ? { image: options.image } : {}
|
|
211
|
+
};
|
|
1459
212
|
}
|
|
1460
|
-
function
|
|
1461
|
-
const
|
|
1462
|
-
|
|
1463
|
-
|
|
213
|
+
async function share(options) {
|
|
214
|
+
const request = validateRequest(options);
|
|
215
|
+
const bridge = getBridgeWindow4();
|
|
216
|
+
if (typeof bridge?.__oasizShareRequest !== "function") {
|
|
217
|
+
warnMissingBridge2("__oasizShareRequest");
|
|
218
|
+
throw new Error("Share bridge unavailable");
|
|
1464
219
|
}
|
|
1465
|
-
|
|
1466
|
-
}
|
|
1467
|
-
function cssSafeAreaPercent(bridge, side) {
|
|
1468
|
-
return pixelsToPercentOfViewport(readCssSafeAreaPixels(bridge, side), bridge, side);
|
|
220
|
+
await bridge.__oasizShareRequest(request);
|
|
1469
221
|
}
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
return percent > 0 ? percent : cssSafeAreaPercent(bridge, side);
|
|
222
|
+
|
|
223
|
+
// src/state.ts
|
|
224
|
+
function isDevelopment5() {
|
|
225
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
226
|
+
return nodeEnv !== "production";
|
|
1476
227
|
}
|
|
1477
|
-
function
|
|
1478
|
-
|
|
1479
|
-
if (typeof numeric === "undefined") {
|
|
228
|
+
function getBridgeWindow5() {
|
|
229
|
+
if (typeof window === "undefined") {
|
|
1480
230
|
return void 0;
|
|
1481
231
|
}
|
|
1482
|
-
return
|
|
232
|
+
return window;
|
|
1483
233
|
}
|
|
1484
|
-
function
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
return "Top";
|
|
1488
|
-
case "right":
|
|
1489
|
-
return "Right";
|
|
1490
|
-
case "bottom":
|
|
1491
|
-
return "Bottom";
|
|
1492
|
-
case "left":
|
|
1493
|
-
return "Left";
|
|
234
|
+
function isPlainObject(value) {
|
|
235
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
236
|
+
return false;
|
|
1494
237
|
}
|
|
238
|
+
const proto = Object.getPrototypeOf(value);
|
|
239
|
+
return proto === Object.prototype || proto === null;
|
|
1495
240
|
}
|
|
1496
|
-
function
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
try {
|
|
1502
|
-
return fn.call(bridge);
|
|
1503
|
-
} catch (error) {
|
|
1504
|
-
console.error("[oasiz/sdk] " + String(name) + " failed:", error);
|
|
1505
|
-
return void 0;
|
|
241
|
+
function warnMissingBridge3(methodName) {
|
|
242
|
+
if (isDevelopment5()) {
|
|
243
|
+
console.warn(
|
|
244
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
245
|
+
);
|
|
1506
246
|
}
|
|
1507
247
|
}
|
|
1508
|
-
function
|
|
1509
|
-
|
|
1510
|
-
|
|
248
|
+
function loadGameState() {
|
|
249
|
+
const bridge = getBridgeWindow5();
|
|
250
|
+
if (typeof bridge?.loadGameState !== "function") {
|
|
251
|
+
warnMissingBridge3("loadGameState");
|
|
252
|
+
return {};
|
|
1511
253
|
}
|
|
1512
|
-
|
|
1513
|
-
|
|
254
|
+
const state = bridge.loadGameState();
|
|
255
|
+
if (!isPlainObject(state)) {
|
|
256
|
+
if (isDevelopment5()) {
|
|
257
|
+
console.warn(
|
|
258
|
+
"[oasiz/sdk] loadGameState returned invalid data. Falling back to empty object."
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
return {};
|
|
1514
262
|
}
|
|
1515
|
-
return
|
|
1516
|
-
}
|
|
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
|
-
);
|
|
263
|
+
return state;
|
|
1547
264
|
}
|
|
1548
|
-
function
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
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
|
-
};
|
|
265
|
+
function saveGameState(state) {
|
|
266
|
+
if (!isPlainObject(state)) {
|
|
267
|
+
if (isDevelopment5()) {
|
|
268
|
+
console.warn("[oasiz/sdk] saveGameState expected a plain object:", state);
|
|
269
|
+
}
|
|
270
|
+
return;
|
|
1564
271
|
}
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
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
|
-
};
|
|
272
|
+
const bridge = getBridgeWindow5();
|
|
273
|
+
if (typeof bridge?.saveGameState === "function") {
|
|
274
|
+
bridge.saveGameState(state);
|
|
275
|
+
return;
|
|
1578
276
|
}
|
|
1579
|
-
|
|
1580
|
-
return {
|
|
1581
|
-
pixels: cssPixels,
|
|
1582
|
-
percent: pixelsToPercentOfViewport(cssPixels, bridge, side)
|
|
1583
|
-
};
|
|
277
|
+
warnMissingBridge3("saveGameState");
|
|
1584
278
|
}
|
|
1585
|
-
function
|
|
1586
|
-
const bridge =
|
|
1587
|
-
if (
|
|
1588
|
-
|
|
1589
|
-
|
|
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;
|
|
279
|
+
function flushGameState() {
|
|
280
|
+
const bridge = getBridgeWindow5();
|
|
281
|
+
if (typeof bridge?.flushGameState === "function") {
|
|
282
|
+
bridge.flushGameState();
|
|
283
|
+
return;
|
|
1600
284
|
}
|
|
1601
|
-
|
|
285
|
+
warnMissingBridge3("flushGameState");
|
|
1602
286
|
}
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
const top = getViewportInsets().percent.top;
|
|
1609
|
-
if (top <= 0) {
|
|
1610
|
-
warnMissingBridge6("getSafeAreaTop");
|
|
1611
|
-
}
|
|
1612
|
-
return top;
|
|
287
|
+
|
|
288
|
+
// src/lifecycle.ts
|
|
289
|
+
function isDevelopment6() {
|
|
290
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
291
|
+
return nodeEnv !== "production";
|
|
1613
292
|
}
|
|
1614
|
-
function
|
|
1615
|
-
if (typeof
|
|
1616
|
-
if (
|
|
293
|
+
function addLifecycleListener(eventName, callback) {
|
|
294
|
+
if (typeof window === "undefined") {
|
|
295
|
+
if (isDevelopment6()) {
|
|
1617
296
|
console.warn(
|
|
1618
|
-
"[oasiz/sdk]
|
|
1619
|
-
visible
|
|
297
|
+
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
1620
298
|
);
|
|
1621
299
|
}
|
|
1622
|
-
return
|
|
1623
|
-
|
|
1624
|
-
const bridge = getBridgeWindow8();
|
|
1625
|
-
if (typeof bridge?.__oasizSetLeaderboardVisible === "function") {
|
|
1626
|
-
bridge.__oasizSetLeaderboardVisible(visible);
|
|
1627
|
-
return;
|
|
300
|
+
return () => {
|
|
301
|
+
};
|
|
1628
302
|
}
|
|
1629
|
-
|
|
303
|
+
const handler = () => callback();
|
|
304
|
+
window.addEventListener(eventName, handler);
|
|
305
|
+
return () => window.removeEventListener(eventName, handler);
|
|
306
|
+
}
|
|
307
|
+
function onPause(callback) {
|
|
308
|
+
return addLifecycleListener("oasiz:pause", callback);
|
|
309
|
+
}
|
|
310
|
+
function onResume(callback) {
|
|
311
|
+
return addLifecycleListener("oasiz:resume", callback);
|
|
1630
312
|
}
|
|
1631
313
|
|
|
1632
314
|
// src/navigation.ts
|
|
1633
|
-
var BACK_BUTTON_TEST_STATE_KEY = "__oasizBackButtonTest";
|
|
1634
315
|
var activeBackListeners = 0;
|
|
1635
|
-
|
|
1636
|
-
function isDevelopment10() {
|
|
316
|
+
function isDevelopment7() {
|
|
1637
317
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1638
318
|
return nodeEnv !== "production";
|
|
1639
319
|
}
|
|
1640
|
-
function
|
|
320
|
+
function getBridgeWindow6() {
|
|
1641
321
|
if (typeof window === "undefined") {
|
|
1642
322
|
return void 0;
|
|
1643
323
|
}
|
|
1644
324
|
return window;
|
|
1645
325
|
}
|
|
1646
|
-
function
|
|
1647
|
-
if (
|
|
326
|
+
function warnMissingBridge4(methodName) {
|
|
327
|
+
if (isDevelopment7()) {
|
|
1648
328
|
console.warn(
|
|
1649
329
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1650
330
|
);
|
|
@@ -1658,19 +338,9 @@ function normalizeNavigationError(error) {
|
|
|
1658
338
|
typeof error === "string" ? error : "Back button callback failed."
|
|
1659
339
|
);
|
|
1660
340
|
}
|
|
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
|
-
}
|
|
1671
341
|
function addNavigationListener(eventName, callback) {
|
|
1672
342
|
if (typeof window === "undefined") {
|
|
1673
|
-
if (
|
|
343
|
+
if (isDevelopment7()) {
|
|
1674
344
|
console.warn(
|
|
1675
345
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
1676
346
|
);
|
|
@@ -1682,151 +352,6 @@ function addNavigationListener(eventName, callback) {
|
|
|
1682
352
|
window.addEventListener(eventName, handler);
|
|
1683
353
|
return () => window.removeEventListener(eventName, handler);
|
|
1684
354
|
}
|
|
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
|
-
}
|
|
1830
355
|
function onBackButton(callback) {
|
|
1831
356
|
const off = addNavigationListener("oasiz:back", () => {
|
|
1832
357
|
try {
|
|
@@ -1836,24 +361,24 @@ function onBackButton(callback) {
|
|
|
1836
361
|
throw normalizeNavigationError(error);
|
|
1837
362
|
}
|
|
1838
363
|
});
|
|
1839
|
-
const bridge =
|
|
364
|
+
const bridge = getBridgeWindow6();
|
|
1840
365
|
activeBackListeners += 1;
|
|
1841
366
|
if (activeBackListeners === 1) {
|
|
1842
367
|
if (typeof bridge?.__oasizSetBackOverride === "function") {
|
|
1843
368
|
bridge.__oasizSetBackOverride(true);
|
|
1844
369
|
} else {
|
|
1845
|
-
|
|
370
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
1846
371
|
}
|
|
1847
372
|
}
|
|
1848
373
|
return () => {
|
|
1849
374
|
off();
|
|
1850
375
|
activeBackListeners = Math.max(0, activeBackListeners - 1);
|
|
1851
376
|
if (activeBackListeners === 0) {
|
|
1852
|
-
const currentBridge =
|
|
377
|
+
const currentBridge = getBridgeWindow6();
|
|
1853
378
|
if (typeof currentBridge?.__oasizSetBackOverride === "function") {
|
|
1854
379
|
currentBridge.__oasizSetBackOverride(false);
|
|
1855
380
|
} else {
|
|
1856
|
-
|
|
381
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
1857
382
|
}
|
|
1858
383
|
}
|
|
1859
384
|
};
|
|
@@ -1862,414 +387,177 @@ function onLeaveGame(callback) {
|
|
|
1862
387
|
return addNavigationListener("oasiz:leave", callback);
|
|
1863
388
|
}
|
|
1864
389
|
function leaveGame() {
|
|
1865
|
-
const bridge =
|
|
390
|
+
const bridge = getBridgeWindow6();
|
|
1866
391
|
if (typeof bridge?.__oasizLeaveGame === "function") {
|
|
1867
392
|
bridge.__oasizLeaveGame();
|
|
1868
393
|
return;
|
|
1869
394
|
}
|
|
1870
|
-
|
|
395
|
+
warnMissingBridge4("__oasizLeaveGame");
|
|
1871
396
|
}
|
|
1872
397
|
|
|
1873
|
-
// src/
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
minimal: 24,
|
|
1880
|
-
low: 30,
|
|
1881
|
-
medium: 45,
|
|
1882
|
-
high: 60
|
|
1883
|
-
};
|
|
1884
|
-
var cachedEstimatedGraphicsPerformance;
|
|
1885
|
-
function getBridgeWindow10() {
|
|
398
|
+
// src/store.ts
|
|
399
|
+
function isDevelopment8() {
|
|
400
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
401
|
+
return nodeEnv !== "production";
|
|
402
|
+
}
|
|
403
|
+
function getBridgeWindow7() {
|
|
1886
404
|
if (typeof window === "undefined") {
|
|
1887
405
|
return void 0;
|
|
1888
406
|
}
|
|
1889
407
|
return window;
|
|
1890
408
|
}
|
|
1891
|
-
function
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
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
|
-
}
|
|
409
|
+
function warnMissingBridge5(methodName) {
|
|
410
|
+
if (isDevelopment8()) {
|
|
411
|
+
console.warn(
|
|
412
|
+
"[oasiz/sdk] " + methodName + " store bridge is unavailable. This is expected in local development."
|
|
413
|
+
);
|
|
1903
414
|
}
|
|
1904
|
-
return void 0;
|
|
1905
|
-
}
|
|
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
415
|
}
|
|
1927
|
-
function
|
|
1928
|
-
|
|
1929
|
-
|
|
416
|
+
async function requestStoreBridge(action, payload) {
|
|
417
|
+
const bridge = getBridgeWindow7();
|
|
418
|
+
if (typeof bridge?.__oasizStoreBridgeRequest !== "function") {
|
|
419
|
+
warnMissingBridge5(action);
|
|
420
|
+
throw new Error("Store bridge unavailable");
|
|
1930
421
|
}
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
if (normalized === "low") return "low";
|
|
1936
|
-
return void 0;
|
|
422
|
+
return await bridge.__oasizStoreBridgeRequest({
|
|
423
|
+
action,
|
|
424
|
+
payload
|
|
425
|
+
});
|
|
1937
426
|
}
|
|
1938
|
-
function
|
|
1939
|
-
return
|
|
427
|
+
async function getFreshState() {
|
|
428
|
+
return await requestStoreBridge("getStoreState");
|
|
1940
429
|
}
|
|
1941
|
-
function
|
|
1942
|
-
if (typeof
|
|
1943
|
-
return
|
|
1944
|
-
|
|
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;
|
|
430
|
+
function subscribeToStoreEvent(eventName, callback) {
|
|
431
|
+
if (typeof window === "undefined") {
|
|
432
|
+
return () => {
|
|
433
|
+
};
|
|
1986
434
|
}
|
|
1987
|
-
const
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
435
|
+
const handler = (event) => {
|
|
436
|
+
const customEvent = event;
|
|
437
|
+
callback(customEvent.detail);
|
|
438
|
+
};
|
|
439
|
+
window.addEventListener(eventName, handler);
|
|
440
|
+
return () => {
|
|
441
|
+
window.removeEventListener(eventName, handler);
|
|
1993
442
|
};
|
|
1994
443
|
}
|
|
1995
|
-
function
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
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
|
-
}
|
|
2006
|
-
}
|
|
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;
|
|
2022
|
-
}
|
|
2023
|
-
function getDevicePixelRatio2(bridge) {
|
|
2024
|
-
const dpr = bridge.devicePixelRatio;
|
|
2025
|
-
return typeof dpr === "number" && Number.isFinite(dpr) && dpr > 0 ? dpr : 1;
|
|
2026
|
-
}
|
|
2027
|
-
function getNavigatorValue(bridge) {
|
|
2028
|
-
return bridge.navigator;
|
|
2029
|
-
}
|
|
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;
|
|
2037
|
-
}
|
|
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;
|
|
2041
|
-
}
|
|
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
|
-
);
|
|
444
|
+
async function syncProducts(products, expectedVersion) {
|
|
445
|
+
return await requestStoreBridge("syncProducts", {
|
|
446
|
+
expectedVersion: expectedVersion ?? null,
|
|
447
|
+
products
|
|
448
|
+
});
|
|
2053
449
|
}
|
|
2054
|
-
function
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
} catch {
|
|
2058
|
-
return false;
|
|
2059
|
-
}
|
|
450
|
+
async function getProducts() {
|
|
451
|
+
const state = await getFreshState();
|
|
452
|
+
return state.products;
|
|
2060
453
|
}
|
|
2061
|
-
function
|
|
2062
|
-
const
|
|
2063
|
-
|
|
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
|
-
};
|
|
454
|
+
async function getEntitlements() {
|
|
455
|
+
const state = await getFreshState();
|
|
456
|
+
return state.entitlements;
|
|
2095
457
|
}
|
|
2096
|
-
function
|
|
2097
|
-
|
|
2098
|
-
|
|
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;
|
|
458
|
+
async function hasEntitlement(productId) {
|
|
459
|
+
const state = await getFreshState();
|
|
460
|
+
return state.entitlements.find((item) => item.productId === productId)?.owned === true;
|
|
2105
461
|
}
|
|
2106
|
-
function
|
|
2107
|
-
|
|
2108
|
-
|
|
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;
|
|
462
|
+
async function getQuantity(productId) {
|
|
463
|
+
const state = await getFreshState();
|
|
464
|
+
return state.entitlements.find((item) => item.productId === productId)?.quantity ?? 0;
|
|
2114
465
|
}
|
|
2115
|
-
function
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
}
|
|
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;
|
|
466
|
+
async function purchase(productId, quantity = 1) {
|
|
467
|
+
return await requestStoreBridge("purchaseProduct", {
|
|
468
|
+
productId,
|
|
469
|
+
quantity
|
|
470
|
+
});
|
|
2136
471
|
}
|
|
2137
|
-
function
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
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;
|
|
472
|
+
async function consume(productId, quantity = 1) {
|
|
473
|
+
return await requestStoreBridge("consumeProduct", {
|
|
474
|
+
productId,
|
|
475
|
+
quantity
|
|
476
|
+
});
|
|
2149
477
|
}
|
|
2150
|
-
function
|
|
2151
|
-
|
|
2152
|
-
|
|
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);
|
|
478
|
+
async function getJemBalance() {
|
|
479
|
+
const state = await getFreshState();
|
|
480
|
+
return state.jemBalance;
|
|
2168
481
|
}
|
|
2169
|
-
function
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
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
|
-
};
|
|
482
|
+
function onEntitlementsChanged(callback) {
|
|
483
|
+
return subscribeToStoreEvent("oasiz:entitlements-changed", (state) => {
|
|
484
|
+
callback(state.entitlements);
|
|
485
|
+
});
|
|
2182
486
|
}
|
|
2183
|
-
function
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
}
|
|
2188
|
-
const hostMetric = readHostGraphicsPerformance(bridge);
|
|
2189
|
-
if (hostMetric) {
|
|
2190
|
-
return hostMetric;
|
|
2191
|
-
}
|
|
2192
|
-
cachedEstimatedGraphicsPerformance ??= estimateGraphicsPerformance(bridge);
|
|
2193
|
-
return { ...cachedEstimatedGraphicsPerformance };
|
|
487
|
+
function onJemBalanceChanged(callback) {
|
|
488
|
+
return subscribeToStoreEvent("oasiz:jem-balance-changed", (state) => {
|
|
489
|
+
callback(state.jemBalance);
|
|
490
|
+
});
|
|
2194
491
|
}
|
|
2195
492
|
|
|
2196
493
|
// src/index.ts
|
|
2197
494
|
var oasiz = {
|
|
2198
495
|
submitScore,
|
|
2199
|
-
|
|
2200
|
-
setScore,
|
|
2201
|
-
getPlayerCharacter,
|
|
496
|
+
emitScoreConfig,
|
|
2202
497
|
share,
|
|
2203
498
|
triggerHaptic,
|
|
2204
|
-
enableLogOverlay,
|
|
2205
499
|
loadGameState,
|
|
2206
500
|
saveGameState,
|
|
2207
501
|
flushGameState,
|
|
2208
502
|
shareRoomCode,
|
|
2209
|
-
openInviteModal,
|
|
2210
503
|
onPause,
|
|
2211
504
|
onResume,
|
|
2212
|
-
getSafeAreaTop,
|
|
2213
|
-
getViewportInsets,
|
|
2214
|
-
setLeaderboardVisible,
|
|
2215
|
-
getGraphicsPerformance,
|
|
2216
|
-
enableBackButtonTesting,
|
|
2217
505
|
onBackButton,
|
|
2218
506
|
onLeaveGame,
|
|
2219
507
|
leaveGame,
|
|
508
|
+
store: {
|
|
509
|
+
syncProducts,
|
|
510
|
+
getProducts,
|
|
511
|
+
getEntitlements,
|
|
512
|
+
hasEntitlement,
|
|
513
|
+
getQuantity,
|
|
514
|
+
purchase,
|
|
515
|
+
consume,
|
|
516
|
+
getJemBalance,
|
|
517
|
+
onEntitlementsChanged,
|
|
518
|
+
onJemBalanceChanged
|
|
519
|
+
},
|
|
2220
520
|
get gameId() {
|
|
2221
521
|
return getGameId();
|
|
2222
522
|
},
|
|
2223
523
|
get roomCode() {
|
|
2224
524
|
return getRoomCode();
|
|
2225
525
|
},
|
|
2226
|
-
get playerId() {
|
|
2227
|
-
return getPlayerId();
|
|
2228
|
-
},
|
|
2229
526
|
get playerName() {
|
|
2230
527
|
return getPlayerName();
|
|
2231
528
|
},
|
|
2232
529
|
get playerAvatar() {
|
|
2233
530
|
return getPlayerAvatar();
|
|
2234
|
-
},
|
|
2235
|
-
get safeAreaTop() {
|
|
2236
|
-
return getSafeAreaTop();
|
|
2237
|
-
},
|
|
2238
|
-
get viewportInsets() {
|
|
2239
|
-
return getViewportInsets();
|
|
2240
|
-
},
|
|
2241
|
-
get graphicsPerformance() {
|
|
2242
|
-
return getGraphicsPerformance();
|
|
2243
531
|
}
|
|
2244
532
|
};
|
|
2245
533
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2246
534
|
0 && (module.exports = {
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
enableLogOverlay,
|
|
535
|
+
consume,
|
|
536
|
+
emitScoreConfig,
|
|
2250
537
|
flushGameState,
|
|
538
|
+
getEntitlements,
|
|
2251
539
|
getGameId,
|
|
2252
|
-
|
|
540
|
+
getJemBalance,
|
|
2253
541
|
getPlayerAvatar,
|
|
2254
|
-
getPlayerCharacter,
|
|
2255
|
-
getPlayerId,
|
|
2256
542
|
getPlayerName,
|
|
543
|
+
getProducts,
|
|
544
|
+
getQuantity,
|
|
2257
545
|
getRoomCode,
|
|
2258
|
-
|
|
2259
|
-
getViewportInsets,
|
|
546
|
+
hasEntitlement,
|
|
2260
547
|
leaveGame,
|
|
2261
548
|
loadGameState,
|
|
2262
549
|
oasiz,
|
|
2263
550
|
onBackButton,
|
|
551
|
+
onEntitlementsChanged,
|
|
552
|
+
onJemBalanceChanged,
|
|
2264
553
|
onLeaveGame,
|
|
2265
554
|
onPause,
|
|
2266
555
|
onResume,
|
|
2267
|
-
|
|
556
|
+
purchase,
|
|
2268
557
|
saveGameState,
|
|
2269
|
-
setLeaderboardVisible,
|
|
2270
|
-
setScore,
|
|
2271
558
|
share,
|
|
2272
559
|
shareRoomCode,
|
|
2273
560
|
submitScore,
|
|
561
|
+
syncProducts,
|
|
2274
562
|
triggerHaptic
|
|
2275
563
|
});
|