@oasiz/sdk 1.5.5 → 1.6.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 +84 -346
- package/dist/index.cjs +187 -1276
- package/dist/index.d.cts +97 -182
- package/dist/index.d.ts +97 -182
- package/dist/index.js +176 -1268
- package/package.json +4 -14
package/dist/index.cjs
CHANGED
|
@@ -20,35 +20,38 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
consume: () => consume,
|
|
24
|
+
emitScoreConfig: () => emitScoreConfig,
|
|
25
25
|
flushGameState: () => flushGameState,
|
|
26
|
+
getEntitlements: () => getEntitlements,
|
|
26
27
|
getGameId: () => getGameId,
|
|
28
|
+
getJemBalance: () => getJemBalance,
|
|
27
29
|
getPlayerAvatar: () => getPlayerAvatar,
|
|
28
|
-
getPlayerCharacter: () => getPlayerCharacter,
|
|
29
|
-
getPlayerId: () => getPlayerId,
|
|
30
30
|
getPlayerName: () => getPlayerName,
|
|
31
|
+
getProducts: () => getProducts,
|
|
32
|
+
getQuantity: () => getQuantity,
|
|
31
33
|
getRoomCode: () => getRoomCode,
|
|
32
|
-
|
|
34
|
+
hasEntitlement: () => hasEntitlement,
|
|
33
35
|
leaveGame: () => leaveGame,
|
|
34
36
|
loadGameState: () => loadGameState,
|
|
35
37
|
oasiz: () => oasiz,
|
|
36
38
|
onBackButton: () => onBackButton,
|
|
39
|
+
onEntitlementsChanged: () => onEntitlementsChanged,
|
|
40
|
+
onJemBalanceChanged: () => onJemBalanceChanged,
|
|
37
41
|
onLeaveGame: () => onLeaveGame,
|
|
38
42
|
onPause: () => onPause,
|
|
39
43
|
onResume: () => onResume,
|
|
40
|
-
|
|
44
|
+
purchase: () => purchase,
|
|
41
45
|
saveGameState: () => saveGameState,
|
|
42
|
-
setLeaderboardVisible: () => setLeaderboardVisible,
|
|
43
|
-
setScore: () => setScore,
|
|
44
46
|
share: () => share,
|
|
45
47
|
shareRoomCode: () => shareRoomCode,
|
|
46
48
|
submitScore: () => submitScore,
|
|
49
|
+
syncProducts: () => syncProducts,
|
|
47
50
|
triggerHaptic: () => triggerHaptic
|
|
48
51
|
});
|
|
49
52
|
module.exports = __toCommonJS(index_exports);
|
|
50
53
|
|
|
51
|
-
// src/
|
|
54
|
+
// src/haptics.ts
|
|
52
55
|
function isDevelopment() {
|
|
53
56
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
54
57
|
return nodeEnv !== "production";
|
|
@@ -59,1014 +62,72 @@ function getBridgeWindow() {
|
|
|
59
62
|
}
|
|
60
63
|
return window;
|
|
61
64
|
}
|
|
62
|
-
function warnMissingBridge(methodName) {
|
|
63
|
-
if (isDevelopment()) {
|
|
64
|
-
console.warn(
|
|
65
|
-
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
async function getPlayerCharacter() {
|
|
70
|
-
const bridge = getBridgeWindow();
|
|
71
|
-
if (typeof bridge?.__oasizGetPlayerCharacter !== "function") {
|
|
72
|
-
warnMissingBridge("getPlayerCharacter");
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
const result = await bridge.__oasizGetPlayerCharacter();
|
|
77
|
-
return result ?? null;
|
|
78
|
-
} catch (error) {
|
|
79
|
-
if (isDevelopment()) {
|
|
80
|
-
console.error("[oasiz/sdk] getPlayerCharacter failed:", error);
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// src/haptics.ts
|
|
87
|
-
function isDevelopment2() {
|
|
88
|
-
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
89
|
-
return nodeEnv !== "production";
|
|
90
|
-
}
|
|
91
|
-
function getBridgeWindow2() {
|
|
92
|
-
if (typeof window === "undefined") {
|
|
93
|
-
return void 0;
|
|
94
|
-
}
|
|
95
|
-
return window;
|
|
96
|
-
}
|
|
97
65
|
function triggerHaptic(type) {
|
|
98
|
-
const bridge =
|
|
66
|
+
const bridge = getBridgeWindow();
|
|
99
67
|
if (typeof bridge?.triggerHaptic === "function") {
|
|
100
68
|
bridge.triggerHaptic(type);
|
|
101
69
|
return;
|
|
102
70
|
}
|
|
103
|
-
if (
|
|
71
|
+
if (isDevelopment()) {
|
|
104
72
|
console.warn(
|
|
105
73
|
"[oasiz/sdk] triggerHaptic bridge is unavailable. This is expected in local development."
|
|
106
74
|
);
|
|
107
75
|
}
|
|
108
76
|
}
|
|
109
77
|
|
|
110
|
-
// src/log-overlay.ts
|
|
111
|
-
var CONSOLE_METHODS = [
|
|
112
|
-
"debug",
|
|
113
|
-
"log",
|
|
114
|
-
"info",
|
|
115
|
-
"warn",
|
|
116
|
-
"error"
|
|
117
|
-
];
|
|
118
|
-
var DEFAULT_MAX_ENTRIES = 200;
|
|
119
|
-
var DEFAULT_TITLE = "SDK Logs";
|
|
120
|
-
var OVERLAY_MARGIN = 12;
|
|
121
|
-
var DEFAULT_COLLAPSED_WIDTH = 156;
|
|
122
|
-
var DEFAULT_COLLAPSED_HEIGHT = 52;
|
|
123
|
-
var DEFAULT_EXPANDED_WIDTH = 565;
|
|
124
|
-
var DEFAULT_EXPANDED_HEIGHT = 372;
|
|
125
|
-
var DRAG_THRESHOLD_PX = 6;
|
|
126
|
-
var MIN_EXPANDED_WIDTH = 160;
|
|
127
|
-
var MIN_EXPANDED_HEIGHT = 110;
|
|
128
|
-
var RESIZE_HOTSPOT_PX = 28;
|
|
129
|
-
var TOP_DRAG_ZONE_PX = 44;
|
|
130
|
-
var NOOP_HANDLE = {
|
|
131
|
-
clear() {
|
|
132
|
-
},
|
|
133
|
-
destroy() {
|
|
134
|
-
},
|
|
135
|
-
hide() {
|
|
136
|
-
},
|
|
137
|
-
isVisible() {
|
|
138
|
-
return false;
|
|
139
|
-
},
|
|
140
|
-
show() {
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
function getBrowserWindow() {
|
|
144
|
-
if (typeof window === "undefined") {
|
|
145
|
-
return void 0;
|
|
146
|
-
}
|
|
147
|
-
return window;
|
|
148
|
-
}
|
|
149
|
-
function getDocument() {
|
|
150
|
-
if (typeof document === "undefined") {
|
|
151
|
-
return void 0;
|
|
152
|
-
}
|
|
153
|
-
return document;
|
|
154
|
-
}
|
|
155
|
-
function clampMaxEntries(value) {
|
|
156
|
-
if (!Number.isFinite(value)) {
|
|
157
|
-
return DEFAULT_MAX_ENTRIES;
|
|
158
|
-
}
|
|
159
|
-
return Math.max(10, Math.floor(value));
|
|
160
|
-
}
|
|
161
|
-
function createConsoleSnapshot() {
|
|
162
|
-
const fallback = console.log.bind(console);
|
|
163
|
-
return {
|
|
164
|
-
debug: typeof console.debug === "function" ? console.debug.bind(console) : fallback,
|
|
165
|
-
log: fallback,
|
|
166
|
-
info: typeof console.info === "function" ? console.info.bind(console) : fallback,
|
|
167
|
-
warn: typeof console.warn === "function" ? console.warn.bind(console) : fallback,
|
|
168
|
-
error: typeof console.error === "function" ? console.error.bind(console) : fallback
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
function formatTimestamp(timestamp) {
|
|
172
|
-
const date = new Date(timestamp);
|
|
173
|
-
const hours = String(date.getHours()).padStart(2, "0");
|
|
174
|
-
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
175
|
-
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
176
|
-
const milliseconds = String(date.getMilliseconds()).padStart(3, "0");
|
|
177
|
-
return "[" + hours + ":" + minutes + ":" + seconds + "." + milliseconds + "]";
|
|
178
|
-
}
|
|
179
|
-
function safeStringify(value) {
|
|
180
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
181
|
-
try {
|
|
182
|
-
return JSON.stringify(
|
|
183
|
-
value,
|
|
184
|
-
(_key, candidate) => {
|
|
185
|
-
if (typeof candidate === "bigint") {
|
|
186
|
-
return candidate.toString() + "n";
|
|
187
|
-
}
|
|
188
|
-
if (typeof candidate === "object" && candidate !== null) {
|
|
189
|
-
if (seen.has(candidate)) {
|
|
190
|
-
return "[Circular]";
|
|
191
|
-
}
|
|
192
|
-
seen.add(candidate);
|
|
193
|
-
}
|
|
194
|
-
return candidate;
|
|
195
|
-
},
|
|
196
|
-
2
|
|
197
|
-
) ?? String(value);
|
|
198
|
-
} catch {
|
|
199
|
-
return String(value);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
function formatArg(value) {
|
|
203
|
-
if (typeof value === "string") {
|
|
204
|
-
return value;
|
|
205
|
-
}
|
|
206
|
-
if (value instanceof Error) {
|
|
207
|
-
if (value.stack) {
|
|
208
|
-
return value.stack;
|
|
209
|
-
}
|
|
210
|
-
return value.name + ": " + value.message;
|
|
211
|
-
}
|
|
212
|
-
if (typeof value === "undefined") {
|
|
213
|
-
return "undefined";
|
|
214
|
-
}
|
|
215
|
-
if (typeof value === "function") {
|
|
216
|
-
return "[Function " + (value.name || "anonymous") + "]";
|
|
217
|
-
}
|
|
218
|
-
return safeStringify(value);
|
|
219
|
-
}
|
|
220
|
-
function formatEntryMessage(args) {
|
|
221
|
-
const message = args.map(formatArg).join(" ");
|
|
222
|
-
if (message.length <= 4e3) {
|
|
223
|
-
return message;
|
|
224
|
-
}
|
|
225
|
-
return message.slice(0, 3997) + "...";
|
|
226
|
-
}
|
|
227
|
-
function createEntry(level, args, id) {
|
|
228
|
-
return {
|
|
229
|
-
id,
|
|
230
|
-
level,
|
|
231
|
-
message: formatEntryMessage(args),
|
|
232
|
-
timestamp: Date.now()
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
function createButton(label) {
|
|
236
|
-
const button = document.createElement("button");
|
|
237
|
-
button.type = "button";
|
|
238
|
-
button.textContent = label;
|
|
239
|
-
button.style.cssText = [
|
|
240
|
-
"appearance:none",
|
|
241
|
-
"border:1px solid rgba(255,255,255,0.18)",
|
|
242
|
-
"background:rgba(255,255,255,0.06)",
|
|
243
|
-
"color:#f8fafc",
|
|
244
|
-
"border-radius:999px",
|
|
245
|
-
"padding:6px 10px",
|
|
246
|
-
"font:600 12px/1.1 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
|
|
247
|
-
"cursor:pointer"
|
|
248
|
-
].join(";");
|
|
249
|
-
return button;
|
|
250
|
-
}
|
|
251
|
-
function getLevelAccent(level) {
|
|
252
|
-
if (level === "error") {
|
|
253
|
-
return {
|
|
254
|
-
lineBackground: "rgba(255, 109, 122, 0.08)"
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
if (level === "warn") {
|
|
258
|
-
return {
|
|
259
|
-
lineBackground: "rgba(255, 196, 94, 0.07)"
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
if (level === "info") {
|
|
263
|
-
return {
|
|
264
|
-
lineBackground: "rgba(82, 187, 255, 0.07)"
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
if (level === "debug") {
|
|
268
|
-
return {
|
|
269
|
-
lineBackground: "rgba(166, 137, 255, 0.07)"
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
return {
|
|
273
|
-
lineBackground: "rgba(117, 235, 191, 0.06)"
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
function getViewportSize() {
|
|
277
|
-
const browserWindow = getBrowserWindow();
|
|
278
|
-
return {
|
|
279
|
-
width: Math.max(320, browserWindow?.innerWidth ?? 1280),
|
|
280
|
-
height: Math.max(240, browserWindow?.innerHeight ?? 720)
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
function clampPanelSize(size) {
|
|
284
|
-
const viewport = getViewportSize();
|
|
285
|
-
const maxWidth = Math.max(MIN_EXPANDED_WIDTH, viewport.width - OVERLAY_MARGIN * 2);
|
|
286
|
-
const maxHeight = Math.max(
|
|
287
|
-
MIN_EXPANDED_HEIGHT,
|
|
288
|
-
viewport.height - OVERLAY_MARGIN * 2
|
|
289
|
-
);
|
|
290
|
-
return {
|
|
291
|
-
width: Math.min(maxWidth, Math.max(MIN_EXPANDED_WIDTH, size.width)),
|
|
292
|
-
height: Math.min(maxHeight, Math.max(MIN_EXPANDED_HEIGHT, size.height))
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
function getOverlaySize(state) {
|
|
296
|
-
if (state.expanded && state.panelSize) {
|
|
297
|
-
return state.panelSize;
|
|
298
|
-
}
|
|
299
|
-
const rect = state.ui?.root && typeof state.ui.root.getBoundingClientRect === "function" ? state.ui.root.getBoundingClientRect() : null;
|
|
300
|
-
if (rect && Number.isFinite(rect.width) && Number.isFinite(rect.height)) {
|
|
301
|
-
return {
|
|
302
|
-
width: Math.max(1, rect.width),
|
|
303
|
-
height: Math.max(1, rect.height)
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
return state.expanded ? clampPanelSize({
|
|
307
|
-
width: DEFAULT_EXPANDED_WIDTH,
|
|
308
|
-
height: DEFAULT_EXPANDED_HEIGHT
|
|
309
|
-
}) : { width: DEFAULT_COLLAPSED_WIDTH, height: DEFAULT_COLLAPSED_HEIGHT };
|
|
310
|
-
}
|
|
311
|
-
function applyPanelSize(state) {
|
|
312
|
-
if (!state.ui) {
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
if (!state.expanded) {
|
|
316
|
-
state.ui.root.style.width = "auto";
|
|
317
|
-
state.ui.panel.style.width = "min(565px, calc(100vw - 24px))";
|
|
318
|
-
state.ui.panel.style.height = "auto";
|
|
319
|
-
state.ui.entries.style.maxHeight = "min(36vh, 280px)";
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
if (!state.panelSize) {
|
|
323
|
-
state.ui.root.style.width = "min(565px, calc(100vw - 24px))";
|
|
324
|
-
state.ui.panel.style.width = "min(565px, calc(100vw - 24px))";
|
|
325
|
-
state.ui.panel.style.height = "auto";
|
|
326
|
-
state.ui.entries.style.maxHeight = "min(36vh, 280px)";
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
const nextSize = clampPanelSize(
|
|
330
|
-
state.panelSize
|
|
331
|
-
);
|
|
332
|
-
state.panelSize = nextSize;
|
|
333
|
-
state.ui.root.style.width = nextSize.width + "px";
|
|
334
|
-
state.ui.panel.style.width = "100%";
|
|
335
|
-
state.ui.panel.style.height = nextSize.height + "px";
|
|
336
|
-
state.ui.entries.style.maxHeight = Math.max(72, nextSize.height - 88) + "px";
|
|
337
|
-
}
|
|
338
|
-
function clampPosition(point, state) {
|
|
339
|
-
const viewport = getViewportSize();
|
|
340
|
-
const size = getOverlaySize(state);
|
|
341
|
-
const maxX = Math.max(OVERLAY_MARGIN, viewport.width - size.width - OVERLAY_MARGIN);
|
|
342
|
-
const maxY = Math.max(
|
|
343
|
-
OVERLAY_MARGIN,
|
|
344
|
-
viewport.height - size.height - OVERLAY_MARGIN
|
|
345
|
-
);
|
|
346
|
-
return {
|
|
347
|
-
x: Math.min(maxX, Math.max(OVERLAY_MARGIN, point.x)),
|
|
348
|
-
y: Math.min(maxY, Math.max(OVERLAY_MARGIN, point.y))
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
function applyOverlayPosition(state) {
|
|
352
|
-
if (!state.ui) {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
if (!state.position) {
|
|
356
|
-
const viewport = getViewportSize();
|
|
357
|
-
const size = getOverlaySize(state);
|
|
358
|
-
state.position = clampPosition(
|
|
359
|
-
{
|
|
360
|
-
x: viewport.width - size.width - OVERLAY_MARGIN,
|
|
361
|
-
y: viewport.height - size.height - OVERLAY_MARGIN
|
|
362
|
-
},
|
|
363
|
-
state
|
|
364
|
-
);
|
|
365
|
-
} else {
|
|
366
|
-
state.position = clampPosition(state.position, state);
|
|
367
|
-
}
|
|
368
|
-
state.ui.root.style.left = state.position.x + "px";
|
|
369
|
-
state.ui.root.style.top = state.position.y + "px";
|
|
370
|
-
}
|
|
371
|
-
function getPointFromMouseEvent(event) {
|
|
372
|
-
return { x: event.clientX, y: event.clientY };
|
|
373
|
-
}
|
|
374
|
-
function getPointFromTouchEvent(event) {
|
|
375
|
-
const touch = event.touches[0] ?? event.changedTouches[0];
|
|
376
|
-
if (!touch) {
|
|
377
|
-
return null;
|
|
378
|
-
}
|
|
379
|
-
return { x: touch.clientX, y: touch.clientY };
|
|
380
|
-
}
|
|
381
|
-
function stopDragging(state) {
|
|
382
|
-
if (state.isDragging || state.isResizing) {
|
|
383
|
-
state.suppressToggleClickUntil = Date.now() + 180;
|
|
384
|
-
}
|
|
385
|
-
state.isDragging = false;
|
|
386
|
-
state.dragStartPoint = null;
|
|
387
|
-
state.lastDragPoint = null;
|
|
388
|
-
state.removeDragListeners?.();
|
|
389
|
-
state.removeDragListeners = null;
|
|
390
|
-
if (state.ui) {
|
|
391
|
-
state.ui.panel.style.cursor = "default";
|
|
392
|
-
state.ui.dragZone.style.cursor = "grab";
|
|
393
|
-
state.ui.toggleButton.style.cursor = "grab";
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
function stopResizing(state) {
|
|
397
|
-
if (state.isResizing) {
|
|
398
|
-
state.suppressToggleClickUntil = Date.now() + 180;
|
|
399
|
-
}
|
|
400
|
-
state.isResizing = false;
|
|
401
|
-
state.resizeStartPoint = null;
|
|
402
|
-
state.resizeStartSize = null;
|
|
403
|
-
state.removeResizeListeners?.();
|
|
404
|
-
state.removeResizeListeners = null;
|
|
405
|
-
}
|
|
406
|
-
function beginDragTracking(state, startPoint) {
|
|
407
|
-
const doc = getDocument();
|
|
408
|
-
if (!doc) {
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
stopResizing(state);
|
|
412
|
-
stopDragging(state);
|
|
413
|
-
state.dragMoved = false;
|
|
414
|
-
state.dragStartPoint = startPoint;
|
|
415
|
-
state.lastDragPoint = startPoint;
|
|
416
|
-
const handlePointerMove = (nextPoint) => {
|
|
417
|
-
if (!state.dragStartPoint || !state.lastDragPoint || !nextPoint) {
|
|
418
|
-
return;
|
|
419
|
-
}
|
|
420
|
-
if (!state.isDragging) {
|
|
421
|
-
const deltaFromStartX = nextPoint.x - state.dragStartPoint.x;
|
|
422
|
-
const deltaFromStartY = nextPoint.y - state.dragStartPoint.y;
|
|
423
|
-
const distance = Math.sqrt(
|
|
424
|
-
deltaFromStartX * deltaFromStartX + deltaFromStartY * deltaFromStartY
|
|
425
|
-
);
|
|
426
|
-
if (distance < DRAG_THRESHOLD_PX) {
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
429
|
-
state.isDragging = true;
|
|
430
|
-
state.dragMoved = true;
|
|
431
|
-
if (state.ui) {
|
|
432
|
-
state.ui.panel.style.cursor = "grabbing";
|
|
433
|
-
state.ui.dragZone.style.cursor = "grabbing";
|
|
434
|
-
state.ui.toggleButton.style.cursor = "grabbing";
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
const currentPosition = state.position ?? { x: OVERLAY_MARGIN, y: OVERLAY_MARGIN };
|
|
438
|
-
state.position = clampPosition(
|
|
439
|
-
{
|
|
440
|
-
x: currentPosition.x + (nextPoint.x - state.lastDragPoint.x),
|
|
441
|
-
y: currentPosition.y + (nextPoint.y - state.lastDragPoint.y)
|
|
442
|
-
},
|
|
443
|
-
state
|
|
444
|
-
);
|
|
445
|
-
state.lastDragPoint = nextPoint;
|
|
446
|
-
applyOverlayPosition(state);
|
|
447
|
-
};
|
|
448
|
-
const handleMouseMove = (event) => {
|
|
449
|
-
handlePointerMove(getPointFromMouseEvent(event));
|
|
450
|
-
};
|
|
451
|
-
const handleTouchMove = (event) => {
|
|
452
|
-
handlePointerMove(getPointFromTouchEvent(event));
|
|
453
|
-
};
|
|
454
|
-
const handleMouseUp = () => {
|
|
455
|
-
stopDragging(state);
|
|
456
|
-
};
|
|
457
|
-
const handleTouchEnd = () => {
|
|
458
|
-
stopDragging(state);
|
|
459
|
-
};
|
|
460
|
-
doc.addEventListener("mousemove", handleMouseMove);
|
|
461
|
-
doc.addEventListener("mouseup", handleMouseUp);
|
|
462
|
-
doc.addEventListener("touchmove", handleTouchMove, { passive: true });
|
|
463
|
-
doc.addEventListener("touchend", handleTouchEnd);
|
|
464
|
-
doc.addEventListener("touchcancel", handleTouchEnd);
|
|
465
|
-
state.removeDragListeners = () => {
|
|
466
|
-
doc.removeEventListener("mousemove", handleMouseMove);
|
|
467
|
-
doc.removeEventListener("mouseup", handleMouseUp);
|
|
468
|
-
doc.removeEventListener("touchmove", handleTouchMove);
|
|
469
|
-
doc.removeEventListener("touchend", handleTouchEnd);
|
|
470
|
-
doc.removeEventListener("touchcancel", handleTouchEnd);
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
function startResizing(state, startPoint) {
|
|
474
|
-
const doc = getDocument();
|
|
475
|
-
if (!doc) {
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
stopDragging(state);
|
|
479
|
-
stopResizing(state);
|
|
480
|
-
state.isResizing = true;
|
|
481
|
-
state.resizeStartPoint = startPoint;
|
|
482
|
-
state.resizeStartSize = state.panelSize ?? clampPanelSize({ width: DEFAULT_EXPANDED_WIDTH, height: DEFAULT_EXPANDED_HEIGHT });
|
|
483
|
-
const handleResizeMove = (nextPoint) => {
|
|
484
|
-
if (!state.isResizing || !state.resizeStartPoint || !state.resizeStartSize || !nextPoint) {
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
|
-
state.panelSize = clampPanelSize({
|
|
488
|
-
width: state.resizeStartSize.width + (nextPoint.x - state.resizeStartPoint.x),
|
|
489
|
-
height: state.resizeStartSize.height + (nextPoint.y - state.resizeStartPoint.y)
|
|
490
|
-
});
|
|
491
|
-
applyPanelSize(state);
|
|
492
|
-
applyOverlayPosition(state);
|
|
493
|
-
};
|
|
494
|
-
const handleMouseMove = (event) => {
|
|
495
|
-
handleResizeMove(getPointFromMouseEvent(event));
|
|
496
|
-
};
|
|
497
|
-
const handleTouchMove = (event) => {
|
|
498
|
-
handleResizeMove(getPointFromTouchEvent(event));
|
|
499
|
-
};
|
|
500
|
-
const handleFinish = () => {
|
|
501
|
-
stopResizing(state);
|
|
502
|
-
};
|
|
503
|
-
doc.addEventListener("mousemove", handleMouseMove);
|
|
504
|
-
doc.addEventListener("mouseup", handleFinish);
|
|
505
|
-
doc.addEventListener("touchmove", handleTouchMove, { passive: true });
|
|
506
|
-
doc.addEventListener("touchend", handleFinish);
|
|
507
|
-
doc.addEventListener("touchcancel", handleFinish);
|
|
508
|
-
state.removeResizeListeners = () => {
|
|
509
|
-
doc.removeEventListener("mousemove", handleMouseMove);
|
|
510
|
-
doc.removeEventListener("mouseup", handleFinish);
|
|
511
|
-
doc.removeEventListener("touchmove", handleTouchMove);
|
|
512
|
-
doc.removeEventListener("touchend", handleFinish);
|
|
513
|
-
doc.removeEventListener("touchcancel", handleFinish);
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
function isInBottomRightResizeZone(element, point) {
|
|
517
|
-
const rect = element.getBoundingClientRect();
|
|
518
|
-
return point.x >= rect.right - RESIZE_HOTSPOT_PX && point.x <= rect.right && point.y >= rect.bottom - RESIZE_HOTSPOT_PX && point.y <= rect.bottom;
|
|
519
|
-
}
|
|
520
|
-
function canStartDragFromTarget(target) {
|
|
521
|
-
if (!(target instanceof Element)) {
|
|
522
|
-
return true;
|
|
523
|
-
}
|
|
524
|
-
if (target.closest("button") || target.closest("a") || target.closest("input") || target.closest("textarea") || target.closest("select")) {
|
|
525
|
-
return false;
|
|
526
|
-
}
|
|
527
|
-
return true;
|
|
528
|
-
}
|
|
529
|
-
function isInTopDragZone(element, point, zoneHeight) {
|
|
530
|
-
const rect = element.getBoundingClientRect();
|
|
531
|
-
return point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.top + zoneHeight;
|
|
532
|
-
}
|
|
533
|
-
function attachDragStartListeners(element, state, options = {}) {
|
|
534
|
-
element.addEventListener("mousedown", (event) => {
|
|
535
|
-
if (!options.allowInteractiveTarget && !canStartDragFromTarget(event.target)) {
|
|
536
|
-
return;
|
|
537
|
-
}
|
|
538
|
-
const point = getPointFromMouseEvent(event);
|
|
539
|
-
if (typeof options.topZoneHeight === "number" && !isInTopDragZone(element, point, options.topZoneHeight)) {
|
|
540
|
-
return;
|
|
541
|
-
}
|
|
542
|
-
beginDragTracking(state, point);
|
|
543
|
-
});
|
|
544
|
-
element.addEventListener("touchstart", (event) => {
|
|
545
|
-
if (!options.allowInteractiveTarget && !canStartDragFromTarget(event.target)) {
|
|
546
|
-
return;
|
|
547
|
-
}
|
|
548
|
-
const point = getPointFromTouchEvent(event);
|
|
549
|
-
if (!point) {
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
|
-
if (typeof options.topZoneHeight === "number" && !isInTopDragZone(element, point, options.topZoneHeight)) {
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
beginDragTracking(state, point);
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
function attachCollapsedToggleListeners(element, state) {
|
|
559
|
-
const startToggleInteraction = (startPoint) => {
|
|
560
|
-
const doc = getDocument();
|
|
561
|
-
if (!doc) {
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
beginDragTracking(state, startPoint);
|
|
565
|
-
const finishInteraction = () => {
|
|
566
|
-
releaseListeners();
|
|
567
|
-
if (state.dragMoved || Date.now() < state.suppressToggleClickUntil) {
|
|
568
|
-
return;
|
|
569
|
-
}
|
|
570
|
-
state.expanded = true;
|
|
571
|
-
state.unreadCount = 0;
|
|
572
|
-
renderOverlay(state);
|
|
573
|
-
};
|
|
574
|
-
const releaseListeners = () => {
|
|
575
|
-
doc.removeEventListener("mouseup", finishInteraction);
|
|
576
|
-
doc.removeEventListener("touchend", finishInteraction);
|
|
577
|
-
doc.removeEventListener("touchcancel", finishInteraction);
|
|
578
|
-
};
|
|
579
|
-
doc.addEventListener("mouseup", finishInteraction);
|
|
580
|
-
doc.addEventListener("touchend", finishInteraction);
|
|
581
|
-
doc.addEventListener("touchcancel", finishInteraction);
|
|
582
|
-
};
|
|
583
|
-
element.addEventListener("mousedown", (event) => {
|
|
584
|
-
event.preventDefault();
|
|
585
|
-
startToggleInteraction(getPointFromMouseEvent(event));
|
|
586
|
-
});
|
|
587
|
-
element.addEventListener("touchstart", (event) => {
|
|
588
|
-
const point = getPointFromTouchEvent(event);
|
|
589
|
-
if (!point) {
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
event.preventDefault();
|
|
593
|
-
startToggleInteraction(point);
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
function attachPanelResizeListeners(element, state) {
|
|
597
|
-
element.addEventListener("mousedown", (event) => {
|
|
598
|
-
if (!state.expanded || !canStartDragFromTarget(event.target)) {
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
601
|
-
const point = getPointFromMouseEvent(event);
|
|
602
|
-
if (!isInBottomRightResizeZone(element, point)) {
|
|
603
|
-
return;
|
|
604
|
-
}
|
|
605
|
-
event.preventDefault();
|
|
606
|
-
event.stopPropagation();
|
|
607
|
-
startResizing(state, point);
|
|
608
|
-
});
|
|
609
|
-
element.addEventListener("touchstart", (event) => {
|
|
610
|
-
if (!state.expanded || !canStartDragFromTarget(event.target)) {
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
const point = getPointFromTouchEvent(event);
|
|
614
|
-
if (!point || !isInBottomRightResizeZone(element, point)) {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
event.preventDefault();
|
|
618
|
-
event.stopPropagation();
|
|
619
|
-
startResizing(state, point);
|
|
620
|
-
});
|
|
621
|
-
}
|
|
622
|
-
function createOverlayUi(state) {
|
|
623
|
-
const root = document.createElement("div");
|
|
624
|
-
root.style.cssText = [
|
|
625
|
-
"position:fixed",
|
|
626
|
-
"left:12px",
|
|
627
|
-
"top:12px",
|
|
628
|
-
"z-index:2147483647",
|
|
629
|
-
"display:flex",
|
|
630
|
-
"flex-direction:column",
|
|
631
|
-
"align-items:stretch",
|
|
632
|
-
"gap:8px",
|
|
633
|
-
"width:min(565px, calc(100vw - 24px))",
|
|
634
|
-
"pointer-events:none"
|
|
635
|
-
].join(";");
|
|
636
|
-
const toggleButton = createButton("Logs");
|
|
637
|
-
toggleButton.style.pointerEvents = "auto";
|
|
638
|
-
toggleButton.style.alignSelf = "flex-end";
|
|
639
|
-
toggleButton.style.display = "inline-flex";
|
|
640
|
-
toggleButton.style.alignItems = "center";
|
|
641
|
-
toggleButton.style.justifyContent = "center";
|
|
642
|
-
toggleButton.style.minHeight = "40px";
|
|
643
|
-
toggleButton.style.minWidth = "76px";
|
|
644
|
-
toggleButton.style.padding = "8px 14px";
|
|
645
|
-
toggleButton.style.textAlign = "center";
|
|
646
|
-
toggleButton.style.border = "1px solid rgba(122, 212, 255, 0.22)";
|
|
647
|
-
toggleButton.style.background = "linear-gradient(180deg, rgba(13,31,54,0.98), rgba(8,19,37,0.98))";
|
|
648
|
-
toggleButton.style.boxShadow = "0 18px 40px rgba(4,12,24,0.34)";
|
|
649
|
-
toggleButton.style.cursor = "grab";
|
|
650
|
-
toggleButton.style.touchAction = "none";
|
|
651
|
-
const panel = document.createElement("div");
|
|
652
|
-
panel.style.cssText = [
|
|
653
|
-
"position:relative",
|
|
654
|
-
"display:flex",
|
|
655
|
-
"flex-direction:column",
|
|
656
|
-
"width:min(565px, calc(100vw - 24px))",
|
|
657
|
-
"max-height:min(48vh, 372px)",
|
|
658
|
-
"border-radius:18px",
|
|
659
|
-
"border:1px solid rgba(116,167,255,0.16)",
|
|
660
|
-
"background:linear-gradient(180deg, rgba(9,19,37,0.98), rgba(5,12,24,0.98))",
|
|
661
|
-
"box-shadow:0 28px 64px rgba(2,8,18,0.46)",
|
|
662
|
-
"backdrop-filter:blur(16px)",
|
|
663
|
-
"overflow:hidden",
|
|
664
|
-
"cursor:default",
|
|
665
|
-
"pointer-events:auto"
|
|
666
|
-
].join(";");
|
|
667
|
-
const dragZone = document.createElement("div");
|
|
668
|
-
dragZone.style.cssText = [
|
|
669
|
-
"position:absolute",
|
|
670
|
-
"top:0",
|
|
671
|
-
"left:0",
|
|
672
|
-
"right:0",
|
|
673
|
-
"height:" + String(TOP_DRAG_ZONE_PX) + "px",
|
|
674
|
-
"z-index:1",
|
|
675
|
-
"cursor:grab",
|
|
676
|
-
"background:transparent",
|
|
677
|
-
"pointer-events:auto"
|
|
678
|
-
].join(";");
|
|
679
|
-
const controls = document.createElement("div");
|
|
680
|
-
controls.style.cssText = [
|
|
681
|
-
"position:absolute",
|
|
682
|
-
"top:22px",
|
|
683
|
-
"right:22px",
|
|
684
|
-
"z-index:2",
|
|
685
|
-
"display:flex",
|
|
686
|
-
"align-items:center",
|
|
687
|
-
"gap:8px",
|
|
688
|
-
"pointer-events:auto"
|
|
689
|
-
].join(";");
|
|
690
|
-
const clearButton = createButton("Clear");
|
|
691
|
-
clearButton.style.background = "rgba(255,255,255,0.1)";
|
|
692
|
-
clearButton.style.border = "1px solid rgba(255,255,255,0.16)";
|
|
693
|
-
clearButton.style.color = "#eef6ff";
|
|
694
|
-
clearButton.style.minHeight = "30px";
|
|
695
|
-
clearButton.style.padding = "4px 9px";
|
|
696
|
-
clearButton.style.fontSize = "11px";
|
|
697
|
-
clearButton.style.backdropFilter = "blur(8px)";
|
|
698
|
-
const collapseButton = createButton("Hide");
|
|
699
|
-
collapseButton.style.background = "rgba(113, 171, 255, 0.12)";
|
|
700
|
-
collapseButton.style.border = "1px solid rgba(113, 171, 255, 0.2)";
|
|
701
|
-
collapseButton.style.color = "#d9ebff";
|
|
702
|
-
collapseButton.style.minHeight = "30px";
|
|
703
|
-
collapseButton.style.padding = "4px 9px";
|
|
704
|
-
collapseButton.style.fontSize = "11px";
|
|
705
|
-
collapseButton.style.backdropFilter = "blur(8px)";
|
|
706
|
-
const body = document.createElement("div");
|
|
707
|
-
body.style.cssText = [
|
|
708
|
-
"position:relative",
|
|
709
|
-
"display:flex",
|
|
710
|
-
"flex-direction:column",
|
|
711
|
-
"padding:12px",
|
|
712
|
-
"background:linear-gradient(180deg, rgba(4,10,20,0.88), rgba(3,8,18,0.98))",
|
|
713
|
-
"flex:1 1 auto",
|
|
714
|
-
"min-height:0"
|
|
715
|
-
].join(";");
|
|
716
|
-
const entries = document.createElement("div");
|
|
717
|
-
entries.style.cssText = [
|
|
718
|
-
"display:flex",
|
|
719
|
-
"flex-direction:column",
|
|
720
|
-
"gap:0",
|
|
721
|
-
"overflow:auto",
|
|
722
|
-
"flex:1 1 auto",
|
|
723
|
-
"min-height:96px",
|
|
724
|
-
"max-height:min(36vh, 280px)",
|
|
725
|
-
"padding:0",
|
|
726
|
-
"border:1px solid rgba(115,153,212,0.14)",
|
|
727
|
-
"border-radius:12px",
|
|
728
|
-
"background:rgba(4,10,20,0.82)"
|
|
729
|
-
].join(";");
|
|
730
|
-
const emptyState = document.createElement("div");
|
|
731
|
-
emptyState.style.cssText = [
|
|
732
|
-
"display:flex",
|
|
733
|
-
"align-items:center",
|
|
734
|
-
"justify-content:center",
|
|
735
|
-
"flex:1 1 auto",
|
|
736
|
-
"min-height:96px",
|
|
737
|
-
"color:rgba(204,222,250,0.6)",
|
|
738
|
-
"font:500 12px/1.5 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
|
|
739
|
-
"text-align:center",
|
|
740
|
-
"padding:18px"
|
|
741
|
-
].join(";");
|
|
742
|
-
emptyState.textContent = "Console output will appear here.";
|
|
743
|
-
collapseButton.addEventListener("click", (event) => {
|
|
744
|
-
event.stopPropagation();
|
|
745
|
-
state.expanded = false;
|
|
746
|
-
renderOverlay(state);
|
|
747
|
-
});
|
|
748
|
-
clearButton.addEventListener("click", (event) => {
|
|
749
|
-
event.stopPropagation();
|
|
750
|
-
state.entries = [];
|
|
751
|
-
state.unreadCount = 0;
|
|
752
|
-
renderOverlay(state);
|
|
753
|
-
});
|
|
754
|
-
controls.appendChild(clearButton);
|
|
755
|
-
controls.appendChild(collapseButton);
|
|
756
|
-
entries.appendChild(emptyState);
|
|
757
|
-
body.appendChild(entries);
|
|
758
|
-
body.appendChild(controls);
|
|
759
|
-
panel.appendChild(dragZone);
|
|
760
|
-
panel.appendChild(body);
|
|
761
|
-
attachDragStartListeners(dragZone, state);
|
|
762
|
-
attachPanelResizeListeners(panel, state);
|
|
763
|
-
attachCollapsedToggleListeners(toggleButton, state);
|
|
764
|
-
root.appendChild(panel);
|
|
765
|
-
root.appendChild(toggleButton);
|
|
766
|
-
return {
|
|
767
|
-
body,
|
|
768
|
-
clearButton,
|
|
769
|
-
collapseButton,
|
|
770
|
-
controls,
|
|
771
|
-
dragZone,
|
|
772
|
-
emptyState,
|
|
773
|
-
entries,
|
|
774
|
-
panel,
|
|
775
|
-
root,
|
|
776
|
-
toggleButton
|
|
777
|
-
};
|
|
778
|
-
}
|
|
779
|
-
function renderOverlay(state) {
|
|
780
|
-
if (!state.ui) {
|
|
781
|
-
return;
|
|
782
|
-
}
|
|
783
|
-
state.ui.panel.style.display = state.expanded ? "flex" : "none";
|
|
784
|
-
state.ui.toggleButton.style.display = state.expanded ? "none" : "inline-flex";
|
|
785
|
-
state.ui.toggleButton.textContent = "Logs";
|
|
786
|
-
if (state.entries.length === 0) {
|
|
787
|
-
state.ui.entries.style.display = "flex";
|
|
788
|
-
state.ui.emptyState.style.display = "flex";
|
|
789
|
-
state.ui.entries.replaceChildren(state.ui.emptyState);
|
|
790
|
-
applyPanelSize(state);
|
|
791
|
-
applyOverlayPosition(state);
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
794
|
-
state.ui.entries.style.display = "flex";
|
|
795
|
-
state.ui.emptyState.style.display = "none";
|
|
796
|
-
const nextChildren = state.entries.map((entry) => {
|
|
797
|
-
const accent = getLevelAccent(entry.level);
|
|
798
|
-
const row = document.createElement("div");
|
|
799
|
-
row.style.cssText = [
|
|
800
|
-
"display:flex",
|
|
801
|
-
"align-items:flex-start",
|
|
802
|
-
"gap:0",
|
|
803
|
-
"padding:4px 12px",
|
|
804
|
-
"background:" + accent.lineBackground
|
|
805
|
-
].join(";");
|
|
806
|
-
const line = document.createElement("div");
|
|
807
|
-
line.textContent = formatTimestamp(entry.timestamp) + " " + entry.level.toUpperCase() + " " + entry.message;
|
|
808
|
-
line.style.cssText = [
|
|
809
|
-
"color:#ecf4ff",
|
|
810
|
-
"font:500 12px/1.5 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
|
|
811
|
-
"white-space:pre-wrap",
|
|
812
|
-
"word-break:break-word",
|
|
813
|
-
"flex:1 1 auto"
|
|
814
|
-
].join(";");
|
|
815
|
-
row.appendChild(line);
|
|
816
|
-
return row;
|
|
817
|
-
});
|
|
818
|
-
state.ui.entries.replaceChildren(...nextChildren);
|
|
819
|
-
state.ui.entries.scrollTop = state.ui.entries.scrollHeight;
|
|
820
|
-
applyPanelSize(state);
|
|
821
|
-
applyOverlayPosition(state);
|
|
822
|
-
}
|
|
823
|
-
function mountOverlay(state) {
|
|
824
|
-
const doc = getDocument();
|
|
825
|
-
if (!doc?.body || state.ui) {
|
|
826
|
-
return;
|
|
827
|
-
}
|
|
828
|
-
state.ui = createOverlayUi(state);
|
|
829
|
-
doc.body.appendChild(state.ui.root);
|
|
830
|
-
applyPanelSize(state);
|
|
831
|
-
applyOverlayPosition(state);
|
|
832
|
-
renderOverlay(state);
|
|
833
|
-
}
|
|
834
|
-
function enqueueEntry(state, level, args) {
|
|
835
|
-
state.entries.push(createEntry(level, args, state.nextEntryId));
|
|
836
|
-
state.nextEntryId += 1;
|
|
837
|
-
if (state.entries.length > state.maxEntries) {
|
|
838
|
-
state.entries.splice(0, state.entries.length - state.maxEntries);
|
|
839
|
-
}
|
|
840
|
-
if (!state.expanded) {
|
|
841
|
-
state.unreadCount += 1;
|
|
842
|
-
}
|
|
843
|
-
renderOverlay(state);
|
|
844
|
-
}
|
|
845
|
-
function restoreConsole(snapshot) {
|
|
846
|
-
for (const method of CONSOLE_METHODS) {
|
|
847
|
-
console[method] = snapshot[method];
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
function patchConsole(state) {
|
|
851
|
-
for (const method of CONSOLE_METHODS) {
|
|
852
|
-
const original = state.originalConsole[method];
|
|
853
|
-
console[method] = (...args) => {
|
|
854
|
-
enqueueEntry(state, method, args);
|
|
855
|
-
original(...args);
|
|
856
|
-
};
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
function cleanupOverlay(browserWindow, state) {
|
|
860
|
-
restoreConsole(state.originalConsole);
|
|
861
|
-
stopResizing(state);
|
|
862
|
-
stopDragging(state);
|
|
863
|
-
if (state.domReadyHandler) {
|
|
864
|
-
getDocument()?.removeEventListener("DOMContentLoaded", state.domReadyHandler);
|
|
865
|
-
state.domReadyHandler = void 0;
|
|
866
|
-
}
|
|
867
|
-
if (state.resizeHandler && typeof browserWindow.removeEventListener === "function") {
|
|
868
|
-
browserWindow.removeEventListener("resize", state.resizeHandler);
|
|
869
|
-
state.resizeHandler = void 0;
|
|
870
|
-
}
|
|
871
|
-
state.ui?.root.remove();
|
|
872
|
-
state.ui = null;
|
|
873
|
-
delete browserWindow.__oasizLogOverlayController__;
|
|
874
|
-
delete browserWindow.__oasizLogOverlayState__;
|
|
875
|
-
}
|
|
876
|
-
function createController(browserWindow, state) {
|
|
877
|
-
return {
|
|
878
|
-
retain() {
|
|
879
|
-
state.refCount += 1;
|
|
880
|
-
this.ensureMounted();
|
|
881
|
-
},
|
|
882
|
-
ensureMounted() {
|
|
883
|
-
const doc = getDocument();
|
|
884
|
-
if (!doc) {
|
|
885
|
-
return;
|
|
886
|
-
}
|
|
887
|
-
if (doc.body) {
|
|
888
|
-
mountOverlay(state);
|
|
889
|
-
applyOverlayPosition(state);
|
|
890
|
-
return;
|
|
891
|
-
}
|
|
892
|
-
if (!state.domReadyHandler) {
|
|
893
|
-
state.domReadyHandler = () => {
|
|
894
|
-
mountOverlay(state);
|
|
895
|
-
state.domReadyHandler = void 0;
|
|
896
|
-
};
|
|
897
|
-
doc.addEventListener("DOMContentLoaded", state.domReadyHandler, {
|
|
898
|
-
once: true
|
|
899
|
-
});
|
|
900
|
-
}
|
|
901
|
-
},
|
|
902
|
-
clear() {
|
|
903
|
-
state.entries = [];
|
|
904
|
-
state.unreadCount = 0;
|
|
905
|
-
renderOverlay(state);
|
|
906
|
-
},
|
|
907
|
-
show() {
|
|
908
|
-
state.expanded = true;
|
|
909
|
-
state.unreadCount = 0;
|
|
910
|
-
renderOverlay(state);
|
|
911
|
-
},
|
|
912
|
-
hide() {
|
|
913
|
-
state.expanded = false;
|
|
914
|
-
renderOverlay(state);
|
|
915
|
-
},
|
|
916
|
-
isVisible() {
|
|
917
|
-
return state.expanded;
|
|
918
|
-
},
|
|
919
|
-
destroy() {
|
|
920
|
-
state.refCount = Math.max(0, state.refCount - 1);
|
|
921
|
-
if (state.refCount === 0) {
|
|
922
|
-
cleanupOverlay(browserWindow, state);
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
};
|
|
926
|
-
}
|
|
927
|
-
function enableLogOverlay(options = {}) {
|
|
928
|
-
if (options.enabled === false) {
|
|
929
|
-
return NOOP_HANDLE;
|
|
930
|
-
}
|
|
931
|
-
const browserWindow = getBrowserWindow();
|
|
932
|
-
const doc = getDocument();
|
|
933
|
-
if (!browserWindow || !doc) {
|
|
934
|
-
return NOOP_HANDLE;
|
|
935
|
-
}
|
|
936
|
-
const existingController = browserWindow.__oasizLogOverlayController__;
|
|
937
|
-
const existingState = browserWindow.__oasizLogOverlayState__;
|
|
938
|
-
if (existingController && existingState) {
|
|
939
|
-
existingController.retain();
|
|
940
|
-
if (typeof options.maxEntries === "number") {
|
|
941
|
-
existingState.maxEntries = clampMaxEntries(options.maxEntries);
|
|
942
|
-
if (existingState.entries.length > existingState.maxEntries) {
|
|
943
|
-
existingState.entries.splice(
|
|
944
|
-
0,
|
|
945
|
-
existingState.entries.length - existingState.maxEntries
|
|
946
|
-
);
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
if (typeof options.collapsed === "boolean") {
|
|
950
|
-
existingState.expanded = !options.collapsed;
|
|
951
|
-
applyPanelSize(existingState);
|
|
952
|
-
if (existingState.expanded) {
|
|
953
|
-
existingState.unreadCount = 0;
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
if (typeof options.title === "string" && options.title.trim().length > 0) {
|
|
957
|
-
existingState.title = options.title.trim();
|
|
958
|
-
}
|
|
959
|
-
existingController.ensureMounted();
|
|
960
|
-
renderOverlay(existingState);
|
|
961
|
-
return existingController;
|
|
962
|
-
}
|
|
963
|
-
const state = {
|
|
964
|
-
dragMoved: false,
|
|
965
|
-
dragStartPoint: null,
|
|
966
|
-
entries: [],
|
|
967
|
-
expanded: options.collapsed !== true,
|
|
968
|
-
isDragging: false,
|
|
969
|
-
isResizing: false,
|
|
970
|
-
lastDragPoint: null,
|
|
971
|
-
maxEntries: clampMaxEntries(options.maxEntries),
|
|
972
|
-
nextEntryId: 1,
|
|
973
|
-
originalConsole: createConsoleSnapshot(),
|
|
974
|
-
panelSize: null,
|
|
975
|
-
position: null,
|
|
976
|
-
refCount: 1,
|
|
977
|
-
removeDragListeners: null,
|
|
978
|
-
removeResizeListeners: null,
|
|
979
|
-
resizeStartPoint: null,
|
|
980
|
-
resizeStartSize: null,
|
|
981
|
-
suppressToggleClickUntil: 0,
|
|
982
|
-
title: typeof options.title === "string" && options.title.trim().length > 0 ? options.title.trim() : DEFAULT_TITLE,
|
|
983
|
-
resizeHandler: void 0,
|
|
984
|
-
ui: null,
|
|
985
|
-
unreadCount: 0
|
|
986
|
-
};
|
|
987
|
-
const controller = createController(browserWindow, state);
|
|
988
|
-
browserWindow.__oasizLogOverlayState__ = state;
|
|
989
|
-
browserWindow.__oasizLogOverlayController__ = controller;
|
|
990
|
-
patchConsole(state);
|
|
991
|
-
if (typeof browserWindow.addEventListener === "function") {
|
|
992
|
-
state.resizeHandler = () => {
|
|
993
|
-
applyOverlayPosition(state);
|
|
994
|
-
};
|
|
995
|
-
browserWindow.addEventListener("resize", state.resizeHandler);
|
|
996
|
-
}
|
|
997
|
-
controller.ensureMounted();
|
|
998
|
-
return controller;
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
78
|
// src/multiplayer.ts
|
|
1002
|
-
function
|
|
79
|
+
function isDevelopment2() {
|
|
1003
80
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1004
81
|
return nodeEnv !== "production";
|
|
1005
82
|
}
|
|
1006
|
-
function
|
|
83
|
+
function getBridgeWindow2() {
|
|
1007
84
|
if (typeof window === "undefined") {
|
|
1008
85
|
return void 0;
|
|
1009
86
|
}
|
|
1010
87
|
return window;
|
|
1011
88
|
}
|
|
1012
|
-
function shareRoomCode(roomCode
|
|
1013
|
-
const bridge =
|
|
89
|
+
function shareRoomCode(roomCode) {
|
|
90
|
+
const bridge = getBridgeWindow2();
|
|
1014
91
|
if (typeof bridge?.shareRoomCode === "function") {
|
|
1015
|
-
bridge.shareRoomCode(roomCode
|
|
92
|
+
bridge.shareRoomCode(roomCode);
|
|
1016
93
|
return;
|
|
1017
94
|
}
|
|
1018
|
-
if (
|
|
95
|
+
if (isDevelopment2()) {
|
|
1019
96
|
console.warn(
|
|
1020
97
|
"[oasiz/sdk] shareRoomCode bridge is unavailable. This is expected in local development."
|
|
1021
98
|
);
|
|
1022
99
|
}
|
|
1023
100
|
}
|
|
1024
|
-
function openInviteModal() {
|
|
1025
|
-
const bridge = getBridgeWindow3();
|
|
1026
|
-
if (typeof bridge?.openInviteModal === "function") {
|
|
1027
|
-
bridge.openInviteModal();
|
|
1028
|
-
return;
|
|
1029
|
-
}
|
|
1030
|
-
if (isDevelopment3()) {
|
|
1031
|
-
console.warn(
|
|
1032
|
-
"[oasiz/sdk] openInviteModal bridge is unavailable. This is expected in local development."
|
|
1033
|
-
);
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
101
|
function getGameId() {
|
|
1037
|
-
const bridge =
|
|
102
|
+
const bridge = getBridgeWindow2();
|
|
1038
103
|
return bridge?.__GAME_ID__;
|
|
1039
104
|
}
|
|
1040
105
|
function getRoomCode() {
|
|
1041
|
-
const bridge =
|
|
106
|
+
const bridge = getBridgeWindow2();
|
|
1042
107
|
return bridge?.__ROOM_CODE__;
|
|
1043
108
|
}
|
|
1044
|
-
function getPlayerId() {
|
|
1045
|
-
const bridge = getBridgeWindow3();
|
|
1046
|
-
return bridge?.__PLAYER_ID__;
|
|
1047
|
-
}
|
|
1048
109
|
function getPlayerName() {
|
|
1049
|
-
const bridge =
|
|
110
|
+
const bridge = getBridgeWindow2();
|
|
1050
111
|
return bridge?.__PLAYER_NAME__;
|
|
1051
112
|
}
|
|
1052
113
|
function getPlayerAvatar() {
|
|
1053
|
-
const bridge =
|
|
114
|
+
const bridge = getBridgeWindow2();
|
|
1054
115
|
return bridge?.__PLAYER_AVATAR__;
|
|
1055
116
|
}
|
|
1056
117
|
|
|
1057
118
|
// src/score.ts
|
|
1058
|
-
function
|
|
119
|
+
function isDevelopment3() {
|
|
1059
120
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1060
121
|
return nodeEnv !== "production";
|
|
1061
122
|
}
|
|
1062
|
-
function
|
|
1063
|
-
if (
|
|
123
|
+
function warnMissingBridge(methodName) {
|
|
124
|
+
if (isDevelopment3()) {
|
|
1064
125
|
console.warn(
|
|
1065
126
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1066
127
|
);
|
|
1067
128
|
}
|
|
1068
129
|
}
|
|
1069
|
-
function
|
|
130
|
+
function getBridgeWindow3() {
|
|
1070
131
|
if (typeof window === "undefined") {
|
|
1071
132
|
return void 0;
|
|
1072
133
|
}
|
|
@@ -1074,92 +135,41 @@ function getBridgeWindow4() {
|
|
|
1074
135
|
}
|
|
1075
136
|
function submitScore(score) {
|
|
1076
137
|
if (!Number.isFinite(score)) {
|
|
1077
|
-
if (
|
|
138
|
+
if (isDevelopment3()) {
|
|
1078
139
|
console.warn("[oasiz/sdk] submitScore expected a finite number:", score);
|
|
1079
140
|
}
|
|
1080
141
|
return;
|
|
1081
142
|
}
|
|
1082
|
-
const bridge =
|
|
143
|
+
const bridge = getBridgeWindow3();
|
|
1083
144
|
const normalizedScore = Math.max(0, Math.floor(score));
|
|
1084
145
|
if (typeof bridge?.submitScore === "function") {
|
|
1085
146
|
bridge.submitScore(normalizedScore);
|
|
1086
147
|
return;
|
|
1087
148
|
}
|
|
1088
|
-
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
// src/score-edit.ts
|
|
1092
|
-
function isDevelopment5() {
|
|
1093
|
-
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1094
|
-
return nodeEnv !== "production";
|
|
1095
|
-
}
|
|
1096
|
-
function getBridgeWindow5() {
|
|
1097
|
-
if (typeof window === "undefined") {
|
|
1098
|
-
return void 0;
|
|
1099
|
-
}
|
|
1100
|
-
return window;
|
|
1101
|
-
}
|
|
1102
|
-
function warnMissingBridge3(methodName) {
|
|
1103
|
-
if (isDevelopment5()) {
|
|
1104
|
-
console.warn(
|
|
1105
|
-
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1106
|
-
);
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
async function editScore(payload, methodName) {
|
|
1110
|
-
const bridge = getBridgeWindow5();
|
|
1111
|
-
if (typeof bridge?.__oasizEditScore !== "function") {
|
|
1112
|
-
warnMissingBridge3(methodName);
|
|
1113
|
-
return null;
|
|
1114
|
-
}
|
|
1115
|
-
try {
|
|
1116
|
-
const result = await bridge.__oasizEditScore(payload);
|
|
1117
|
-
return result ?? null;
|
|
1118
|
-
} catch (error) {
|
|
1119
|
-
if (isDevelopment5()) {
|
|
1120
|
-
console.error("[oasiz/sdk] " + methodName + " failed:", error);
|
|
1121
|
-
}
|
|
1122
|
-
return null;
|
|
1123
|
-
}
|
|
149
|
+
warnMissingBridge("submitScore");
|
|
1124
150
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
return null;
|
|
1131
|
-
}
|
|
1132
|
-
if (delta === 0) {
|
|
1133
|
-
return null;
|
|
1134
|
-
}
|
|
1135
|
-
return editScore({ delta }, "addScore");
|
|
1136
|
-
}
|
|
1137
|
-
async function setScore(score) {
|
|
1138
|
-
if (!Number.isInteger(score) || score < 0) {
|
|
1139
|
-
if (isDevelopment5()) {
|
|
1140
|
-
console.warn(
|
|
1141
|
-
"[oasiz/sdk] setScore expected a non-negative integer:",
|
|
1142
|
-
score
|
|
1143
|
-
);
|
|
1144
|
-
}
|
|
1145
|
-
return null;
|
|
151
|
+
function emitScoreConfig(config) {
|
|
152
|
+
const bridge = getBridgeWindow3();
|
|
153
|
+
if (typeof bridge?.emitScoreConfig === "function") {
|
|
154
|
+
bridge.emitScoreConfig(config);
|
|
155
|
+
return;
|
|
1146
156
|
}
|
|
1147
|
-
|
|
157
|
+
warnMissingBridge("emitScoreConfig");
|
|
1148
158
|
}
|
|
1149
159
|
|
|
1150
160
|
// src/share.ts
|
|
1151
|
-
function
|
|
161
|
+
function isDevelopment4() {
|
|
1152
162
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1153
163
|
return nodeEnv !== "production";
|
|
1154
164
|
}
|
|
1155
|
-
function
|
|
165
|
+
function getBridgeWindow4() {
|
|
1156
166
|
if (typeof window === "undefined") {
|
|
1157
167
|
return void 0;
|
|
1158
168
|
}
|
|
1159
169
|
return window;
|
|
1160
170
|
}
|
|
1161
|
-
function
|
|
1162
|
-
if (
|
|
171
|
+
function warnMissingBridge2(methodName) {
|
|
172
|
+
if (isDevelopment4()) {
|
|
1163
173
|
console.warn(
|
|
1164
174
|
"[oasiz/sdk] " + methodName + " share bridge is unavailable. This is expected in local development."
|
|
1165
175
|
);
|
|
@@ -1202,20 +212,20 @@ function validateRequest(options) {
|
|
|
1202
212
|
}
|
|
1203
213
|
async function share(options) {
|
|
1204
214
|
const request = validateRequest(options);
|
|
1205
|
-
const bridge =
|
|
215
|
+
const bridge = getBridgeWindow4();
|
|
1206
216
|
if (typeof bridge?.__oasizShareRequest !== "function") {
|
|
1207
|
-
|
|
217
|
+
warnMissingBridge2("__oasizShareRequest");
|
|
1208
218
|
throw new Error("Share bridge unavailable");
|
|
1209
219
|
}
|
|
1210
220
|
await bridge.__oasizShareRequest(request);
|
|
1211
221
|
}
|
|
1212
222
|
|
|
1213
223
|
// src/state.ts
|
|
1214
|
-
function
|
|
224
|
+
function isDevelopment5() {
|
|
1215
225
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1216
226
|
return nodeEnv !== "production";
|
|
1217
227
|
}
|
|
1218
|
-
function
|
|
228
|
+
function getBridgeWindow5() {
|
|
1219
229
|
if (typeof window === "undefined") {
|
|
1220
230
|
return void 0;
|
|
1221
231
|
}
|
|
@@ -1228,22 +238,22 @@ function isPlainObject(value) {
|
|
|
1228
238
|
const proto = Object.getPrototypeOf(value);
|
|
1229
239
|
return proto === Object.prototype || proto === null;
|
|
1230
240
|
}
|
|
1231
|
-
function
|
|
1232
|
-
if (
|
|
241
|
+
function warnMissingBridge3(methodName) {
|
|
242
|
+
if (isDevelopment5()) {
|
|
1233
243
|
console.warn(
|
|
1234
244
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1235
245
|
);
|
|
1236
246
|
}
|
|
1237
247
|
}
|
|
1238
248
|
function loadGameState() {
|
|
1239
|
-
const bridge =
|
|
249
|
+
const bridge = getBridgeWindow5();
|
|
1240
250
|
if (typeof bridge?.loadGameState !== "function") {
|
|
1241
|
-
|
|
251
|
+
warnMissingBridge3("loadGameState");
|
|
1242
252
|
return {};
|
|
1243
253
|
}
|
|
1244
254
|
const state = bridge.loadGameState();
|
|
1245
255
|
if (!isPlainObject(state)) {
|
|
1246
|
-
if (
|
|
256
|
+
if (isDevelopment5()) {
|
|
1247
257
|
console.warn(
|
|
1248
258
|
"[oasiz/sdk] loadGameState returned invalid data. Falling back to empty object."
|
|
1249
259
|
);
|
|
@@ -1254,35 +264,35 @@ function loadGameState() {
|
|
|
1254
264
|
}
|
|
1255
265
|
function saveGameState(state) {
|
|
1256
266
|
if (!isPlainObject(state)) {
|
|
1257
|
-
if (
|
|
267
|
+
if (isDevelopment5()) {
|
|
1258
268
|
console.warn("[oasiz/sdk] saveGameState expected a plain object:", state);
|
|
1259
269
|
}
|
|
1260
270
|
return;
|
|
1261
271
|
}
|
|
1262
|
-
const bridge =
|
|
272
|
+
const bridge = getBridgeWindow5();
|
|
1263
273
|
if (typeof bridge?.saveGameState === "function") {
|
|
1264
274
|
bridge.saveGameState(state);
|
|
1265
275
|
return;
|
|
1266
276
|
}
|
|
1267
|
-
|
|
277
|
+
warnMissingBridge3("saveGameState");
|
|
1268
278
|
}
|
|
1269
279
|
function flushGameState() {
|
|
1270
|
-
const bridge =
|
|
280
|
+
const bridge = getBridgeWindow5();
|
|
1271
281
|
if (typeof bridge?.flushGameState === "function") {
|
|
1272
282
|
bridge.flushGameState();
|
|
1273
283
|
return;
|
|
1274
284
|
}
|
|
1275
|
-
|
|
285
|
+
warnMissingBridge3("flushGameState");
|
|
1276
286
|
}
|
|
1277
287
|
|
|
1278
288
|
// src/lifecycle.ts
|
|
1279
|
-
function
|
|
289
|
+
function isDevelopment6() {
|
|
1280
290
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1281
291
|
return nodeEnv !== "production";
|
|
1282
292
|
}
|
|
1283
293
|
function addLifecycleListener(eventName, callback) {
|
|
1284
294
|
if (typeof window === "undefined") {
|
|
1285
|
-
if (
|
|
295
|
+
if (isDevelopment6()) {
|
|
1286
296
|
console.warn(
|
|
1287
297
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
1288
298
|
);
|
|
@@ -1301,217 +311,20 @@ function onResume(callback) {
|
|
|
1301
311
|
return addLifecycleListener("oasiz:resume", callback);
|
|
1302
312
|
}
|
|
1303
313
|
|
|
1304
|
-
// src/layout.ts
|
|
1305
|
-
function isDevelopment9() {
|
|
1306
|
-
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1307
|
-
return nodeEnv !== "production";
|
|
1308
|
-
}
|
|
1309
|
-
function getBridgeWindow8() {
|
|
1310
|
-
if (typeof window === "undefined") {
|
|
1311
|
-
return void 0;
|
|
1312
|
-
}
|
|
1313
|
-
return window;
|
|
1314
|
-
}
|
|
1315
|
-
function warnMissingBridge6(methodName) {
|
|
1316
|
-
if (isDevelopment9()) {
|
|
1317
|
-
console.warn(
|
|
1318
|
-
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1319
|
-
);
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
function toFiniteNumber(value) {
|
|
1323
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1324
|
-
if (typeof value !== "string") {
|
|
1325
|
-
return void 0;
|
|
1326
|
-
}
|
|
1327
|
-
const parsed = Number.parseFloat(value.trim());
|
|
1328
|
-
if (!Number.isFinite(parsed)) {
|
|
1329
|
-
return void 0;
|
|
1330
|
-
}
|
|
1331
|
-
return parsed;
|
|
1332
|
-
}
|
|
1333
|
-
return value;
|
|
1334
|
-
}
|
|
1335
|
-
function clampSafeAreaTopPixels(value) {
|
|
1336
|
-
const numeric = toFiniteNumber(value);
|
|
1337
|
-
if (typeof numeric === "undefined") {
|
|
1338
|
-
return 0;
|
|
1339
|
-
}
|
|
1340
|
-
return Math.max(0, numeric);
|
|
1341
|
-
}
|
|
1342
|
-
function normalizeSafeAreaTopPercent(value) {
|
|
1343
|
-
const numeric = toFiniteNumber(value);
|
|
1344
|
-
if (typeof numeric === "undefined") {
|
|
1345
|
-
return void 0;
|
|
1346
|
-
}
|
|
1347
|
-
return Math.min(100, Math.max(0, numeric));
|
|
1348
|
-
}
|
|
1349
|
-
function getViewportHeight(bridge) {
|
|
1350
|
-
const visualViewportHeight = bridge.visualViewport?.height;
|
|
1351
|
-
if (typeof visualViewportHeight === "number" && Number.isFinite(visualViewportHeight) && visualViewportHeight > 0) {
|
|
1352
|
-
return visualViewportHeight;
|
|
1353
|
-
}
|
|
1354
|
-
const innerHeight = bridge.innerHeight;
|
|
1355
|
-
if (typeof innerHeight === "number" && Number.isFinite(innerHeight) && innerHeight > 0) {
|
|
1356
|
-
return innerHeight;
|
|
1357
|
-
}
|
|
1358
|
-
const documentHeight = bridge.document?.documentElement?.clientHeight;
|
|
1359
|
-
if (typeof documentHeight === "number" && Number.isFinite(documentHeight) && documentHeight > 0) {
|
|
1360
|
-
return documentHeight;
|
|
1361
|
-
}
|
|
1362
|
-
const bodyHeight = bridge.document?.body?.clientHeight;
|
|
1363
|
-
if (typeof bodyHeight === "number" && Number.isFinite(bodyHeight) && bodyHeight > 0) {
|
|
1364
|
-
return bodyHeight;
|
|
1365
|
-
}
|
|
1366
|
-
return 0;
|
|
1367
|
-
}
|
|
1368
|
-
function readCssSafeAreaValue(bridge, cssValue) {
|
|
1369
|
-
const doc = bridge.document;
|
|
1370
|
-
const root = doc?.body ?? doc?.documentElement;
|
|
1371
|
-
if (!doc || !root || typeof doc.createElement !== "function" || typeof root.appendChild !== "function" || typeof bridge.getComputedStyle !== "function") {
|
|
1372
|
-
return 0;
|
|
1373
|
-
}
|
|
1374
|
-
const probe = doc.createElement("div");
|
|
1375
|
-
probe.style.position = "fixed";
|
|
1376
|
-
probe.style.top = "0";
|
|
1377
|
-
probe.style.left = "0";
|
|
1378
|
-
probe.style.width = "0";
|
|
1379
|
-
probe.style.height = "0";
|
|
1380
|
-
probe.style.visibility = "hidden";
|
|
1381
|
-
probe.style.pointerEvents = "none";
|
|
1382
|
-
probe.style.paddingTop = cssValue;
|
|
1383
|
-
root.appendChild(probe);
|
|
1384
|
-
try {
|
|
1385
|
-
return clampSafeAreaTopPixels(bridge.getComputedStyle(probe).paddingTop);
|
|
1386
|
-
} finally {
|
|
1387
|
-
if (typeof probe.remove === "function") {
|
|
1388
|
-
probe.remove();
|
|
1389
|
-
} else {
|
|
1390
|
-
probe.parentNode?.removeChild(probe);
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
function readCssSafeAreaTopPixels(bridge) {
|
|
1395
|
-
const envPixels = readCssSafeAreaValue(bridge, "env(safe-area-inset-top)");
|
|
1396
|
-
if (envPixels > 0) {
|
|
1397
|
-
return envPixels;
|
|
1398
|
-
}
|
|
1399
|
-
return readCssSafeAreaValue(bridge, "constant(safe-area-inset-top)");
|
|
1400
|
-
}
|
|
1401
|
-
function getDevicePixelRatio(bridge) {
|
|
1402
|
-
const dpr = bridge.devicePixelRatio;
|
|
1403
|
-
if (typeof dpr !== "number" || !Number.isFinite(dpr) || dpr <= 0) {
|
|
1404
|
-
return 1;
|
|
1405
|
-
}
|
|
1406
|
-
return dpr;
|
|
1407
|
-
}
|
|
1408
|
-
function roughlyEqualPixels(a, b) {
|
|
1409
|
-
return Math.abs(a - b) <= 2;
|
|
1410
|
-
}
|
|
1411
|
-
function normalizeSafeAreaTopPixels(value, bridge) {
|
|
1412
|
-
const pixels = clampSafeAreaTopPixels(value);
|
|
1413
|
-
const cssEnvPixels = readCssSafeAreaTopPixels(bridge);
|
|
1414
|
-
if (pixels <= 0) {
|
|
1415
|
-
return cssEnvPixels;
|
|
1416
|
-
}
|
|
1417
|
-
const dpr = getDevicePixelRatio(bridge);
|
|
1418
|
-
if (cssEnvPixels > 0 && dpr > 1 && roughlyEqualPixels(pixels / dpr, cssEnvPixels)) {
|
|
1419
|
-
return cssEnvPixels;
|
|
1420
|
-
}
|
|
1421
|
-
return pixels;
|
|
1422
|
-
}
|
|
1423
|
-
function pixelsTopToPercentOfViewport(pixels, bridge) {
|
|
1424
|
-
const h = getViewportHeight(bridge);
|
|
1425
|
-
if (h <= 0) {
|
|
1426
|
-
return 0;
|
|
1427
|
-
}
|
|
1428
|
-
return normalizeSafeAreaTopPercent(pixels / h * 100) ?? 0;
|
|
1429
|
-
}
|
|
1430
|
-
function cssSafeAreaTopPercent(bridge) {
|
|
1431
|
-
return pixelsTopToPercentOfViewport(readCssSafeAreaTopPixels(bridge), bridge);
|
|
1432
|
-
}
|
|
1433
|
-
function resolvePercentValue(value, bridge) {
|
|
1434
|
-
const percent = normalizeSafeAreaTopPercent(value);
|
|
1435
|
-
if (typeof percent === "undefined") {
|
|
1436
|
-
return void 0;
|
|
1437
|
-
}
|
|
1438
|
-
return percent > 0 ? percent : cssSafeAreaTopPercent(bridge);
|
|
1439
|
-
}
|
|
1440
|
-
function resolvePixelValue(value, bridge) {
|
|
1441
|
-
const numeric = toFiniteNumber(value);
|
|
1442
|
-
if (typeof numeric === "undefined") {
|
|
1443
|
-
return void 0;
|
|
1444
|
-
}
|
|
1445
|
-
return pixelsTopToPercentOfViewport(normalizeSafeAreaTopPixels(numeric, bridge), bridge);
|
|
1446
|
-
}
|
|
1447
|
-
function getSafeAreaTop() {
|
|
1448
|
-
const bridge = getBridgeWindow8();
|
|
1449
|
-
if (!bridge) {
|
|
1450
|
-
return 0;
|
|
1451
|
-
}
|
|
1452
|
-
if (typeof bridge.getSafeAreaTopPercent === "function") {
|
|
1453
|
-
const percent = resolvePercentValue(bridge.getSafeAreaTopPercent(), bridge);
|
|
1454
|
-
if (typeof percent !== "undefined") {
|
|
1455
|
-
return percent;
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
if (typeof bridge.__OASIZ_SAFE_AREA_TOP_PERCENT__ !== "undefined") {
|
|
1459
|
-
const percent = resolvePercentValue(bridge.__OASIZ_SAFE_AREA_TOP_PERCENT__, bridge);
|
|
1460
|
-
if (typeof percent !== "undefined") {
|
|
1461
|
-
return percent;
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
if (typeof bridge.getSafeAreaTop === "function") {
|
|
1465
|
-
const percent = resolvePixelValue(bridge.getSafeAreaTop(), bridge);
|
|
1466
|
-
if (typeof percent !== "undefined") {
|
|
1467
|
-
return percent;
|
|
1468
|
-
}
|
|
1469
|
-
}
|
|
1470
|
-
if (typeof bridge.__OASIZ_SAFE_AREA_TOP__ !== "undefined") {
|
|
1471
|
-
const percent = resolvePixelValue(bridge.__OASIZ_SAFE_AREA_TOP__, bridge);
|
|
1472
|
-
if (typeof percent !== "undefined") {
|
|
1473
|
-
return percent;
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
const cssPercent = cssSafeAreaTopPercent(bridge);
|
|
1477
|
-
if (cssPercent > 0) {
|
|
1478
|
-
return cssPercent;
|
|
1479
|
-
}
|
|
1480
|
-
warnMissingBridge6("getSafeAreaTop");
|
|
1481
|
-
return 0;
|
|
1482
|
-
}
|
|
1483
|
-
function setLeaderboardVisible(visible) {
|
|
1484
|
-
if (typeof visible !== "boolean") {
|
|
1485
|
-
if (isDevelopment9()) {
|
|
1486
|
-
console.warn(
|
|
1487
|
-
"[oasiz/sdk] setLeaderboardVisible expected a boolean:",
|
|
1488
|
-
visible
|
|
1489
|
-
);
|
|
1490
|
-
}
|
|
1491
|
-
return;
|
|
1492
|
-
}
|
|
1493
|
-
const bridge = getBridgeWindow8();
|
|
1494
|
-
if (typeof bridge?.__oasizSetLeaderboardVisible === "function") {
|
|
1495
|
-
bridge.__oasizSetLeaderboardVisible(visible);
|
|
1496
|
-
return;
|
|
1497
|
-
}
|
|
1498
|
-
warnMissingBridge6("__oasizSetLeaderboardVisible");
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
314
|
// src/navigation.ts
|
|
1502
315
|
var activeBackListeners = 0;
|
|
1503
|
-
function
|
|
316
|
+
function isDevelopment7() {
|
|
1504
317
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1505
318
|
return nodeEnv !== "production";
|
|
1506
319
|
}
|
|
1507
|
-
function
|
|
320
|
+
function getBridgeWindow6() {
|
|
1508
321
|
if (typeof window === "undefined") {
|
|
1509
322
|
return void 0;
|
|
1510
323
|
}
|
|
1511
324
|
return window;
|
|
1512
325
|
}
|
|
1513
|
-
function
|
|
1514
|
-
if (
|
|
326
|
+
function warnMissingBridge4(methodName) {
|
|
327
|
+
if (isDevelopment7()) {
|
|
1515
328
|
console.warn(
|
|
1516
329
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1517
330
|
);
|
|
@@ -1527,7 +340,7 @@ function normalizeNavigationError(error) {
|
|
|
1527
340
|
}
|
|
1528
341
|
function addNavigationListener(eventName, callback) {
|
|
1529
342
|
if (typeof window === "undefined") {
|
|
1530
|
-
if (
|
|
343
|
+
if (isDevelopment7()) {
|
|
1531
344
|
console.warn(
|
|
1532
345
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
1533
346
|
);
|
|
@@ -1548,24 +361,24 @@ function onBackButton(callback) {
|
|
|
1548
361
|
throw normalizeNavigationError(error);
|
|
1549
362
|
}
|
|
1550
363
|
});
|
|
1551
|
-
const bridge =
|
|
364
|
+
const bridge = getBridgeWindow6();
|
|
1552
365
|
activeBackListeners += 1;
|
|
1553
366
|
if (activeBackListeners === 1) {
|
|
1554
367
|
if (typeof bridge?.__oasizSetBackOverride === "function") {
|
|
1555
368
|
bridge.__oasizSetBackOverride(true);
|
|
1556
369
|
} else {
|
|
1557
|
-
|
|
370
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
1558
371
|
}
|
|
1559
372
|
}
|
|
1560
373
|
return () => {
|
|
1561
374
|
off();
|
|
1562
375
|
activeBackListeners = Math.max(0, activeBackListeners - 1);
|
|
1563
376
|
if (activeBackListeners === 0) {
|
|
1564
|
-
const currentBridge =
|
|
377
|
+
const currentBridge = getBridgeWindow6();
|
|
1565
378
|
if (typeof currentBridge?.__oasizSetBackOverride === "function") {
|
|
1566
379
|
currentBridge.__oasizSetBackOverride(false);
|
|
1567
380
|
} else {
|
|
1568
|
-
|
|
381
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
1569
382
|
}
|
|
1570
383
|
}
|
|
1571
384
|
};
|
|
@@ -1574,79 +387,177 @@ function onLeaveGame(callback) {
|
|
|
1574
387
|
return addNavigationListener("oasiz:leave", callback);
|
|
1575
388
|
}
|
|
1576
389
|
function leaveGame() {
|
|
1577
|
-
const bridge =
|
|
390
|
+
const bridge = getBridgeWindow6();
|
|
1578
391
|
if (typeof bridge?.__oasizLeaveGame === "function") {
|
|
1579
392
|
bridge.__oasizLeaveGame();
|
|
1580
393
|
return;
|
|
1581
394
|
}
|
|
1582
|
-
|
|
395
|
+
warnMissingBridge4("__oasizLeaveGame");
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// src/store.ts
|
|
399
|
+
function isDevelopment8() {
|
|
400
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
401
|
+
return nodeEnv !== "production";
|
|
402
|
+
}
|
|
403
|
+
function getBridgeWindow7() {
|
|
404
|
+
if (typeof window === "undefined") {
|
|
405
|
+
return void 0;
|
|
406
|
+
}
|
|
407
|
+
return window;
|
|
408
|
+
}
|
|
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
|
+
);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
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");
|
|
421
|
+
}
|
|
422
|
+
return await bridge.__oasizStoreBridgeRequest({
|
|
423
|
+
action,
|
|
424
|
+
payload
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
async function getFreshState() {
|
|
428
|
+
return await requestStoreBridge("getStoreState");
|
|
429
|
+
}
|
|
430
|
+
function subscribeToStoreEvent(eventName, callback) {
|
|
431
|
+
if (typeof window === "undefined") {
|
|
432
|
+
return () => {
|
|
433
|
+
};
|
|
434
|
+
}
|
|
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);
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
async function syncProducts(products, expectedVersion) {
|
|
445
|
+
return await requestStoreBridge("syncProducts", {
|
|
446
|
+
expectedVersion: expectedVersion ?? null,
|
|
447
|
+
products
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
async function getProducts() {
|
|
451
|
+
const state = await getFreshState();
|
|
452
|
+
return state.products;
|
|
453
|
+
}
|
|
454
|
+
async function getEntitlements() {
|
|
455
|
+
const state = await getFreshState();
|
|
456
|
+
return state.entitlements;
|
|
457
|
+
}
|
|
458
|
+
async function hasEntitlement(productId) {
|
|
459
|
+
const state = await getFreshState();
|
|
460
|
+
return state.entitlements.find((item) => item.productId === productId)?.owned === true;
|
|
461
|
+
}
|
|
462
|
+
async function getQuantity(productId) {
|
|
463
|
+
const state = await getFreshState();
|
|
464
|
+
return state.entitlements.find((item) => item.productId === productId)?.quantity ?? 0;
|
|
465
|
+
}
|
|
466
|
+
async function purchase(productId, quantity = 1) {
|
|
467
|
+
return await requestStoreBridge("purchaseProduct", {
|
|
468
|
+
productId,
|
|
469
|
+
quantity
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
async function consume(productId, quantity = 1) {
|
|
473
|
+
return await requestStoreBridge("consumeProduct", {
|
|
474
|
+
productId,
|
|
475
|
+
quantity
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
async function getJemBalance() {
|
|
479
|
+
const state = await getFreshState();
|
|
480
|
+
return state.jemBalance;
|
|
481
|
+
}
|
|
482
|
+
function onEntitlementsChanged(callback) {
|
|
483
|
+
return subscribeToStoreEvent("oasiz:entitlements-changed", (state) => {
|
|
484
|
+
callback(state.entitlements);
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
function onJemBalanceChanged(callback) {
|
|
488
|
+
return subscribeToStoreEvent("oasiz:jem-balance-changed", (state) => {
|
|
489
|
+
callback(state.jemBalance);
|
|
490
|
+
});
|
|
1583
491
|
}
|
|
1584
492
|
|
|
1585
493
|
// src/index.ts
|
|
1586
494
|
var oasiz = {
|
|
1587
495
|
submitScore,
|
|
1588
|
-
|
|
1589
|
-
setScore,
|
|
1590
|
-
getPlayerCharacter,
|
|
496
|
+
emitScoreConfig,
|
|
1591
497
|
share,
|
|
1592
498
|
triggerHaptic,
|
|
1593
|
-
enableLogOverlay,
|
|
1594
499
|
loadGameState,
|
|
1595
500
|
saveGameState,
|
|
1596
501
|
flushGameState,
|
|
1597
502
|
shareRoomCode,
|
|
1598
|
-
openInviteModal,
|
|
1599
503
|
onPause,
|
|
1600
504
|
onResume,
|
|
1601
|
-
getSafeAreaTop,
|
|
1602
|
-
setLeaderboardVisible,
|
|
1603
505
|
onBackButton,
|
|
1604
506
|
onLeaveGame,
|
|
1605
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
|
+
},
|
|
1606
520
|
get gameId() {
|
|
1607
521
|
return getGameId();
|
|
1608
522
|
},
|
|
1609
523
|
get roomCode() {
|
|
1610
524
|
return getRoomCode();
|
|
1611
525
|
},
|
|
1612
|
-
get playerId() {
|
|
1613
|
-
return getPlayerId();
|
|
1614
|
-
},
|
|
1615
526
|
get playerName() {
|
|
1616
527
|
return getPlayerName();
|
|
1617
528
|
},
|
|
1618
529
|
get playerAvatar() {
|
|
1619
530
|
return getPlayerAvatar();
|
|
1620
|
-
},
|
|
1621
|
-
get safeAreaTop() {
|
|
1622
|
-
return getSafeAreaTop();
|
|
1623
531
|
}
|
|
1624
532
|
};
|
|
1625
533
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1626
534
|
0 && (module.exports = {
|
|
1627
|
-
|
|
1628
|
-
|
|
535
|
+
consume,
|
|
536
|
+
emitScoreConfig,
|
|
1629
537
|
flushGameState,
|
|
538
|
+
getEntitlements,
|
|
1630
539
|
getGameId,
|
|
540
|
+
getJemBalance,
|
|
1631
541
|
getPlayerAvatar,
|
|
1632
|
-
getPlayerCharacter,
|
|
1633
|
-
getPlayerId,
|
|
1634
542
|
getPlayerName,
|
|
543
|
+
getProducts,
|
|
544
|
+
getQuantity,
|
|
1635
545
|
getRoomCode,
|
|
1636
|
-
|
|
546
|
+
hasEntitlement,
|
|
1637
547
|
leaveGame,
|
|
1638
548
|
loadGameState,
|
|
1639
549
|
oasiz,
|
|
1640
550
|
onBackButton,
|
|
551
|
+
onEntitlementsChanged,
|
|
552
|
+
onJemBalanceChanged,
|
|
1641
553
|
onLeaveGame,
|
|
1642
554
|
onPause,
|
|
1643
555
|
onResume,
|
|
1644
|
-
|
|
556
|
+
purchase,
|
|
1645
557
|
saveGameState,
|
|
1646
|
-
setLeaderboardVisible,
|
|
1647
|
-
setScore,
|
|
1648
558
|
share,
|
|
1649
559
|
shareRoomCode,
|
|
1650
560
|
submitScore,
|
|
561
|
+
syncProducts,
|
|
1651
562
|
triggerHaptic
|
|
1652
563
|
});
|