@oasiz/sdk 1.2.1 → 1.4.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 +2 -63
- package/dist/index.cjs +129 -911
- package/dist/index.d.cts +96 -40
- package/dist/index.d.ts +96 -40
- package/dist/index.js +119 -909
- package/package.json +1 -1
- package/dist/index.global.js +0 -252
package/dist/index.js
CHANGED
|
@@ -22,897 +22,6 @@ function triggerHaptic(type) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
// src/log-overlay.ts
|
|
26
|
-
var CONSOLE_METHODS = [
|
|
27
|
-
"debug",
|
|
28
|
-
"log",
|
|
29
|
-
"info",
|
|
30
|
-
"warn",
|
|
31
|
-
"error"
|
|
32
|
-
];
|
|
33
|
-
var DEFAULT_MAX_ENTRIES = 200;
|
|
34
|
-
var DEFAULT_TITLE = "SDK Logs";
|
|
35
|
-
var OVERLAY_MARGIN = 12;
|
|
36
|
-
var DEFAULT_COLLAPSED_WIDTH = 156;
|
|
37
|
-
var DEFAULT_COLLAPSED_HEIGHT = 52;
|
|
38
|
-
var DEFAULT_EXPANDED_WIDTH = 565;
|
|
39
|
-
var DEFAULT_EXPANDED_HEIGHT = 372;
|
|
40
|
-
var DRAG_THRESHOLD_PX = 6;
|
|
41
|
-
var MIN_EXPANDED_WIDTH = 160;
|
|
42
|
-
var MIN_EXPANDED_HEIGHT = 110;
|
|
43
|
-
var RESIZE_HOTSPOT_PX = 28;
|
|
44
|
-
var TOP_DRAG_ZONE_PX = 44;
|
|
45
|
-
var NOOP_HANDLE = {
|
|
46
|
-
clear() {
|
|
47
|
-
},
|
|
48
|
-
destroy() {
|
|
49
|
-
},
|
|
50
|
-
hide() {
|
|
51
|
-
},
|
|
52
|
-
isVisible() {
|
|
53
|
-
return false;
|
|
54
|
-
},
|
|
55
|
-
show() {
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
function getBrowserWindow() {
|
|
59
|
-
if (typeof window === "undefined") {
|
|
60
|
-
return void 0;
|
|
61
|
-
}
|
|
62
|
-
return window;
|
|
63
|
-
}
|
|
64
|
-
function getDocument() {
|
|
65
|
-
if (typeof document === "undefined") {
|
|
66
|
-
return void 0;
|
|
67
|
-
}
|
|
68
|
-
return document;
|
|
69
|
-
}
|
|
70
|
-
function clampMaxEntries(value) {
|
|
71
|
-
if (!Number.isFinite(value)) {
|
|
72
|
-
return DEFAULT_MAX_ENTRIES;
|
|
73
|
-
}
|
|
74
|
-
return Math.max(10, Math.floor(value));
|
|
75
|
-
}
|
|
76
|
-
function createConsoleSnapshot() {
|
|
77
|
-
const fallback = console.log.bind(console);
|
|
78
|
-
return {
|
|
79
|
-
debug: typeof console.debug === "function" ? console.debug.bind(console) : fallback,
|
|
80
|
-
log: fallback,
|
|
81
|
-
info: typeof console.info === "function" ? console.info.bind(console) : fallback,
|
|
82
|
-
warn: typeof console.warn === "function" ? console.warn.bind(console) : fallback,
|
|
83
|
-
error: typeof console.error === "function" ? console.error.bind(console) : fallback
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
function formatTimestamp(timestamp) {
|
|
87
|
-
const date = new Date(timestamp);
|
|
88
|
-
const hours = String(date.getHours()).padStart(2, "0");
|
|
89
|
-
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
90
|
-
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
91
|
-
const milliseconds = String(date.getMilliseconds()).padStart(3, "0");
|
|
92
|
-
return "[" + hours + ":" + minutes + ":" + seconds + "." + milliseconds + "]";
|
|
93
|
-
}
|
|
94
|
-
function safeStringify(value) {
|
|
95
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
96
|
-
try {
|
|
97
|
-
return JSON.stringify(
|
|
98
|
-
value,
|
|
99
|
-
(_key, candidate) => {
|
|
100
|
-
if (typeof candidate === "bigint") {
|
|
101
|
-
return candidate.toString() + "n";
|
|
102
|
-
}
|
|
103
|
-
if (typeof candidate === "object" && candidate !== null) {
|
|
104
|
-
if (seen.has(candidate)) {
|
|
105
|
-
return "[Circular]";
|
|
106
|
-
}
|
|
107
|
-
seen.add(candidate);
|
|
108
|
-
}
|
|
109
|
-
return candidate;
|
|
110
|
-
},
|
|
111
|
-
2
|
|
112
|
-
) ?? String(value);
|
|
113
|
-
} catch {
|
|
114
|
-
return String(value);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function formatArg(value) {
|
|
118
|
-
if (typeof value === "string") {
|
|
119
|
-
return value;
|
|
120
|
-
}
|
|
121
|
-
if (value instanceof Error) {
|
|
122
|
-
if (value.stack) {
|
|
123
|
-
return value.stack;
|
|
124
|
-
}
|
|
125
|
-
return value.name + ": " + value.message;
|
|
126
|
-
}
|
|
127
|
-
if (typeof value === "undefined") {
|
|
128
|
-
return "undefined";
|
|
129
|
-
}
|
|
130
|
-
if (typeof value === "function") {
|
|
131
|
-
return "[Function " + (value.name || "anonymous") + "]";
|
|
132
|
-
}
|
|
133
|
-
return safeStringify(value);
|
|
134
|
-
}
|
|
135
|
-
function formatEntryMessage(args) {
|
|
136
|
-
const message = args.map(formatArg).join(" ");
|
|
137
|
-
if (message.length <= 4e3) {
|
|
138
|
-
return message;
|
|
139
|
-
}
|
|
140
|
-
return message.slice(0, 3997) + "...";
|
|
141
|
-
}
|
|
142
|
-
function createEntry(level, args, id) {
|
|
143
|
-
return {
|
|
144
|
-
id,
|
|
145
|
-
level,
|
|
146
|
-
message: formatEntryMessage(args),
|
|
147
|
-
timestamp: Date.now()
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
function createButton(label) {
|
|
151
|
-
const button = document.createElement("button");
|
|
152
|
-
button.type = "button";
|
|
153
|
-
button.textContent = label;
|
|
154
|
-
button.style.cssText = [
|
|
155
|
-
"appearance:none",
|
|
156
|
-
"border:1px solid rgba(255,255,255,0.18)",
|
|
157
|
-
"background:rgba(255,255,255,0.06)",
|
|
158
|
-
"color:#f8fafc",
|
|
159
|
-
"border-radius:999px",
|
|
160
|
-
"padding:6px 10px",
|
|
161
|
-
"font:600 12px/1.1 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
|
|
162
|
-
"cursor:pointer"
|
|
163
|
-
].join(";");
|
|
164
|
-
return button;
|
|
165
|
-
}
|
|
166
|
-
function getLevelAccent(level) {
|
|
167
|
-
if (level === "error") {
|
|
168
|
-
return {
|
|
169
|
-
lineBackground: "rgba(255, 109, 122, 0.08)"
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
if (level === "warn") {
|
|
173
|
-
return {
|
|
174
|
-
lineBackground: "rgba(255, 196, 94, 0.07)"
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
if (level === "info") {
|
|
178
|
-
return {
|
|
179
|
-
lineBackground: "rgba(82, 187, 255, 0.07)"
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
if (level === "debug") {
|
|
183
|
-
return {
|
|
184
|
-
lineBackground: "rgba(166, 137, 255, 0.07)"
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
return {
|
|
188
|
-
lineBackground: "rgba(117, 235, 191, 0.06)"
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
function getViewportSize() {
|
|
192
|
-
const browserWindow = getBrowserWindow();
|
|
193
|
-
return {
|
|
194
|
-
width: Math.max(320, browserWindow?.innerWidth ?? 1280),
|
|
195
|
-
height: Math.max(240, browserWindow?.innerHeight ?? 720)
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
function clampPanelSize(size) {
|
|
199
|
-
const viewport = getViewportSize();
|
|
200
|
-
const maxWidth = Math.max(MIN_EXPANDED_WIDTH, viewport.width - OVERLAY_MARGIN * 2);
|
|
201
|
-
const maxHeight = Math.max(
|
|
202
|
-
MIN_EXPANDED_HEIGHT,
|
|
203
|
-
viewport.height - OVERLAY_MARGIN * 2
|
|
204
|
-
);
|
|
205
|
-
return {
|
|
206
|
-
width: Math.min(maxWidth, Math.max(MIN_EXPANDED_WIDTH, size.width)),
|
|
207
|
-
height: Math.min(maxHeight, Math.max(MIN_EXPANDED_HEIGHT, size.height))
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
function getOverlaySize(state) {
|
|
211
|
-
if (state.expanded && state.panelSize) {
|
|
212
|
-
return state.panelSize;
|
|
213
|
-
}
|
|
214
|
-
const rect = state.ui?.root && typeof state.ui.root.getBoundingClientRect === "function" ? state.ui.root.getBoundingClientRect() : null;
|
|
215
|
-
if (rect && Number.isFinite(rect.width) && Number.isFinite(rect.height)) {
|
|
216
|
-
return {
|
|
217
|
-
width: Math.max(1, rect.width),
|
|
218
|
-
height: Math.max(1, rect.height)
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
return state.expanded ? clampPanelSize({
|
|
222
|
-
width: DEFAULT_EXPANDED_WIDTH,
|
|
223
|
-
height: DEFAULT_EXPANDED_HEIGHT
|
|
224
|
-
}) : { width: DEFAULT_COLLAPSED_WIDTH, height: DEFAULT_COLLAPSED_HEIGHT };
|
|
225
|
-
}
|
|
226
|
-
function applyPanelSize(state) {
|
|
227
|
-
if (!state.ui) {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
if (!state.expanded) {
|
|
231
|
-
state.ui.root.style.width = "auto";
|
|
232
|
-
state.ui.panel.style.width = "min(565px, calc(100vw - 24px))";
|
|
233
|
-
state.ui.panel.style.height = "auto";
|
|
234
|
-
state.ui.entries.style.maxHeight = "min(36vh, 280px)";
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
if (!state.panelSize) {
|
|
238
|
-
state.ui.root.style.width = "min(565px, calc(100vw - 24px))";
|
|
239
|
-
state.ui.panel.style.width = "min(565px, calc(100vw - 24px))";
|
|
240
|
-
state.ui.panel.style.height = "auto";
|
|
241
|
-
state.ui.entries.style.maxHeight = "min(36vh, 280px)";
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
const nextSize = clampPanelSize(
|
|
245
|
-
state.panelSize
|
|
246
|
-
);
|
|
247
|
-
state.panelSize = nextSize;
|
|
248
|
-
state.ui.root.style.width = nextSize.width + "px";
|
|
249
|
-
state.ui.panel.style.width = "100%";
|
|
250
|
-
state.ui.panel.style.height = nextSize.height + "px";
|
|
251
|
-
state.ui.entries.style.maxHeight = Math.max(72, nextSize.height - 88) + "px";
|
|
252
|
-
}
|
|
253
|
-
function clampPosition(point, state) {
|
|
254
|
-
const viewport = getViewportSize();
|
|
255
|
-
const size = getOverlaySize(state);
|
|
256
|
-
const maxX = Math.max(OVERLAY_MARGIN, viewport.width - size.width - OVERLAY_MARGIN);
|
|
257
|
-
const maxY = Math.max(
|
|
258
|
-
OVERLAY_MARGIN,
|
|
259
|
-
viewport.height - size.height - OVERLAY_MARGIN
|
|
260
|
-
);
|
|
261
|
-
return {
|
|
262
|
-
x: Math.min(maxX, Math.max(OVERLAY_MARGIN, point.x)),
|
|
263
|
-
y: Math.min(maxY, Math.max(OVERLAY_MARGIN, point.y))
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
function applyOverlayPosition(state) {
|
|
267
|
-
if (!state.ui) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
if (!state.position) {
|
|
271
|
-
const viewport = getViewportSize();
|
|
272
|
-
const size = getOverlaySize(state);
|
|
273
|
-
state.position = clampPosition(
|
|
274
|
-
{
|
|
275
|
-
x: viewport.width - size.width - OVERLAY_MARGIN,
|
|
276
|
-
y: viewport.height - size.height - OVERLAY_MARGIN
|
|
277
|
-
},
|
|
278
|
-
state
|
|
279
|
-
);
|
|
280
|
-
} else {
|
|
281
|
-
state.position = clampPosition(state.position, state);
|
|
282
|
-
}
|
|
283
|
-
state.ui.root.style.left = state.position.x + "px";
|
|
284
|
-
state.ui.root.style.top = state.position.y + "px";
|
|
285
|
-
}
|
|
286
|
-
function getPointFromMouseEvent(event) {
|
|
287
|
-
return { x: event.clientX, y: event.clientY };
|
|
288
|
-
}
|
|
289
|
-
function getPointFromTouchEvent(event) {
|
|
290
|
-
const touch = event.touches[0] ?? event.changedTouches[0];
|
|
291
|
-
if (!touch) {
|
|
292
|
-
return null;
|
|
293
|
-
}
|
|
294
|
-
return { x: touch.clientX, y: touch.clientY };
|
|
295
|
-
}
|
|
296
|
-
function stopDragging(state) {
|
|
297
|
-
if (state.isDragging || state.isResizing) {
|
|
298
|
-
state.suppressToggleClickUntil = Date.now() + 180;
|
|
299
|
-
}
|
|
300
|
-
state.isDragging = false;
|
|
301
|
-
state.dragStartPoint = null;
|
|
302
|
-
state.lastDragPoint = null;
|
|
303
|
-
state.removeDragListeners?.();
|
|
304
|
-
state.removeDragListeners = null;
|
|
305
|
-
if (state.ui) {
|
|
306
|
-
state.ui.panel.style.cursor = "default";
|
|
307
|
-
state.ui.dragZone.style.cursor = "grab";
|
|
308
|
-
state.ui.toggleButton.style.cursor = "grab";
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
function stopResizing(state) {
|
|
312
|
-
if (state.isResizing) {
|
|
313
|
-
state.suppressToggleClickUntil = Date.now() + 180;
|
|
314
|
-
}
|
|
315
|
-
state.isResizing = false;
|
|
316
|
-
state.resizeStartPoint = null;
|
|
317
|
-
state.resizeStartSize = null;
|
|
318
|
-
state.removeResizeListeners?.();
|
|
319
|
-
state.removeResizeListeners = null;
|
|
320
|
-
}
|
|
321
|
-
function beginDragTracking(state, startPoint) {
|
|
322
|
-
const doc = getDocument();
|
|
323
|
-
if (!doc) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
stopResizing(state);
|
|
327
|
-
stopDragging(state);
|
|
328
|
-
state.dragMoved = false;
|
|
329
|
-
state.dragStartPoint = startPoint;
|
|
330
|
-
state.lastDragPoint = startPoint;
|
|
331
|
-
const handlePointerMove = (nextPoint) => {
|
|
332
|
-
if (!state.dragStartPoint || !state.lastDragPoint || !nextPoint) {
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
if (!state.isDragging) {
|
|
336
|
-
const deltaFromStartX = nextPoint.x - state.dragStartPoint.x;
|
|
337
|
-
const deltaFromStartY = nextPoint.y - state.dragStartPoint.y;
|
|
338
|
-
const distance = Math.sqrt(
|
|
339
|
-
deltaFromStartX * deltaFromStartX + deltaFromStartY * deltaFromStartY
|
|
340
|
-
);
|
|
341
|
-
if (distance < DRAG_THRESHOLD_PX) {
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
state.isDragging = true;
|
|
345
|
-
state.dragMoved = true;
|
|
346
|
-
if (state.ui) {
|
|
347
|
-
state.ui.panel.style.cursor = "grabbing";
|
|
348
|
-
state.ui.dragZone.style.cursor = "grabbing";
|
|
349
|
-
state.ui.toggleButton.style.cursor = "grabbing";
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
const currentPosition = state.position ?? { x: OVERLAY_MARGIN, y: OVERLAY_MARGIN };
|
|
353
|
-
state.position = clampPosition(
|
|
354
|
-
{
|
|
355
|
-
x: currentPosition.x + (nextPoint.x - state.lastDragPoint.x),
|
|
356
|
-
y: currentPosition.y + (nextPoint.y - state.lastDragPoint.y)
|
|
357
|
-
},
|
|
358
|
-
state
|
|
359
|
-
);
|
|
360
|
-
state.lastDragPoint = nextPoint;
|
|
361
|
-
applyOverlayPosition(state);
|
|
362
|
-
};
|
|
363
|
-
const handleMouseMove = (event) => {
|
|
364
|
-
handlePointerMove(getPointFromMouseEvent(event));
|
|
365
|
-
};
|
|
366
|
-
const handleTouchMove = (event) => {
|
|
367
|
-
handlePointerMove(getPointFromTouchEvent(event));
|
|
368
|
-
};
|
|
369
|
-
const handleMouseUp = () => {
|
|
370
|
-
stopDragging(state);
|
|
371
|
-
};
|
|
372
|
-
const handleTouchEnd = () => {
|
|
373
|
-
stopDragging(state);
|
|
374
|
-
};
|
|
375
|
-
doc.addEventListener("mousemove", handleMouseMove);
|
|
376
|
-
doc.addEventListener("mouseup", handleMouseUp);
|
|
377
|
-
doc.addEventListener("touchmove", handleTouchMove, { passive: true });
|
|
378
|
-
doc.addEventListener("touchend", handleTouchEnd);
|
|
379
|
-
doc.addEventListener("touchcancel", handleTouchEnd);
|
|
380
|
-
state.removeDragListeners = () => {
|
|
381
|
-
doc.removeEventListener("mousemove", handleMouseMove);
|
|
382
|
-
doc.removeEventListener("mouseup", handleMouseUp);
|
|
383
|
-
doc.removeEventListener("touchmove", handleTouchMove);
|
|
384
|
-
doc.removeEventListener("touchend", handleTouchEnd);
|
|
385
|
-
doc.removeEventListener("touchcancel", handleTouchEnd);
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
function startResizing(state, startPoint) {
|
|
389
|
-
const doc = getDocument();
|
|
390
|
-
if (!doc) {
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
stopDragging(state);
|
|
394
|
-
stopResizing(state);
|
|
395
|
-
state.isResizing = true;
|
|
396
|
-
state.resizeStartPoint = startPoint;
|
|
397
|
-
state.resizeStartSize = state.panelSize ?? clampPanelSize({ width: DEFAULT_EXPANDED_WIDTH, height: DEFAULT_EXPANDED_HEIGHT });
|
|
398
|
-
const handleResizeMove = (nextPoint) => {
|
|
399
|
-
if (!state.isResizing || !state.resizeStartPoint || !state.resizeStartSize || !nextPoint) {
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
state.panelSize = clampPanelSize({
|
|
403
|
-
width: state.resizeStartSize.width + (nextPoint.x - state.resizeStartPoint.x),
|
|
404
|
-
height: state.resizeStartSize.height + (nextPoint.y - state.resizeStartPoint.y)
|
|
405
|
-
});
|
|
406
|
-
applyPanelSize(state);
|
|
407
|
-
applyOverlayPosition(state);
|
|
408
|
-
};
|
|
409
|
-
const handleMouseMove = (event) => {
|
|
410
|
-
handleResizeMove(getPointFromMouseEvent(event));
|
|
411
|
-
};
|
|
412
|
-
const handleTouchMove = (event) => {
|
|
413
|
-
handleResizeMove(getPointFromTouchEvent(event));
|
|
414
|
-
};
|
|
415
|
-
const handleFinish = () => {
|
|
416
|
-
stopResizing(state);
|
|
417
|
-
};
|
|
418
|
-
doc.addEventListener("mousemove", handleMouseMove);
|
|
419
|
-
doc.addEventListener("mouseup", handleFinish);
|
|
420
|
-
doc.addEventListener("touchmove", handleTouchMove, { passive: true });
|
|
421
|
-
doc.addEventListener("touchend", handleFinish);
|
|
422
|
-
doc.addEventListener("touchcancel", handleFinish);
|
|
423
|
-
state.removeResizeListeners = () => {
|
|
424
|
-
doc.removeEventListener("mousemove", handleMouseMove);
|
|
425
|
-
doc.removeEventListener("mouseup", handleFinish);
|
|
426
|
-
doc.removeEventListener("touchmove", handleTouchMove);
|
|
427
|
-
doc.removeEventListener("touchend", handleFinish);
|
|
428
|
-
doc.removeEventListener("touchcancel", handleFinish);
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
function isInBottomRightResizeZone(element, point) {
|
|
432
|
-
const rect = element.getBoundingClientRect();
|
|
433
|
-
return point.x >= rect.right - RESIZE_HOTSPOT_PX && point.x <= rect.right && point.y >= rect.bottom - RESIZE_HOTSPOT_PX && point.y <= rect.bottom;
|
|
434
|
-
}
|
|
435
|
-
function canStartDragFromTarget(target) {
|
|
436
|
-
if (!(target instanceof Element)) {
|
|
437
|
-
return true;
|
|
438
|
-
}
|
|
439
|
-
if (target.closest("button") || target.closest("a") || target.closest("input") || target.closest("textarea") || target.closest("select")) {
|
|
440
|
-
return false;
|
|
441
|
-
}
|
|
442
|
-
return true;
|
|
443
|
-
}
|
|
444
|
-
function isInTopDragZone(element, point, zoneHeight) {
|
|
445
|
-
const rect = element.getBoundingClientRect();
|
|
446
|
-
return point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.top + zoneHeight;
|
|
447
|
-
}
|
|
448
|
-
function attachDragStartListeners(element, state, options = {}) {
|
|
449
|
-
element.addEventListener("mousedown", (event) => {
|
|
450
|
-
if (!options.allowInteractiveTarget && !canStartDragFromTarget(event.target)) {
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
const point = getPointFromMouseEvent(event);
|
|
454
|
-
if (typeof options.topZoneHeight === "number" && !isInTopDragZone(element, point, options.topZoneHeight)) {
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
beginDragTracking(state, point);
|
|
458
|
-
});
|
|
459
|
-
element.addEventListener("touchstart", (event) => {
|
|
460
|
-
if (!options.allowInteractiveTarget && !canStartDragFromTarget(event.target)) {
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
const point = getPointFromTouchEvent(event);
|
|
464
|
-
if (!point) {
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
if (typeof options.topZoneHeight === "number" && !isInTopDragZone(element, point, options.topZoneHeight)) {
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
beginDragTracking(state, point);
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
function attachCollapsedToggleListeners(element, state) {
|
|
474
|
-
const startToggleInteraction = (startPoint) => {
|
|
475
|
-
const doc = getDocument();
|
|
476
|
-
if (!doc) {
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
beginDragTracking(state, startPoint);
|
|
480
|
-
const finishInteraction = () => {
|
|
481
|
-
releaseListeners();
|
|
482
|
-
if (state.dragMoved || Date.now() < state.suppressToggleClickUntil) {
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
state.expanded = true;
|
|
486
|
-
state.unreadCount = 0;
|
|
487
|
-
renderOverlay(state);
|
|
488
|
-
};
|
|
489
|
-
const releaseListeners = () => {
|
|
490
|
-
doc.removeEventListener("mouseup", finishInteraction);
|
|
491
|
-
doc.removeEventListener("touchend", finishInteraction);
|
|
492
|
-
doc.removeEventListener("touchcancel", finishInteraction);
|
|
493
|
-
};
|
|
494
|
-
doc.addEventListener("mouseup", finishInteraction);
|
|
495
|
-
doc.addEventListener("touchend", finishInteraction);
|
|
496
|
-
doc.addEventListener("touchcancel", finishInteraction);
|
|
497
|
-
};
|
|
498
|
-
element.addEventListener("mousedown", (event) => {
|
|
499
|
-
event.preventDefault();
|
|
500
|
-
startToggleInteraction(getPointFromMouseEvent(event));
|
|
501
|
-
});
|
|
502
|
-
element.addEventListener("touchstart", (event) => {
|
|
503
|
-
const point = getPointFromTouchEvent(event);
|
|
504
|
-
if (!point) {
|
|
505
|
-
return;
|
|
506
|
-
}
|
|
507
|
-
event.preventDefault();
|
|
508
|
-
startToggleInteraction(point);
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
function attachPanelResizeListeners(element, state) {
|
|
512
|
-
element.addEventListener("mousedown", (event) => {
|
|
513
|
-
if (!state.expanded || !canStartDragFromTarget(event.target)) {
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
const point = getPointFromMouseEvent(event);
|
|
517
|
-
if (!isInBottomRightResizeZone(element, point)) {
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
520
|
-
event.preventDefault();
|
|
521
|
-
event.stopPropagation();
|
|
522
|
-
startResizing(state, point);
|
|
523
|
-
});
|
|
524
|
-
element.addEventListener("touchstart", (event) => {
|
|
525
|
-
if (!state.expanded || !canStartDragFromTarget(event.target)) {
|
|
526
|
-
return;
|
|
527
|
-
}
|
|
528
|
-
const point = getPointFromTouchEvent(event);
|
|
529
|
-
if (!point || !isInBottomRightResizeZone(element, point)) {
|
|
530
|
-
return;
|
|
531
|
-
}
|
|
532
|
-
event.preventDefault();
|
|
533
|
-
event.stopPropagation();
|
|
534
|
-
startResizing(state, point);
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
function createOverlayUi(state) {
|
|
538
|
-
const root = document.createElement("div");
|
|
539
|
-
root.style.cssText = [
|
|
540
|
-
"position:fixed",
|
|
541
|
-
"left:12px",
|
|
542
|
-
"top:12px",
|
|
543
|
-
"z-index:2147483647",
|
|
544
|
-
"display:flex",
|
|
545
|
-
"flex-direction:column",
|
|
546
|
-
"align-items:stretch",
|
|
547
|
-
"gap:8px",
|
|
548
|
-
"width:min(565px, calc(100vw - 24px))",
|
|
549
|
-
"pointer-events:none"
|
|
550
|
-
].join(";");
|
|
551
|
-
const toggleButton = createButton("Logs");
|
|
552
|
-
toggleButton.style.pointerEvents = "auto";
|
|
553
|
-
toggleButton.style.alignSelf = "flex-end";
|
|
554
|
-
toggleButton.style.display = "inline-flex";
|
|
555
|
-
toggleButton.style.alignItems = "center";
|
|
556
|
-
toggleButton.style.justifyContent = "center";
|
|
557
|
-
toggleButton.style.minHeight = "40px";
|
|
558
|
-
toggleButton.style.minWidth = "76px";
|
|
559
|
-
toggleButton.style.padding = "8px 14px";
|
|
560
|
-
toggleButton.style.textAlign = "center";
|
|
561
|
-
toggleButton.style.border = "1px solid rgba(122, 212, 255, 0.22)";
|
|
562
|
-
toggleButton.style.background = "linear-gradient(180deg, rgba(13,31,54,0.98), rgba(8,19,37,0.98))";
|
|
563
|
-
toggleButton.style.boxShadow = "0 18px 40px rgba(4,12,24,0.34)";
|
|
564
|
-
toggleButton.style.cursor = "grab";
|
|
565
|
-
toggleButton.style.touchAction = "none";
|
|
566
|
-
const panel = document.createElement("div");
|
|
567
|
-
panel.style.cssText = [
|
|
568
|
-
"position:relative",
|
|
569
|
-
"display:flex",
|
|
570
|
-
"flex-direction:column",
|
|
571
|
-
"width:min(565px, calc(100vw - 24px))",
|
|
572
|
-
"max-height:min(48vh, 372px)",
|
|
573
|
-
"border-radius:18px",
|
|
574
|
-
"border:1px solid rgba(116,167,255,0.16)",
|
|
575
|
-
"background:linear-gradient(180deg, rgba(9,19,37,0.98), rgba(5,12,24,0.98))",
|
|
576
|
-
"box-shadow:0 28px 64px rgba(2,8,18,0.46)",
|
|
577
|
-
"backdrop-filter:blur(16px)",
|
|
578
|
-
"overflow:hidden",
|
|
579
|
-
"cursor:default",
|
|
580
|
-
"pointer-events:auto"
|
|
581
|
-
].join(";");
|
|
582
|
-
const dragZone = document.createElement("div");
|
|
583
|
-
dragZone.style.cssText = [
|
|
584
|
-
"position:absolute",
|
|
585
|
-
"top:0",
|
|
586
|
-
"left:0",
|
|
587
|
-
"right:0",
|
|
588
|
-
"height:" + String(TOP_DRAG_ZONE_PX) + "px",
|
|
589
|
-
"z-index:1",
|
|
590
|
-
"cursor:grab",
|
|
591
|
-
"background:transparent",
|
|
592
|
-
"pointer-events:auto"
|
|
593
|
-
].join(";");
|
|
594
|
-
const controls = document.createElement("div");
|
|
595
|
-
controls.style.cssText = [
|
|
596
|
-
"position:absolute",
|
|
597
|
-
"top:22px",
|
|
598
|
-
"right:22px",
|
|
599
|
-
"z-index:2",
|
|
600
|
-
"display:flex",
|
|
601
|
-
"align-items:center",
|
|
602
|
-
"gap:8px",
|
|
603
|
-
"pointer-events:auto"
|
|
604
|
-
].join(";");
|
|
605
|
-
const clearButton = createButton("Clear");
|
|
606
|
-
clearButton.style.background = "rgba(255,255,255,0.1)";
|
|
607
|
-
clearButton.style.border = "1px solid rgba(255,255,255,0.16)";
|
|
608
|
-
clearButton.style.color = "#eef6ff";
|
|
609
|
-
clearButton.style.minHeight = "30px";
|
|
610
|
-
clearButton.style.padding = "4px 9px";
|
|
611
|
-
clearButton.style.fontSize = "11px";
|
|
612
|
-
clearButton.style.backdropFilter = "blur(8px)";
|
|
613
|
-
const collapseButton = createButton("Hide");
|
|
614
|
-
collapseButton.style.background = "rgba(113, 171, 255, 0.12)";
|
|
615
|
-
collapseButton.style.border = "1px solid rgba(113, 171, 255, 0.2)";
|
|
616
|
-
collapseButton.style.color = "#d9ebff";
|
|
617
|
-
collapseButton.style.minHeight = "30px";
|
|
618
|
-
collapseButton.style.padding = "4px 9px";
|
|
619
|
-
collapseButton.style.fontSize = "11px";
|
|
620
|
-
collapseButton.style.backdropFilter = "blur(8px)";
|
|
621
|
-
const body = document.createElement("div");
|
|
622
|
-
body.style.cssText = [
|
|
623
|
-
"position:relative",
|
|
624
|
-
"display:flex",
|
|
625
|
-
"flex-direction:column",
|
|
626
|
-
"padding:12px",
|
|
627
|
-
"background:linear-gradient(180deg, rgba(4,10,20,0.88), rgba(3,8,18,0.98))",
|
|
628
|
-
"flex:1 1 auto",
|
|
629
|
-
"min-height:0"
|
|
630
|
-
].join(";");
|
|
631
|
-
const entries = document.createElement("div");
|
|
632
|
-
entries.style.cssText = [
|
|
633
|
-
"display:flex",
|
|
634
|
-
"flex-direction:column",
|
|
635
|
-
"gap:0",
|
|
636
|
-
"overflow:auto",
|
|
637
|
-
"flex:1 1 auto",
|
|
638
|
-
"min-height:96px",
|
|
639
|
-
"max-height:min(36vh, 280px)",
|
|
640
|
-
"padding:0",
|
|
641
|
-
"border:1px solid rgba(115,153,212,0.14)",
|
|
642
|
-
"border-radius:12px",
|
|
643
|
-
"background:rgba(4,10,20,0.82)"
|
|
644
|
-
].join(";");
|
|
645
|
-
const emptyState = document.createElement("div");
|
|
646
|
-
emptyState.style.cssText = [
|
|
647
|
-
"display:flex",
|
|
648
|
-
"align-items:center",
|
|
649
|
-
"justify-content:center",
|
|
650
|
-
"flex:1 1 auto",
|
|
651
|
-
"min-height:96px",
|
|
652
|
-
"color:rgba(204,222,250,0.6)",
|
|
653
|
-
"font:500 12px/1.5 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
|
|
654
|
-
"text-align:center",
|
|
655
|
-
"padding:18px"
|
|
656
|
-
].join(";");
|
|
657
|
-
emptyState.textContent = "Console output will appear here.";
|
|
658
|
-
collapseButton.addEventListener("click", (event) => {
|
|
659
|
-
event.stopPropagation();
|
|
660
|
-
state.expanded = false;
|
|
661
|
-
renderOverlay(state);
|
|
662
|
-
});
|
|
663
|
-
clearButton.addEventListener("click", (event) => {
|
|
664
|
-
event.stopPropagation();
|
|
665
|
-
state.entries = [];
|
|
666
|
-
state.unreadCount = 0;
|
|
667
|
-
renderOverlay(state);
|
|
668
|
-
});
|
|
669
|
-
controls.appendChild(clearButton);
|
|
670
|
-
controls.appendChild(collapseButton);
|
|
671
|
-
entries.appendChild(emptyState);
|
|
672
|
-
body.appendChild(entries);
|
|
673
|
-
body.appendChild(controls);
|
|
674
|
-
panel.appendChild(dragZone);
|
|
675
|
-
panel.appendChild(body);
|
|
676
|
-
attachDragStartListeners(dragZone, state);
|
|
677
|
-
attachPanelResizeListeners(panel, state);
|
|
678
|
-
attachCollapsedToggleListeners(toggleButton, state);
|
|
679
|
-
root.appendChild(panel);
|
|
680
|
-
root.appendChild(toggleButton);
|
|
681
|
-
return {
|
|
682
|
-
body,
|
|
683
|
-
clearButton,
|
|
684
|
-
collapseButton,
|
|
685
|
-
controls,
|
|
686
|
-
dragZone,
|
|
687
|
-
emptyState,
|
|
688
|
-
entries,
|
|
689
|
-
panel,
|
|
690
|
-
root,
|
|
691
|
-
toggleButton
|
|
692
|
-
};
|
|
693
|
-
}
|
|
694
|
-
function renderOverlay(state) {
|
|
695
|
-
if (!state.ui) {
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
state.ui.panel.style.display = state.expanded ? "flex" : "none";
|
|
699
|
-
state.ui.toggleButton.style.display = state.expanded ? "none" : "inline-flex";
|
|
700
|
-
state.ui.toggleButton.textContent = "Logs";
|
|
701
|
-
if (state.entries.length === 0) {
|
|
702
|
-
state.ui.entries.style.display = "flex";
|
|
703
|
-
state.ui.emptyState.style.display = "flex";
|
|
704
|
-
state.ui.entries.replaceChildren(state.ui.emptyState);
|
|
705
|
-
applyPanelSize(state);
|
|
706
|
-
applyOverlayPosition(state);
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
709
|
-
state.ui.entries.style.display = "flex";
|
|
710
|
-
state.ui.emptyState.style.display = "none";
|
|
711
|
-
const nextChildren = state.entries.map((entry) => {
|
|
712
|
-
const accent = getLevelAccent(entry.level);
|
|
713
|
-
const row = document.createElement("div");
|
|
714
|
-
row.style.cssText = [
|
|
715
|
-
"display:flex",
|
|
716
|
-
"align-items:flex-start",
|
|
717
|
-
"gap:0",
|
|
718
|
-
"padding:4px 12px",
|
|
719
|
-
"background:" + accent.lineBackground
|
|
720
|
-
].join(";");
|
|
721
|
-
const line = document.createElement("div");
|
|
722
|
-
line.textContent = formatTimestamp(entry.timestamp) + " " + entry.level.toUpperCase() + " " + entry.message;
|
|
723
|
-
line.style.cssText = [
|
|
724
|
-
"color:#ecf4ff",
|
|
725
|
-
"font:500 12px/1.5 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
|
|
726
|
-
"white-space:pre-wrap",
|
|
727
|
-
"word-break:break-word",
|
|
728
|
-
"flex:1 1 auto"
|
|
729
|
-
].join(";");
|
|
730
|
-
row.appendChild(line);
|
|
731
|
-
return row;
|
|
732
|
-
});
|
|
733
|
-
state.ui.entries.replaceChildren(...nextChildren);
|
|
734
|
-
state.ui.entries.scrollTop = state.ui.entries.scrollHeight;
|
|
735
|
-
applyPanelSize(state);
|
|
736
|
-
applyOverlayPosition(state);
|
|
737
|
-
}
|
|
738
|
-
function mountOverlay(state) {
|
|
739
|
-
const doc = getDocument();
|
|
740
|
-
if (!doc?.body || state.ui) {
|
|
741
|
-
return;
|
|
742
|
-
}
|
|
743
|
-
state.ui = createOverlayUi(state);
|
|
744
|
-
doc.body.appendChild(state.ui.root);
|
|
745
|
-
applyPanelSize(state);
|
|
746
|
-
applyOverlayPosition(state);
|
|
747
|
-
renderOverlay(state);
|
|
748
|
-
}
|
|
749
|
-
function enqueueEntry(state, level, args) {
|
|
750
|
-
state.entries.push(createEntry(level, args, state.nextEntryId));
|
|
751
|
-
state.nextEntryId += 1;
|
|
752
|
-
if (state.entries.length > state.maxEntries) {
|
|
753
|
-
state.entries.splice(0, state.entries.length - state.maxEntries);
|
|
754
|
-
}
|
|
755
|
-
if (!state.expanded) {
|
|
756
|
-
state.unreadCount += 1;
|
|
757
|
-
}
|
|
758
|
-
renderOverlay(state);
|
|
759
|
-
}
|
|
760
|
-
function restoreConsole(snapshot) {
|
|
761
|
-
for (const method of CONSOLE_METHODS) {
|
|
762
|
-
console[method] = snapshot[method];
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
function patchConsole(state) {
|
|
766
|
-
for (const method of CONSOLE_METHODS) {
|
|
767
|
-
const original = state.originalConsole[method];
|
|
768
|
-
console[method] = (...args) => {
|
|
769
|
-
enqueueEntry(state, method, args);
|
|
770
|
-
original(...args);
|
|
771
|
-
};
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
function cleanupOverlay(browserWindow, state) {
|
|
775
|
-
restoreConsole(state.originalConsole);
|
|
776
|
-
stopResizing(state);
|
|
777
|
-
stopDragging(state);
|
|
778
|
-
if (state.domReadyHandler) {
|
|
779
|
-
getDocument()?.removeEventListener("DOMContentLoaded", state.domReadyHandler);
|
|
780
|
-
state.domReadyHandler = void 0;
|
|
781
|
-
}
|
|
782
|
-
if (state.resizeHandler && typeof browserWindow.removeEventListener === "function") {
|
|
783
|
-
browserWindow.removeEventListener("resize", state.resizeHandler);
|
|
784
|
-
state.resizeHandler = void 0;
|
|
785
|
-
}
|
|
786
|
-
state.ui?.root.remove();
|
|
787
|
-
state.ui = null;
|
|
788
|
-
delete browserWindow.__oasizLogOverlayController__;
|
|
789
|
-
delete browserWindow.__oasizLogOverlayState__;
|
|
790
|
-
}
|
|
791
|
-
function createController(browserWindow, state) {
|
|
792
|
-
return {
|
|
793
|
-
retain() {
|
|
794
|
-
state.refCount += 1;
|
|
795
|
-
this.ensureMounted();
|
|
796
|
-
},
|
|
797
|
-
ensureMounted() {
|
|
798
|
-
const doc = getDocument();
|
|
799
|
-
if (!doc) {
|
|
800
|
-
return;
|
|
801
|
-
}
|
|
802
|
-
if (doc.body) {
|
|
803
|
-
mountOverlay(state);
|
|
804
|
-
applyOverlayPosition(state);
|
|
805
|
-
return;
|
|
806
|
-
}
|
|
807
|
-
if (!state.domReadyHandler) {
|
|
808
|
-
state.domReadyHandler = () => {
|
|
809
|
-
mountOverlay(state);
|
|
810
|
-
state.domReadyHandler = void 0;
|
|
811
|
-
};
|
|
812
|
-
doc.addEventListener("DOMContentLoaded", state.domReadyHandler, {
|
|
813
|
-
once: true
|
|
814
|
-
});
|
|
815
|
-
}
|
|
816
|
-
},
|
|
817
|
-
clear() {
|
|
818
|
-
state.entries = [];
|
|
819
|
-
state.unreadCount = 0;
|
|
820
|
-
renderOverlay(state);
|
|
821
|
-
},
|
|
822
|
-
show() {
|
|
823
|
-
state.expanded = true;
|
|
824
|
-
state.unreadCount = 0;
|
|
825
|
-
renderOverlay(state);
|
|
826
|
-
},
|
|
827
|
-
hide() {
|
|
828
|
-
state.expanded = false;
|
|
829
|
-
renderOverlay(state);
|
|
830
|
-
},
|
|
831
|
-
isVisible() {
|
|
832
|
-
return state.expanded;
|
|
833
|
-
},
|
|
834
|
-
destroy() {
|
|
835
|
-
state.refCount = Math.max(0, state.refCount - 1);
|
|
836
|
-
if (state.refCount === 0) {
|
|
837
|
-
cleanupOverlay(browserWindow, state);
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
function enableLogOverlay(options = {}) {
|
|
843
|
-
if (options.enabled === false) {
|
|
844
|
-
return NOOP_HANDLE;
|
|
845
|
-
}
|
|
846
|
-
const browserWindow = getBrowserWindow();
|
|
847
|
-
const doc = getDocument();
|
|
848
|
-
if (!browserWindow || !doc) {
|
|
849
|
-
return NOOP_HANDLE;
|
|
850
|
-
}
|
|
851
|
-
const existingController = browserWindow.__oasizLogOverlayController__;
|
|
852
|
-
const existingState = browserWindow.__oasizLogOverlayState__;
|
|
853
|
-
if (existingController && existingState) {
|
|
854
|
-
existingController.retain();
|
|
855
|
-
if (typeof options.maxEntries === "number") {
|
|
856
|
-
existingState.maxEntries = clampMaxEntries(options.maxEntries);
|
|
857
|
-
if (existingState.entries.length > existingState.maxEntries) {
|
|
858
|
-
existingState.entries.splice(
|
|
859
|
-
0,
|
|
860
|
-
existingState.entries.length - existingState.maxEntries
|
|
861
|
-
);
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
if (typeof options.collapsed === "boolean") {
|
|
865
|
-
existingState.expanded = !options.collapsed;
|
|
866
|
-
applyPanelSize(existingState);
|
|
867
|
-
if (existingState.expanded) {
|
|
868
|
-
existingState.unreadCount = 0;
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
if (typeof options.title === "string" && options.title.trim().length > 0) {
|
|
872
|
-
existingState.title = options.title.trim();
|
|
873
|
-
}
|
|
874
|
-
existingController.ensureMounted();
|
|
875
|
-
renderOverlay(existingState);
|
|
876
|
-
return existingController;
|
|
877
|
-
}
|
|
878
|
-
const state = {
|
|
879
|
-
dragMoved: false,
|
|
880
|
-
dragStartPoint: null,
|
|
881
|
-
entries: [],
|
|
882
|
-
expanded: options.collapsed !== true,
|
|
883
|
-
isDragging: false,
|
|
884
|
-
isResizing: false,
|
|
885
|
-
lastDragPoint: null,
|
|
886
|
-
maxEntries: clampMaxEntries(options.maxEntries),
|
|
887
|
-
nextEntryId: 1,
|
|
888
|
-
originalConsole: createConsoleSnapshot(),
|
|
889
|
-
panelSize: null,
|
|
890
|
-
position: null,
|
|
891
|
-
refCount: 1,
|
|
892
|
-
removeDragListeners: null,
|
|
893
|
-
removeResizeListeners: null,
|
|
894
|
-
resizeStartPoint: null,
|
|
895
|
-
resizeStartSize: null,
|
|
896
|
-
suppressToggleClickUntil: 0,
|
|
897
|
-
title: typeof options.title === "string" && options.title.trim().length > 0 ? options.title.trim() : DEFAULT_TITLE,
|
|
898
|
-
resizeHandler: void 0,
|
|
899
|
-
ui: null,
|
|
900
|
-
unreadCount: 0
|
|
901
|
-
};
|
|
902
|
-
const controller = createController(browserWindow, state);
|
|
903
|
-
browserWindow.__oasizLogOverlayState__ = state;
|
|
904
|
-
browserWindow.__oasizLogOverlayController__ = controller;
|
|
905
|
-
patchConsole(state);
|
|
906
|
-
if (typeof browserWindow.addEventListener === "function") {
|
|
907
|
-
state.resizeHandler = () => {
|
|
908
|
-
applyOverlayPosition(state);
|
|
909
|
-
};
|
|
910
|
-
browserWindow.addEventListener("resize", state.resizeHandler);
|
|
911
|
-
}
|
|
912
|
-
controller.ensureMounted();
|
|
913
|
-
return controller;
|
|
914
|
-
}
|
|
915
|
-
|
|
916
25
|
// src/multiplayer.ts
|
|
917
26
|
function isDevelopment2() {
|
|
918
27
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
@@ -924,10 +33,10 @@ function getBridgeWindow2() {
|
|
|
924
33
|
}
|
|
925
34
|
return window;
|
|
926
35
|
}
|
|
927
|
-
function shareRoomCode(roomCode
|
|
36
|
+
function shareRoomCode(roomCode) {
|
|
928
37
|
const bridge = getBridgeWindow2();
|
|
929
38
|
if (typeof bridge?.shareRoomCode === "function") {
|
|
930
|
-
bridge.shareRoomCode(roomCode
|
|
39
|
+
bridge.shareRoomCode(roomCode);
|
|
931
40
|
return;
|
|
932
41
|
}
|
|
933
42
|
if (isDevelopment2()) {
|
|
@@ -936,18 +45,6 @@ function shareRoomCode(roomCode, options) {
|
|
|
936
45
|
);
|
|
937
46
|
}
|
|
938
47
|
}
|
|
939
|
-
function openInviteModal() {
|
|
940
|
-
const bridge = getBridgeWindow2();
|
|
941
|
-
if (typeof bridge?.openInviteModal === "function") {
|
|
942
|
-
bridge.openInviteModal();
|
|
943
|
-
return;
|
|
944
|
-
}
|
|
945
|
-
if (isDevelopment2()) {
|
|
946
|
-
console.warn(
|
|
947
|
-
"[oasiz/sdk] openInviteModal bridge is unavailable. This is expected in local development."
|
|
948
|
-
);
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
48
|
function getGameId() {
|
|
952
49
|
const bridge = getBridgeWindow2();
|
|
953
50
|
return bridge?.__GAME_ID__;
|
|
@@ -1167,22 +264,127 @@ function leaveGame() {
|
|
|
1167
264
|
warnMissingBridge3("__oasizLeaveGame");
|
|
1168
265
|
}
|
|
1169
266
|
|
|
267
|
+
// src/store.ts
|
|
268
|
+
function isDevelopment7() {
|
|
269
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
270
|
+
return nodeEnv !== "production";
|
|
271
|
+
}
|
|
272
|
+
function getBridgeWindow6() {
|
|
273
|
+
if (typeof window === "undefined") {
|
|
274
|
+
return void 0;
|
|
275
|
+
}
|
|
276
|
+
return window;
|
|
277
|
+
}
|
|
278
|
+
function warnMissingBridge4(methodName) {
|
|
279
|
+
if (isDevelopment7()) {
|
|
280
|
+
console.warn(
|
|
281
|
+
"[oasiz/sdk] " + methodName + " store bridge is unavailable. This is expected in local development."
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async function requestStoreBridge(action, payload) {
|
|
286
|
+
const bridge = getBridgeWindow6();
|
|
287
|
+
if (typeof bridge?.__oasizStoreBridgeRequest !== "function") {
|
|
288
|
+
warnMissingBridge4(action);
|
|
289
|
+
throw new Error("Store bridge unavailable");
|
|
290
|
+
}
|
|
291
|
+
return await bridge.__oasizStoreBridgeRequest({
|
|
292
|
+
action,
|
|
293
|
+
payload
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
async function getFreshState() {
|
|
297
|
+
return await requestStoreBridge("getStoreState");
|
|
298
|
+
}
|
|
299
|
+
function subscribeToStoreEvent(eventName, callback) {
|
|
300
|
+
if (typeof window === "undefined") {
|
|
301
|
+
return () => {
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
const handler = (event) => {
|
|
305
|
+
const customEvent = event;
|
|
306
|
+
callback(customEvent.detail);
|
|
307
|
+
};
|
|
308
|
+
window.addEventListener(eventName, handler);
|
|
309
|
+
return () => {
|
|
310
|
+
window.removeEventListener(eventName, handler);
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
async function syncProducts(products, expectedVersion) {
|
|
314
|
+
return await requestStoreBridge("syncProducts", {
|
|
315
|
+
expectedVersion: expectedVersion ?? null,
|
|
316
|
+
products
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
async function getProducts() {
|
|
320
|
+
const state = await getFreshState();
|
|
321
|
+
return state.products;
|
|
322
|
+
}
|
|
323
|
+
async function getEntitlements() {
|
|
324
|
+
const state = await getFreshState();
|
|
325
|
+
return state.entitlements;
|
|
326
|
+
}
|
|
327
|
+
async function hasEntitlement(productId) {
|
|
328
|
+
const state = await getFreshState();
|
|
329
|
+
return state.entitlements.find((item) => item.productId === productId)?.owned === true;
|
|
330
|
+
}
|
|
331
|
+
async function getQuantity(productId) {
|
|
332
|
+
const state = await getFreshState();
|
|
333
|
+
return state.entitlements.find((item) => item.productId === productId)?.quantity ?? 0;
|
|
334
|
+
}
|
|
335
|
+
async function purchase(productId, quantity = 1) {
|
|
336
|
+
return await requestStoreBridge("purchaseProduct", {
|
|
337
|
+
productId,
|
|
338
|
+
quantity
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
async function consume(productId, quantity = 1) {
|
|
342
|
+
return await requestStoreBridge("consumeProduct", {
|
|
343
|
+
productId,
|
|
344
|
+
quantity
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
async function getJemBalance() {
|
|
348
|
+
const state = await getFreshState();
|
|
349
|
+
return state.jemBalance;
|
|
350
|
+
}
|
|
351
|
+
function onEntitlementsChanged(callback) {
|
|
352
|
+
return subscribeToStoreEvent("oasiz:entitlements-changed", (state) => {
|
|
353
|
+
callback(state.entitlements);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
function onJemBalanceChanged(callback) {
|
|
357
|
+
return subscribeToStoreEvent("oasiz:jem-balance-changed", (state) => {
|
|
358
|
+
callback(state.jemBalance);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
1170
362
|
// src/index.ts
|
|
1171
363
|
var oasiz = {
|
|
1172
364
|
submitScore,
|
|
1173
365
|
emitScoreConfig,
|
|
1174
366
|
triggerHaptic,
|
|
1175
|
-
enableLogOverlay,
|
|
1176
367
|
loadGameState,
|
|
1177
368
|
saveGameState,
|
|
1178
369
|
flushGameState,
|
|
1179
370
|
shareRoomCode,
|
|
1180
|
-
openInviteModal,
|
|
1181
371
|
onPause,
|
|
1182
372
|
onResume,
|
|
1183
373
|
onBackButton,
|
|
1184
374
|
onLeaveGame,
|
|
1185
375
|
leaveGame,
|
|
376
|
+
store: {
|
|
377
|
+
syncProducts,
|
|
378
|
+
getProducts,
|
|
379
|
+
getEntitlements,
|
|
380
|
+
hasEntitlement,
|
|
381
|
+
getQuantity,
|
|
382
|
+
purchase,
|
|
383
|
+
consume,
|
|
384
|
+
getJemBalance,
|
|
385
|
+
onEntitlementsChanged,
|
|
386
|
+
onJemBalanceChanged
|
|
387
|
+
},
|
|
1186
388
|
get gameId() {
|
|
1187
389
|
return getGameId();
|
|
1188
390
|
},
|
|
@@ -1197,23 +399,31 @@ var oasiz = {
|
|
|
1197
399
|
}
|
|
1198
400
|
};
|
|
1199
401
|
export {
|
|
402
|
+
consume,
|
|
1200
403
|
emitScoreConfig,
|
|
1201
|
-
enableLogOverlay,
|
|
1202
404
|
flushGameState,
|
|
405
|
+
getEntitlements,
|
|
1203
406
|
getGameId,
|
|
407
|
+
getJemBalance,
|
|
1204
408
|
getPlayerAvatar,
|
|
1205
409
|
getPlayerName,
|
|
410
|
+
getProducts,
|
|
411
|
+
getQuantity,
|
|
1206
412
|
getRoomCode,
|
|
413
|
+
hasEntitlement,
|
|
1207
414
|
leaveGame,
|
|
1208
415
|
loadGameState,
|
|
1209
416
|
oasiz,
|
|
1210
417
|
onBackButton,
|
|
418
|
+
onEntitlementsChanged,
|
|
419
|
+
onJemBalanceChanged,
|
|
1211
420
|
onLeaveGame,
|
|
1212
421
|
onPause,
|
|
1213
422
|
onResume,
|
|
1214
|
-
|
|
423
|
+
purchase,
|
|
1215
424
|
saveGameState,
|
|
1216
425
|
shareRoomCode,
|
|
1217
426
|
submitScore,
|
|
427
|
+
syncProducts,
|
|
1218
428
|
triggerHaptic
|
|
1219
429
|
};
|