@playruo/embed 1.3.0 → 1.3.2
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 +9 -0
- package/dist/index.cjs +1354 -371
- package/dist/index.d.cts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +1354 -371
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34,15 +34,18 @@ var PlayruoEmbed = ({
|
|
|
34
34
|
onReady,
|
|
35
35
|
onStateChange,
|
|
36
36
|
onDemoCompleted,
|
|
37
|
+
onEvent,
|
|
37
38
|
onPurchaseRequest,
|
|
38
39
|
onError,
|
|
40
|
+
forwardEventsToParent = true,
|
|
39
41
|
renderState,
|
|
40
42
|
iframeRef: externalIframeRef
|
|
41
43
|
}) => {
|
|
42
44
|
const internalIframeRef = useRef(null);
|
|
43
45
|
const iframeRef = externalIframeRef || internalIframeRef;
|
|
44
46
|
const wasEmbedFullscreenRef = useRef(false);
|
|
45
|
-
const
|
|
47
|
+
const hasNotifiedCompletionRef = useRef(false);
|
|
48
|
+
const suppressNextFullscreenExitCleanupRef = useRef(false);
|
|
46
49
|
const [isIframeLoaded, setIsIframeLoaded] = useState(false);
|
|
47
50
|
const [hasPlayedOnce, setHasPlayedOnce] = useState(false);
|
|
48
51
|
const [showGameIframe, setShowGameIframe] = useState(false);
|
|
@@ -112,6 +115,149 @@ var PlayruoEmbed = ({
|
|
|
112
115
|
console.warn("[PlayruoEmbed] Failed to release Escape key lock:", error);
|
|
113
116
|
}
|
|
114
117
|
}, [getKeyboardApi]);
|
|
118
|
+
const getFullscreenElement = useCallback(() => {
|
|
119
|
+
const doc = document;
|
|
120
|
+
return doc.fullscreenElement || doc.webkitFullscreenElement || doc.mozFullScreenElement || doc.msFullscreenElement || null;
|
|
121
|
+
}, []);
|
|
122
|
+
const notifyDemoCompletedOnce = useCallback(
|
|
123
|
+
(payload) => {
|
|
124
|
+
if (hasNotifiedCompletionRef.current) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
hasNotifiedCompletionRef.current = true;
|
|
128
|
+
onDemoCompleted?.(
|
|
129
|
+
payload ?? {
|
|
130
|
+
reason: "Demo session ended",
|
|
131
|
+
storeUrl
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
[onDemoCompleted, storeUrl]
|
|
136
|
+
);
|
|
137
|
+
const postExitFullscreenToIframe = useCallback(() => {
|
|
138
|
+
const iframe = iframeRef.current;
|
|
139
|
+
if (!iframe) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
iframe.contentWindow?.postMessage({
|
|
144
|
+
type: "playruo",
|
|
145
|
+
action: "exitFullscreen",
|
|
146
|
+
fromEmbed: true,
|
|
147
|
+
isFullscreen: false,
|
|
148
|
+
parentWillHandleFullscreen: true
|
|
149
|
+
}, "*");
|
|
150
|
+
} catch {
|
|
151
|
+
console.error("[PlayruoEmbed] Failed to exit fullscreen");
|
|
152
|
+
}
|
|
153
|
+
}, [iframeRef]);
|
|
154
|
+
const postExitFullscreenAckToIframe = useCallback(() => {
|
|
155
|
+
const iframe = iframeRef.current;
|
|
156
|
+
if (!iframe) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
iframe.contentWindow?.postMessage({ type: "ACK_EXIT_FULLSCREEN" }, "*");
|
|
161
|
+
} catch {
|
|
162
|
+
console.error("[PlayruoEmbed] Failed to acknowledge fullscreen exit");
|
|
163
|
+
}
|
|
164
|
+
}, [iframeRef]);
|
|
165
|
+
const exitEmbedFullscreen = useCallback(
|
|
166
|
+
async ({
|
|
167
|
+
reason = "cleanup",
|
|
168
|
+
suppressFullscreenExitCleanup = true
|
|
169
|
+
} = {}) => {
|
|
170
|
+
const fullscreenElement = getFullscreenElement();
|
|
171
|
+
const doc = document;
|
|
172
|
+
const exitFullscreen = doc.exitFullscreen?.bind(doc) ?? doc.webkitExitFullscreen?.bind(doc) ?? doc.mozCancelFullScreen?.bind(doc) ?? doc.msExitFullscreen?.bind(doc);
|
|
173
|
+
const shouldAttemptExit = Boolean(fullscreenElement || wasEmbedFullscreenRef.current);
|
|
174
|
+
if (!shouldAttemptExit || !exitFullscreen) {
|
|
175
|
+
console.log("[PlayruoEmbed] Parent fullscreen exit skipped", {
|
|
176
|
+
hasFullscreenElement: Boolean(fullscreenElement),
|
|
177
|
+
hasExitFullscreen: Boolean(exitFullscreen),
|
|
178
|
+
reason,
|
|
179
|
+
wasEmbedFullscreen: wasEmbedFullscreenRef.current
|
|
180
|
+
});
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
console.log("[PlayruoEmbed] Parent fullscreen exit requested", {
|
|
184
|
+
fullscreenElement: fullscreenElement?.tagName,
|
|
185
|
+
reason,
|
|
186
|
+
wasEmbedFullscreen: wasEmbedFullscreenRef.current
|
|
187
|
+
});
|
|
188
|
+
const shouldSuppressFullscreenExitCleanup = Boolean(
|
|
189
|
+
suppressFullscreenExitCleanup && fullscreenElement
|
|
190
|
+
);
|
|
191
|
+
if (shouldSuppressFullscreenExitCleanup) {
|
|
192
|
+
suppressNextFullscreenExitCleanupRef.current = true;
|
|
193
|
+
wasEmbedFullscreenRef.current = false;
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
await exitFullscreen();
|
|
197
|
+
if (shouldSuppressFullscreenExitCleanup) {
|
|
198
|
+
window.setTimeout(() => {
|
|
199
|
+
suppressNextFullscreenExitCleanupRef.current = false;
|
|
200
|
+
}, 1e3);
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (shouldSuppressFullscreenExitCleanup) {
|
|
205
|
+
suppressNextFullscreenExitCleanupRef.current = false;
|
|
206
|
+
wasEmbedFullscreenRef.current = Boolean(getFullscreenElement());
|
|
207
|
+
}
|
|
208
|
+
console.warn("[PlayruoEmbed] Failed to leave fullscreen:", error);
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
[getFullscreenElement]
|
|
213
|
+
);
|
|
214
|
+
const cleanupEmbedSession = useCallback(
|
|
215
|
+
({
|
|
216
|
+
payload,
|
|
217
|
+
notifyCompletion = true,
|
|
218
|
+
requestFullscreenExit = true,
|
|
219
|
+
notifyIframe = false,
|
|
220
|
+
markPlayed = true
|
|
221
|
+
} = {}) => {
|
|
222
|
+
setShowGameIframe(false);
|
|
223
|
+
if (markPlayed) {
|
|
224
|
+
setHasPlayedOnce(true);
|
|
225
|
+
}
|
|
226
|
+
releaseEscapeKeyLock();
|
|
227
|
+
if (notifyIframe) {
|
|
228
|
+
postExitFullscreenToIframe();
|
|
229
|
+
}
|
|
230
|
+
if (requestFullscreenExit) {
|
|
231
|
+
void exitEmbedFullscreen();
|
|
232
|
+
}
|
|
233
|
+
if (notifyCompletion) {
|
|
234
|
+
notifyDemoCompletedOnce(payload);
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
[
|
|
238
|
+
exitEmbedFullscreen,
|
|
239
|
+
notifyDemoCompletedOnce,
|
|
240
|
+
postExitFullscreenToIframe,
|
|
241
|
+
releaseEscapeKeyLock
|
|
242
|
+
]
|
|
243
|
+
);
|
|
244
|
+
const markStreamActive = useCallback(() => {
|
|
245
|
+
hasNotifiedCompletionRef.current = false;
|
|
246
|
+
setShowGameIframe(true);
|
|
247
|
+
}, []);
|
|
248
|
+
const forwardEventToParent = useCallback(
|
|
249
|
+
(message) => {
|
|
250
|
+
if (!forwardEventsToParent || typeof window === "undefined" || window.parent === window) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
try {
|
|
254
|
+
window.parent.postMessage(message, "*");
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.warn("[PlayruoEmbed] Failed to forward event to parent:", error);
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
[forwardEventsToParent]
|
|
260
|
+
);
|
|
115
261
|
const lockEscapeKey = useCallback(async () => {
|
|
116
262
|
const keyboard = getKeyboardApi();
|
|
117
263
|
if (!keyboard?.lock) {
|
|
@@ -124,55 +270,8 @@ var PlayruoEmbed = ({
|
|
|
124
270
|
console.warn("[PlayruoEmbed] Failed to lock Escape key:", error);
|
|
125
271
|
}
|
|
126
272
|
}, [getKeyboardApi]);
|
|
127
|
-
const getPointerLockElement = useCallback(() => {
|
|
128
|
-
const doc = document;
|
|
129
|
-
return doc.pointerLockElement || doc.mozPointerLockElement || doc.webkitPointerLockElement || null;
|
|
130
|
-
}, []);
|
|
131
|
-
const releasePointerLock = useCallback(() => {
|
|
132
|
-
const doc = document;
|
|
133
|
-
const exitPointerLock = doc.exitPointerLock?.bind(doc) || doc.mozExitPointerLock?.bind(doc) || doc.webkitExitPointerLock?.bind(doc);
|
|
134
|
-
try {
|
|
135
|
-
exitPointerLock?.();
|
|
136
|
-
wasEmbedPointerLockedRef.current = false;
|
|
137
|
-
} catch (error) {
|
|
138
|
-
console.warn("[PlayruoEmbed] Failed to release pointer lock:", error);
|
|
139
|
-
}
|
|
140
|
-
}, []);
|
|
141
273
|
const requestImmersiveMode = useCallback(
|
|
142
274
|
async (iframe) => {
|
|
143
|
-
const pointerTarget = iframe;
|
|
144
|
-
if (pointerTarget.requestPointerLock) {
|
|
145
|
-
try {
|
|
146
|
-
const pointerLockResult = pointerTarget.requestPointerLock({ unadjustedMovement: true });
|
|
147
|
-
if (pointerLockResult && typeof pointerLockResult.then === "function") {
|
|
148
|
-
void pointerLockResult.then(() => {
|
|
149
|
-
wasEmbedPointerLockedRef.current = true;
|
|
150
|
-
console.log("[PlayruoEmbed] Pointer locked on iframe");
|
|
151
|
-
}).catch(async (error) => {
|
|
152
|
-
if (error instanceof DOMException && error.name === "NotSupportedError") {
|
|
153
|
-
try {
|
|
154
|
-
const fallbackResult = pointerTarget.requestPointerLock?.();
|
|
155
|
-
if (fallbackResult && typeof fallbackResult.then === "function") {
|
|
156
|
-
await fallbackResult;
|
|
157
|
-
}
|
|
158
|
-
wasEmbedPointerLockedRef.current = true;
|
|
159
|
-
console.log("[PlayruoEmbed] Pointer locked on iframe without raw input");
|
|
160
|
-
return;
|
|
161
|
-
} catch (fallbackError) {
|
|
162
|
-
console.warn("[PlayruoEmbed] Failed to lock pointer without raw input:", fallbackError);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
console.warn("[PlayruoEmbed] Failed to lock pointer:", error);
|
|
167
|
-
});
|
|
168
|
-
} else {
|
|
169
|
-
wasEmbedPointerLockedRef.current = true;
|
|
170
|
-
console.log("[PlayruoEmbed] Pointer lock requested on iframe");
|
|
171
|
-
}
|
|
172
|
-
} catch (error) {
|
|
173
|
-
console.warn("[PlayruoEmbed] Failed to request pointer lock:", error);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
275
|
const fullscreenPromise = iframe.requestFullscreen();
|
|
177
276
|
try {
|
|
178
277
|
await fullscreenPromise;
|
|
@@ -180,11 +279,10 @@ var PlayruoEmbed = ({
|
|
|
180
279
|
console.log("[PlayruoEmbed] Fullscreen granted");
|
|
181
280
|
} catch (error) {
|
|
182
281
|
releaseEscapeKeyLock();
|
|
183
|
-
releasePointerLock();
|
|
184
282
|
throw error;
|
|
185
283
|
}
|
|
186
284
|
},
|
|
187
|
-
[releaseEscapeKeyLock
|
|
285
|
+
[releaseEscapeKeyLock]
|
|
188
286
|
);
|
|
189
287
|
const handleTryNow = useCallback(async () => {
|
|
190
288
|
if (!isCompatible) {
|
|
@@ -196,6 +294,7 @@ var PlayruoEmbed = ({
|
|
|
196
294
|
console.warn("[PlayruoEmbed] Iframe not ready");
|
|
197
295
|
return;
|
|
198
296
|
}
|
|
297
|
+
hasNotifiedCompletionRef.current = false;
|
|
199
298
|
setShowGameIframe(true);
|
|
200
299
|
try {
|
|
201
300
|
try {
|
|
@@ -219,6 +318,7 @@ var PlayruoEmbed = ({
|
|
|
219
318
|
setHasPlayedOnce(true);
|
|
220
319
|
} catch (error) {
|
|
221
320
|
console.error("[PlayruoEmbed] Failed to start game:", error);
|
|
321
|
+
setShowGameIframe(false);
|
|
222
322
|
setErrorMessage("Failed to start game");
|
|
223
323
|
onError?.("Failed to start game");
|
|
224
324
|
}
|
|
@@ -242,7 +342,8 @@ var PlayruoEmbed = ({
|
|
|
242
342
|
}, [isReady, onReady]);
|
|
243
343
|
useEffect(() => {
|
|
244
344
|
const handleGameMessage = (event) => {
|
|
245
|
-
const
|
|
345
|
+
const message = event.data || {};
|
|
346
|
+
const { type, data } = message;
|
|
246
347
|
const iframe = iframeRef.current;
|
|
247
348
|
if (!iframe || event.source !== iframe.contentWindow) {
|
|
248
349
|
return;
|
|
@@ -263,8 +364,7 @@ var PlayruoEmbed = ({
|
|
|
263
364
|
onPurchaseRequest?.(data);
|
|
264
365
|
} else if (type === "playruo_demo_completed" && data) {
|
|
265
366
|
console.log("\u{1F537} [Embed] playruo_demo_completed received:", data);
|
|
266
|
-
|
|
267
|
-
onDemoCompleted?.(data);
|
|
367
|
+
cleanupEmbedSession({ payload: data });
|
|
268
368
|
} else if (type === "playruo_error") {
|
|
269
369
|
const errorMessage2 = typeof data === "string" ? data : data?.message || "Unknown error";
|
|
270
370
|
console.log("\u{1F537} [Embed] playruo_error received:", errorMessage2);
|
|
@@ -285,25 +385,65 @@ var PlayruoEmbed = ({
|
|
|
285
385
|
onError?.(errorMessage2);
|
|
286
386
|
} else if (type === "playruo_session_over" && data) {
|
|
287
387
|
console.log("\u{1F537} [Embed] playruo_session_over received:", data);
|
|
288
|
-
|
|
388
|
+
void exitEmbedFullscreen({ reason: "playruo_session_over" });
|
|
289
389
|
setIframeState(data);
|
|
290
390
|
onStateChange?.(data);
|
|
391
|
+
cleanupEmbedSession({ requestFullscreenExit: false });
|
|
291
392
|
} else if (type === "playruo_stream_start") {
|
|
292
393
|
console.log("\u{1F537} [Embed] playruo_stream_start received");
|
|
394
|
+
markStreamActive();
|
|
395
|
+
} else if (type === "playruo_stream_stop") {
|
|
396
|
+
console.log("\u{1F537} [Embed] playruo_stream_stop received");
|
|
397
|
+
void exitEmbedFullscreen({ reason: "playruo_stream_stop" });
|
|
398
|
+
cleanupEmbedSession({
|
|
399
|
+
markPlayed: false,
|
|
400
|
+
notifyCompletion: false,
|
|
401
|
+
requestFullscreenExit: false
|
|
402
|
+
});
|
|
403
|
+
} else if (type === "REQUEST_EXIT_FULLSCREEN") {
|
|
404
|
+
console.log("\u{1F537} [Embed] REQUEST_EXIT_FULLSCREEN received");
|
|
405
|
+
void exitEmbedFullscreen({
|
|
406
|
+
reason: "REQUEST_EXIT_FULLSCREEN",
|
|
407
|
+
suppressFullscreenExitCleanup: false
|
|
408
|
+
}).finally(postExitFullscreenAckToIframe);
|
|
409
|
+
} else if (type === "playruo_event" && data && typeof data === "object") {
|
|
410
|
+
console.log("\u{1F537} [Embed] playruo_event received:", data);
|
|
411
|
+
const eventPayload = data;
|
|
412
|
+
onEvent?.(eventPayload);
|
|
413
|
+
forwardEventToParent({ type: "playruo_event", data: eventPayload });
|
|
414
|
+
} else if (type === "playruo" && message.action === "event" && message.payload && typeof message.payload === "object") {
|
|
415
|
+
console.log("\u{1F537} [Embed] legacy playruo event received:", message.payload);
|
|
416
|
+
const eventPayload = message.payload;
|
|
417
|
+
onEvent?.(eventPayload);
|
|
418
|
+
forwardEventToParent({ type: "playruo_event", data: eventPayload });
|
|
293
419
|
}
|
|
294
420
|
if (type === "error" || type === "closeForBuy" || type === "goToStore") {
|
|
295
421
|
console.log("\u{1F537} [Embed] Legacy message received:", type);
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
422
|
+
cleanupEmbedSession({
|
|
423
|
+
payload: {
|
|
424
|
+
reason: "Demo session ended",
|
|
425
|
+
storeUrl
|
|
426
|
+
}
|
|
427
|
+
});
|
|
302
428
|
}
|
|
303
429
|
};
|
|
304
430
|
window.addEventListener("message", handleGameMessage);
|
|
305
431
|
return () => window.removeEventListener("message", handleGameMessage);
|
|
306
|
-
}, [
|
|
432
|
+
}, [
|
|
433
|
+
cleanupEmbedSession,
|
|
434
|
+
exitEmbedFullscreen,
|
|
435
|
+
forwardEventToParent,
|
|
436
|
+
hasPlayedOnce,
|
|
437
|
+
iframeRef,
|
|
438
|
+
markStreamActive,
|
|
439
|
+
onEvent,
|
|
440
|
+
onError,
|
|
441
|
+
onPurchaseRequest,
|
|
442
|
+
onReady,
|
|
443
|
+
onStateChange,
|
|
444
|
+
postExitFullscreenAckToIframe,
|
|
445
|
+
storeUrl
|
|
446
|
+
]);
|
|
307
447
|
const generateUUID = () => {
|
|
308
448
|
if (self.crypto.randomUUID) return self.crypto.randomUUID();
|
|
309
449
|
const bytes = new Uint8Array(16);
|
|
@@ -350,9 +490,8 @@ var PlayruoEmbed = ({
|
|
|
350
490
|
}, [iframeRef]);
|
|
351
491
|
useEffect(() => {
|
|
352
492
|
const handleFullscreenChange = () => {
|
|
353
|
-
const doc = document;
|
|
354
493
|
const iframe = iframeRef.current;
|
|
355
|
-
const fullscreenElement =
|
|
494
|
+
const fullscreenElement = getFullscreenElement();
|
|
356
495
|
const isEmbedFullscreen = Boolean(iframe && fullscreenElement === iframe);
|
|
357
496
|
if (isEmbedFullscreen) {
|
|
358
497
|
wasEmbedFullscreenRef.current = true;
|
|
@@ -369,30 +508,15 @@ var PlayruoEmbed = ({
|
|
|
369
508
|
return;
|
|
370
509
|
}
|
|
371
510
|
releaseEscapeKeyLock();
|
|
511
|
+
if (suppressNextFullscreenExitCleanupRef.current) {
|
|
512
|
+
suppressNextFullscreenExitCleanupRef.current = false;
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
372
515
|
if (wasEmbedFullscreenRef.current) {
|
|
373
516
|
wasEmbedFullscreenRef.current = false;
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
}
|
|
378
|
-
if (iframe) {
|
|
379
|
-
try {
|
|
380
|
-
iframe.contentWindow?.postMessage({
|
|
381
|
-
type: "playruo",
|
|
382
|
-
action: "exitFullscreen",
|
|
383
|
-
fromEmbed: true,
|
|
384
|
-
isFullscreen: false,
|
|
385
|
-
parentWillHandleFullscreen: true
|
|
386
|
-
}, "*");
|
|
387
|
-
} catch {
|
|
388
|
-
console.error("[PlayruoEmbed] Failed to exit fullscreen");
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
setShowGameIframe(false);
|
|
392
|
-
setHasPlayedOnce(true);
|
|
393
|
-
onDemoCompleted?.({
|
|
394
|
-
reason: "Demo session ended",
|
|
395
|
-
storeUrl
|
|
517
|
+
cleanupEmbedSession({
|
|
518
|
+
notifyIframe: true,
|
|
519
|
+
requestFullscreenExit: false
|
|
396
520
|
});
|
|
397
521
|
}
|
|
398
522
|
};
|
|
@@ -406,33 +530,18 @@ var PlayruoEmbed = ({
|
|
|
406
530
|
document.removeEventListener("mozfullscreenchange", handleFullscreenChange);
|
|
407
531
|
document.removeEventListener("MSFullscreenChange", handleFullscreenChange);
|
|
408
532
|
};
|
|
409
|
-
}, [
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
wasEmbedPointerLockedRef.current = false;
|
|
417
|
-
console.warn("[PlayruoEmbed] Pointer lock request was rejected");
|
|
418
|
-
};
|
|
419
|
-
document.addEventListener("pointerlockchange", handlePointerLockChange);
|
|
420
|
-
document.addEventListener("pointerlockerror", handlePointerLockError);
|
|
421
|
-
return () => {
|
|
422
|
-
document.removeEventListener("pointerlockchange", handlePointerLockChange);
|
|
423
|
-
document.removeEventListener("pointerlockerror", handlePointerLockError);
|
|
424
|
-
};
|
|
425
|
-
}, [getPointerLockElement, iframeRef]);
|
|
533
|
+
}, [
|
|
534
|
+
cleanupEmbedSession,
|
|
535
|
+
getFullscreenElement,
|
|
536
|
+
iframeRef,
|
|
537
|
+
lockEscapeKey,
|
|
538
|
+
releaseEscapeKeyLock
|
|
539
|
+
]);
|
|
426
540
|
useEffect(() => {
|
|
427
541
|
return () => {
|
|
428
542
|
releaseEscapeKeyLock();
|
|
429
|
-
const iframe = iframeRef.current;
|
|
430
|
-
const isEmbedPointerLocked = Boolean(iframe && getPointerLockElement() === iframe);
|
|
431
|
-
if (wasEmbedPointerLockedRef.current || isEmbedPointerLocked) {
|
|
432
|
-
releasePointerLock();
|
|
433
|
-
}
|
|
434
543
|
};
|
|
435
|
-
}, [
|
|
544
|
+
}, [releaseEscapeKeyLock]);
|
|
436
545
|
useEffect(() => {
|
|
437
546
|
const logCrossOriginStatus = () => {
|
|
438
547
|
const isIsolated = self.crossOriginIsolated;
|
|
@@ -512,6 +621,8 @@ var PlayruoEmbed = ({
|
|
|
512
621
|
}
|
|
513
622
|
}, [isReady]);
|
|
514
623
|
const isAvailable = Boolean(isReady && isCompatible && hasIframeConfirmed);
|
|
624
|
+
const shouldDisplayGameIframe = showGameIframe;
|
|
625
|
+
const shouldShowIframeMisuseMessage = Boolean(showIframe && !showGameIframe);
|
|
515
626
|
const renderContent = () => {
|
|
516
627
|
if (!renderState) return null;
|
|
517
628
|
const canTryNow = Boolean(
|
|
@@ -541,6 +652,26 @@ var PlayruoEmbed = ({
|
|
|
541
652
|
};
|
|
542
653
|
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
543
654
|
renderContent(),
|
|
655
|
+
isCompatible && shouldShowIframeMisuseMessage && /* @__PURE__ */ jsx(
|
|
656
|
+
"div",
|
|
657
|
+
{
|
|
658
|
+
role: "status",
|
|
659
|
+
style: {
|
|
660
|
+
alignItems: "center",
|
|
661
|
+
background: "#000",
|
|
662
|
+
color: "#fff",
|
|
663
|
+
display: "flex",
|
|
664
|
+
fontFamily: "system-ui, sans-serif",
|
|
665
|
+
fontSize: 14,
|
|
666
|
+
height: "100%",
|
|
667
|
+
justifyContent: "center",
|
|
668
|
+
padding: 24,
|
|
669
|
+
textAlign: "center",
|
|
670
|
+
width: "100%"
|
|
671
|
+
},
|
|
672
|
+
children: "This iframe is only meant to be displayed through PlayruoEmbed during an active stream."
|
|
673
|
+
}
|
|
674
|
+
),
|
|
544
675
|
isCompatible && /* @__PURE__ */ jsx(
|
|
545
676
|
"iframe",
|
|
546
677
|
{
|
|
@@ -553,9 +684,9 @@ var PlayruoEmbed = ({
|
|
|
553
684
|
title: "Playruo",
|
|
554
685
|
referrerPolicy: "strict-origin-when-cross-origin",
|
|
555
686
|
style: {
|
|
556
|
-
//
|
|
557
|
-
opacity:
|
|
558
|
-
pointerEvents:
|
|
687
|
+
// The iframe stays mounted for readiness checks, visible only during launch/play, and hidden after terminal events.
|
|
688
|
+
opacity: shouldDisplayGameIframe ? 1 : 0,
|
|
689
|
+
pointerEvents: shouldDisplayGameIframe ? "auto" : "none",
|
|
559
690
|
width: "100%",
|
|
560
691
|
height: "100%",
|
|
561
692
|
border: 0
|
|
@@ -582,36 +713,61 @@ var PlayruoEmbed = ({
|
|
|
582
713
|
// src/react/embed-tester.tsx
|
|
583
714
|
import React, { useCallback as useCallback2, useRef as useRef2, useState as useState2 } from "react";
|
|
584
715
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
716
|
+
var createInitialEmbedState = () => ({
|
|
717
|
+
buyNow: { available: false, status: "Not ready" },
|
|
718
|
+
hasPlayedOnce: false,
|
|
719
|
+
isReady: false,
|
|
720
|
+
tryNow: { available: false, status: "Not ready" }
|
|
721
|
+
});
|
|
722
|
+
var createInitialDiagnostics = () => ({
|
|
723
|
+
chromiumBrowser: false,
|
|
724
|
+
crossOriginIsolation: false,
|
|
725
|
+
desktopBrowser: false,
|
|
726
|
+
fullscreenSupported: false,
|
|
727
|
+
gamepadSupported: false,
|
|
728
|
+
iframeAllowsFullscreen: false,
|
|
729
|
+
iframeAllowsGamepad: false,
|
|
730
|
+
iframeAllowsPointerLock: false,
|
|
731
|
+
keyboardLockSupported: false,
|
|
732
|
+
localStorageSupported: false,
|
|
733
|
+
pointerLockSupported: false,
|
|
734
|
+
secureContext: false,
|
|
735
|
+
sharedArrayBufferSupported: false,
|
|
736
|
+
topLevelContext: false,
|
|
737
|
+
webAssemblySupported: false,
|
|
738
|
+
webgl2Supported: false
|
|
739
|
+
});
|
|
585
740
|
var EmbedTester = (props = {}) => {
|
|
586
|
-
const [
|
|
587
|
-
const [
|
|
741
|
+
const [operationDraft, setOperationDraft] = useState2(props.operation ?? "iframe");
|
|
742
|
+
const [storeUrlDraft, setStoreUrlDraft] = useState2(
|
|
743
|
+
props.storeUrl ?? "https://store.steampowered.com/app/123456"
|
|
744
|
+
);
|
|
745
|
+
const [appliedOperation, setAppliedOperation] = useState2(props.operation ?? "iframe");
|
|
746
|
+
const [appliedStoreUrl, setAppliedStoreUrl] = useState2(
|
|
588
747
|
props.storeUrl ?? "https://store.steampowered.com/app/123456"
|
|
589
748
|
);
|
|
590
749
|
const [key, setKey] = useState2(0);
|
|
591
750
|
const [hasUserClicked, setHasUserClicked] = useState2(false);
|
|
592
751
|
const [showIframe, setShowIframe] = useState2(false);
|
|
593
|
-
const [embedState, setEmbedState] = useState2(
|
|
594
|
-
buyNow: { available: false, status: "Not ready" },
|
|
595
|
-
hasPlayedOnce: false,
|
|
596
|
-
isReady: false,
|
|
597
|
-
tryNow: { available: false, status: "Not ready" }
|
|
598
|
-
});
|
|
752
|
+
const [embedState, setEmbedState] = useState2(createInitialEmbedState);
|
|
599
753
|
const [eventLog, setEventLog] = useState2([]);
|
|
600
|
-
const [diagnostics, setDiagnostics] = useState2(
|
|
601
|
-
crossOriginIsolation: false,
|
|
602
|
-
gamepadSupported: false,
|
|
603
|
-
fullscreenSupported: false,
|
|
604
|
-
keyboardLockSupported: false
|
|
605
|
-
});
|
|
754
|
+
const [diagnostics, setDiagnostics] = useState2(createInitialDiagnostics);
|
|
606
755
|
const displayHost = props.baseUrl ? new URL(props.baseUrl).host : "playruo.live";
|
|
607
756
|
const enableConsoleLog = props.enableConsoleLog ?? false;
|
|
608
757
|
const hasReadyBeenCalled = useRef2(false);
|
|
758
|
+
const nextEventIdRef = useRef2(0);
|
|
609
759
|
const previousStateRef = useRef2("");
|
|
610
760
|
const iframeRef = useRef2(null);
|
|
761
|
+
const isOperationPending = operationDraft !== appliedOperation;
|
|
762
|
+
const isStoreUrlPending = storeUrlDraft !== appliedStoreUrl;
|
|
763
|
+
const hasPendingConfigChanges = isOperationPending || isStoreUrlPending;
|
|
764
|
+
const pendingChangeCount = Number(isOperationPending) + Number(isStoreUrlPending);
|
|
611
765
|
const addEvent = useCallback2(
|
|
612
766
|
(message) => {
|
|
613
767
|
const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString();
|
|
614
|
-
|
|
768
|
+
const id = nextEventIdRef.current;
|
|
769
|
+
nextEventIdRef.current += 1;
|
|
770
|
+
setEventLog((prev) => [...prev.slice(-10), { id, message, timestamp }]);
|
|
615
771
|
if (enableConsoleLog) {
|
|
616
772
|
console.log(`[EmbedTester] ${timestamp}: ${message}`);
|
|
617
773
|
}
|
|
@@ -619,18 +775,48 @@ var EmbedTester = (props = {}) => {
|
|
|
619
775
|
[enableConsoleLog]
|
|
620
776
|
);
|
|
621
777
|
const runDiagnostics = useCallback2(() => {
|
|
778
|
+
const userAgent = navigator.userAgent || navigator.vendor || window.opera || "";
|
|
779
|
+
const isMobileDevice = /android|iPad|iPhone|iPod/i.test(userAgent);
|
|
780
|
+
const hasChrome = !!window.chrome;
|
|
781
|
+
const isChromium = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
|
|
782
|
+
const iframeAllow = iframeRef.current?.getAttribute("allow") ?? "";
|
|
783
|
+
const iframeSandbox = iframeRef.current?.getAttribute("sandbox") ?? "";
|
|
784
|
+
const canvas = document.createElement("canvas");
|
|
785
|
+
let localStorageSupported = false;
|
|
786
|
+
try {
|
|
787
|
+
const storageKey = "__playruo_embed_tester__";
|
|
788
|
+
window.localStorage.setItem(storageKey, "1");
|
|
789
|
+
window.localStorage.removeItem(storageKey);
|
|
790
|
+
localStorageSupported = true;
|
|
791
|
+
} catch {
|
|
792
|
+
localStorageSupported = false;
|
|
793
|
+
}
|
|
622
794
|
const newDiagnostics = {
|
|
795
|
+
chromiumBrowser: hasChrome || isChromium,
|
|
623
796
|
crossOriginIsolation: !!(window.crossOriginIsolated || window.crossOriginIsolated),
|
|
624
|
-
|
|
797
|
+
desktopBrowser: !isMobileDevice,
|
|
625
798
|
fullscreenSupported: !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled),
|
|
626
|
-
|
|
799
|
+
gamepadSupported: "getGamepads" in navigator,
|
|
800
|
+
iframeAllowsFullscreen: iframeAllow.includes("fullscreen"),
|
|
801
|
+
iframeAllowsGamepad: iframeAllow.includes("gamepad"),
|
|
802
|
+
iframeAllowsPointerLock: iframeSandbox.includes("allow-pointer-lock"),
|
|
803
|
+
keyboardLockSupported: "keyboard" in navigator && "lock" in navigator.keyboard,
|
|
804
|
+
localStorageSupported,
|
|
805
|
+
pointerLockSupported: "requestPointerLock" in HTMLIFrameElement.prototype || "requestPointerLock" in HTMLElement.prototype || "pointerLockElement" in document,
|
|
806
|
+
secureContext: window.isSecureContext,
|
|
807
|
+
sharedArrayBufferSupported: typeof SharedArrayBuffer !== "undefined",
|
|
808
|
+
topLevelContext: window.self === window.top,
|
|
809
|
+
webAssemblySupported: typeof WebAssembly !== "undefined",
|
|
810
|
+
webgl2Supported: !!canvas.getContext("webgl2")
|
|
627
811
|
};
|
|
628
812
|
setDiagnostics(newDiagnostics);
|
|
629
|
-
addEvent(
|
|
630
|
-
|
|
813
|
+
addEvent(
|
|
814
|
+
`\u{1F50D} Diagnostics updated - Browser: ${newDiagnostics.desktopBrowser && newDiagnostics.chromiumBrowser}, COI: ${newDiagnostics.crossOriginIsolation}, Fullscreen: ${newDiagnostics.fullscreenSupported}`
|
|
815
|
+
);
|
|
816
|
+
}, [addEvent, iframeRef]);
|
|
631
817
|
React.useEffect(() => {
|
|
632
818
|
runDiagnostics();
|
|
633
|
-
}, [runDiagnostics]);
|
|
819
|
+
}, [key, runDiagnostics]);
|
|
634
820
|
const handleReady = useCallback2(() => {
|
|
635
821
|
if (!hasReadyBeenCalled.current) {
|
|
636
822
|
hasReadyBeenCalled.current = true;
|
|
@@ -659,284 +845,1081 @@ var EmbedTester = (props = {}) => {
|
|
|
659
845
|
console.error("Embed error:", error);
|
|
660
846
|
}
|
|
661
847
|
}, [addEvent, enableConsoleLog]);
|
|
848
|
+
const handleEvent = useCallback2((data) => {
|
|
849
|
+
const eventName = typeof data.event === "string" ? data.event : typeof data.name === "string" ? data.name : "unknown";
|
|
850
|
+
addEvent(`Event received: ${eventName}`);
|
|
851
|
+
if (enableConsoleLog) {
|
|
852
|
+
console.log("Embed event:", data);
|
|
853
|
+
}
|
|
854
|
+
}, [addEvent, enableConsoleLog]);
|
|
662
855
|
const handlePurchaseRequest = useCallback2((data) => {
|
|
663
856
|
addEvent(`\u{1F4B3} Explicit purchase request from Buy Now button`);
|
|
664
857
|
addEvent(`Opening store: ${data.storeUrl}`);
|
|
665
858
|
window.open(data.storeUrl, "_blank");
|
|
666
859
|
}, [addEvent]);
|
|
667
|
-
const
|
|
860
|
+
const resetEmbedSession = useCallback2((message) => {
|
|
861
|
+
setEmbedState(createInitialEmbedState());
|
|
668
862
|
setKey((prev) => prev + 1);
|
|
669
863
|
setHasUserClicked(false);
|
|
670
864
|
setShowIframe(false);
|
|
671
865
|
hasReadyBeenCalled.current = false;
|
|
672
866
|
previousStateRef.current = "";
|
|
673
|
-
addEvent(
|
|
867
|
+
addEvent(message);
|
|
674
868
|
}, [addEvent]);
|
|
675
|
-
const
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
869
|
+
const handleApply = useCallback2(() => {
|
|
870
|
+
if (!hasPendingConfigChanges) {
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
setAppliedOperation(operationDraft);
|
|
874
|
+
setAppliedStoreUrl(storeUrlDraft);
|
|
875
|
+
resetEmbedSession("Applied updated embed settings");
|
|
876
|
+
}, [hasPendingConfigChanges, operationDraft, resetEmbedSession, storeUrlDraft]);
|
|
877
|
+
const handleRestartSession = useCallback2(() => {
|
|
878
|
+
resetEmbedSession("Embed restarted with applied settings");
|
|
879
|
+
}, [resetEmbedSession]);
|
|
880
|
+
const handleResetDrafts = useCallback2(() => {
|
|
881
|
+
setOperationDraft(appliedOperation);
|
|
882
|
+
setStoreUrlDraft(appliedStoreUrl);
|
|
883
|
+
addEvent("Reverted draft changes to the applied configuration");
|
|
884
|
+
}, [addEvent, appliedOperation, appliedStoreUrl]);
|
|
885
|
+
const panelStyle = {
|
|
886
|
+
position: "relative",
|
|
887
|
+
border: "1px solid rgba(148, 163, 184, 0.18)",
|
|
888
|
+
borderRadius: "24px",
|
|
889
|
+
padding: "20px",
|
|
890
|
+
background: "linear-gradient(180deg, rgba(15, 23, 42, 0.88) 0%, rgba(7, 12, 24, 0.96) 100%)",
|
|
891
|
+
boxShadow: "0 24px 80px rgba(0, 0, 0, 0.35)",
|
|
892
|
+
backdropFilter: "blur(18px)"
|
|
893
|
+
};
|
|
894
|
+
const sectionTitleStyle = {
|
|
895
|
+
margin: 0,
|
|
896
|
+
fontSize: "18px",
|
|
897
|
+
fontWeight: 600,
|
|
898
|
+
color: "#f8fafc"
|
|
899
|
+
};
|
|
900
|
+
const labelStyle = {
|
|
901
|
+
display: "flex",
|
|
902
|
+
alignItems: "center",
|
|
903
|
+
justifyContent: "space-between",
|
|
904
|
+
gap: "12px",
|
|
905
|
+
marginBottom: "8px",
|
|
906
|
+
fontSize: "13px",
|
|
907
|
+
fontWeight: 600,
|
|
908
|
+
color: "#dbe7ff"
|
|
685
909
|
};
|
|
910
|
+
const buildIndicatorStyle = (pending) => ({
|
|
911
|
+
display: "inline-flex",
|
|
912
|
+
alignItems: "center",
|
|
913
|
+
gap: "8px",
|
|
914
|
+
padding: "4px 10px",
|
|
915
|
+
borderRadius: "999px",
|
|
916
|
+
border: pending ? "1px solid rgba(251, 191, 36, 0.28)" : "1px solid rgba(74, 222, 128, 0.22)",
|
|
917
|
+
backgroundColor: pending ? "rgba(245, 158, 11, 0.12)" : "rgba(34, 197, 94, 0.12)",
|
|
918
|
+
color: pending ? "#fbbf24" : "#86efac",
|
|
919
|
+
fontSize: "11px",
|
|
920
|
+
fontWeight: 700,
|
|
921
|
+
letterSpacing: "0.08em",
|
|
922
|
+
textTransform: "uppercase"
|
|
923
|
+
});
|
|
924
|
+
const buildIndicatorDotStyle = (pending) => ({
|
|
925
|
+
width: "8px",
|
|
926
|
+
height: "8px",
|
|
927
|
+
borderRadius: "999px",
|
|
928
|
+
backgroundColor: pending ? "#f59e0b" : "#22c55e",
|
|
929
|
+
boxShadow: pending ? "0 0 0 4px rgba(245, 158, 11, 0.12)" : "0 0 0 4px rgba(34, 197, 94, 0.12)"
|
|
930
|
+
});
|
|
931
|
+
const buildInputShellStyle = (pending) => ({
|
|
932
|
+
display: "flex",
|
|
933
|
+
alignItems: "center",
|
|
934
|
+
gap: "12px",
|
|
935
|
+
border: pending ? "1px solid rgba(245, 158, 11, 0.35)" : "1px solid rgba(148, 163, 184, 0.18)",
|
|
936
|
+
borderRadius: "16px",
|
|
937
|
+
padding: "0 14px",
|
|
938
|
+
background: pending ? "rgba(35, 23, 8, 0.72)" : "rgba(15, 23, 42, 0.7)",
|
|
939
|
+
boxShadow: pending ? "0 0 0 1px rgba(245, 158, 11, 0.08)" : "none"
|
|
940
|
+
});
|
|
686
941
|
const inputStyle = {
|
|
687
942
|
width: "100%",
|
|
688
|
-
padding: "
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
fontSize: "14px"
|
|
943
|
+
padding: "14px 0",
|
|
944
|
+
border: "none",
|
|
945
|
+
outline: "none",
|
|
946
|
+
backgroundColor: "transparent",
|
|
947
|
+
color: "#f8fafc",
|
|
948
|
+
fontSize: "15px"
|
|
695
949
|
};
|
|
696
|
-
const
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
backgroundColor: "#1a1a1a"
|
|
950
|
+
const helperTextStyle = {
|
|
951
|
+
margin: "8px 0 0 0",
|
|
952
|
+
color: "#94a3b8",
|
|
953
|
+
fontSize: "12px",
|
|
954
|
+
lineHeight: 1.5
|
|
702
955
|
};
|
|
703
|
-
const
|
|
956
|
+
const codeStyle = {
|
|
704
957
|
display: "inline-block",
|
|
705
|
-
padding: "
|
|
706
|
-
|
|
707
|
-
|
|
958
|
+
padding: "2px 8px",
|
|
959
|
+
borderRadius: "999px",
|
|
960
|
+
backgroundColor: "rgba(148, 163, 184, 0.12)",
|
|
961
|
+
color: "#e2e8f0",
|
|
708
962
|
fontSize: "12px",
|
|
709
|
-
|
|
963
|
+
fontFamily: '"SF Mono", "Roboto Mono", monospace',
|
|
964
|
+
wordBreak: "break-all"
|
|
710
965
|
};
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
966
|
+
const buildButtonStyle = (variant, disabled = false) => {
|
|
967
|
+
const palette = {
|
|
968
|
+
ghost: {
|
|
969
|
+
background: "rgba(15, 23, 42, 0.5)",
|
|
970
|
+
border: "1px solid rgba(148, 163, 184, 0.18)",
|
|
971
|
+
color: "#dbe7ff"
|
|
972
|
+
},
|
|
973
|
+
primary: {
|
|
974
|
+
background: "linear-gradient(135deg, #38bdf8 0%, #2563eb 100%)",
|
|
975
|
+
border: "1px solid rgba(125, 211, 252, 0.32)",
|
|
976
|
+
color: "#eff6ff"
|
|
977
|
+
},
|
|
978
|
+
secondary: {
|
|
979
|
+
background: "linear-gradient(135deg, rgba(30, 41, 59, 0.92) 0%, rgba(15, 23, 42, 0.98) 100%)",
|
|
980
|
+
border: "1px solid rgba(148, 163, 184, 0.18)",
|
|
981
|
+
color: "#e2e8f0"
|
|
982
|
+
}
|
|
983
|
+
}[variant];
|
|
984
|
+
return {
|
|
985
|
+
display: "inline-flex",
|
|
986
|
+
alignItems: "center",
|
|
987
|
+
justifyContent: "center",
|
|
988
|
+
gap: "10px",
|
|
989
|
+
minHeight: "44px",
|
|
990
|
+
padding: "0 18px",
|
|
991
|
+
borderRadius: "14px",
|
|
992
|
+
background: palette.background,
|
|
993
|
+
border: palette.border,
|
|
994
|
+
color: palette.color,
|
|
995
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
996
|
+
opacity: disabled ? 0.45 : 1,
|
|
997
|
+
fontSize: "14px",
|
|
998
|
+
fontWeight: 700,
|
|
999
|
+
letterSpacing: "0.01em",
|
|
1000
|
+
transition: "all 0.2s ease",
|
|
1001
|
+
boxShadow: variant === "primary" && !disabled ? "0 16px 32px rgba(37, 99, 235, 0.28)" : "none"
|
|
1002
|
+
};
|
|
1003
|
+
};
|
|
1004
|
+
const buildStatusChipStyle = (active) => ({
|
|
1005
|
+
display: "inline-flex",
|
|
1006
|
+
alignItems: "center",
|
|
1007
|
+
gap: "8px",
|
|
1008
|
+
padding: "8px 12px",
|
|
1009
|
+
borderRadius: "999px",
|
|
1010
|
+
backgroundColor: active ? "rgba(34, 197, 94, 0.12)" : "rgba(248, 113, 113, 0.12)",
|
|
1011
|
+
border: active ? "1px solid rgba(34, 197, 94, 0.22)" : "1px solid rgba(248, 113, 113, 0.22)",
|
|
1012
|
+
color: active ? "#86efac" : "#fca5a5",
|
|
1013
|
+
fontSize: "12px",
|
|
1014
|
+
fontWeight: 700
|
|
1015
|
+
});
|
|
1016
|
+
const statusItems = [
|
|
1017
|
+
{ label: "Ready", value: Boolean(embedState.isReady) },
|
|
1018
|
+
{ label: "Played", value: Boolean(embedState.hasPlayedOnce) },
|
|
1019
|
+
{ label: "Try Now", value: Boolean(embedState.tryNow?.available) },
|
|
1020
|
+
{ label: "Buy Now", value: Boolean(embedState.buyNow?.available) }
|
|
1021
|
+
];
|
|
1022
|
+
const diagnosticGroups = [
|
|
1023
|
+
{
|
|
1024
|
+
title: "Compatibility",
|
|
1025
|
+
items: [
|
|
1026
|
+
{
|
|
1027
|
+
detail: "Playruo currently expects a non-mobile browser.",
|
|
1028
|
+
label: "Desktop browser",
|
|
1029
|
+
value: diagnostics.desktopBrowser
|
|
1030
|
+
},
|
|
1031
|
+
{
|
|
1032
|
+
detail: "The embed flow is tuned for Chromium-based browsers.",
|
|
1033
|
+
label: "Chromium browser",
|
|
1034
|
+
value: diagnostics.chromiumBrowser
|
|
1035
|
+
},
|
|
1036
|
+
{
|
|
1037
|
+
detail: "Keyboard lock works best when the page is not itself embedded.",
|
|
1038
|
+
label: "Top-level tab",
|
|
1039
|
+
value: diagnostics.topLevelContext
|
|
1040
|
+
},
|
|
1041
|
+
{
|
|
1042
|
+
detail: "HTTPS or localhost unlocks the best browser APIs.",
|
|
1043
|
+
label: "Secure context",
|
|
1044
|
+
value: diagnostics.secureContext
|
|
1045
|
+
}
|
|
1046
|
+
]
|
|
1047
|
+
},
|
|
1048
|
+
{
|
|
1049
|
+
title: "Gameplay APIs",
|
|
1050
|
+
items: [
|
|
1051
|
+
{
|
|
1052
|
+
detail: "Needed for the immersive play flow.",
|
|
1053
|
+
label: "Fullscreen API",
|
|
1054
|
+
value: diagnostics.fullscreenSupported
|
|
1055
|
+
},
|
|
1056
|
+
{
|
|
1057
|
+
detail: "Needed for raw mouse capture on the iframe.",
|
|
1058
|
+
label: "Pointer lock",
|
|
1059
|
+
value: diagnostics.pointerLockSupported
|
|
1060
|
+
},
|
|
1061
|
+
{
|
|
1062
|
+
detail: "Used to keep Escape reserved while fullscreen is active.",
|
|
1063
|
+
label: "Keyboard lock",
|
|
1064
|
+
value: diagnostics.keyboardLockSupported
|
|
1065
|
+
},
|
|
1066
|
+
{
|
|
1067
|
+
detail: "Lets the game read connected controllers.",
|
|
1068
|
+
label: "Gamepad API",
|
|
1069
|
+
value: diagnostics.gamepadSupported
|
|
1070
|
+
}
|
|
1071
|
+
]
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
title: "Performance",
|
|
1075
|
+
items: [
|
|
1076
|
+
{
|
|
1077
|
+
detail: "Improves the overall runtime budget for the experience.",
|
|
1078
|
+
label: "Cross-origin isolated",
|
|
1079
|
+
value: diagnostics.crossOriginIsolation
|
|
1080
|
+
},
|
|
1081
|
+
{
|
|
1082
|
+
detail: "Important for heavier threaded workloads.",
|
|
1083
|
+
label: "SharedArrayBuffer",
|
|
1084
|
+
value: diagnostics.sharedArrayBufferSupported
|
|
1085
|
+
},
|
|
1086
|
+
{
|
|
1087
|
+
detail: "Confirms modern rendering features are reachable.",
|
|
1088
|
+
label: "WebGL2",
|
|
1089
|
+
value: diagnostics.webgl2Supported
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
detail: "Confirms the runtime can execute compiled game code paths.",
|
|
1093
|
+
label: "WebAssembly",
|
|
1094
|
+
value: diagnostics.webAssemblySupported
|
|
1095
|
+
}
|
|
1096
|
+
]
|
|
1097
|
+
},
|
|
1098
|
+
{
|
|
1099
|
+
title: "Embed wiring",
|
|
1100
|
+
items: [
|
|
1101
|
+
{
|
|
1102
|
+
detail: "The iframe allow list includes fullscreen access.",
|
|
1103
|
+
label: "Iframe fullscreen allow",
|
|
1104
|
+
value: diagnostics.iframeAllowsFullscreen
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
detail: "The iframe allow list includes gamepad access.",
|
|
1108
|
+
label: "Iframe gamepad allow",
|
|
1109
|
+
value: diagnostics.iframeAllowsGamepad
|
|
1110
|
+
},
|
|
1111
|
+
{
|
|
1112
|
+
detail: "The iframe sandbox includes pointer-lock permission.",
|
|
1113
|
+
label: "Iframe pointer-lock allow",
|
|
1114
|
+
value: diagnostics.iframeAllowsPointerLock
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
detail: "Needed for UUID persistence and session continuity.",
|
|
1118
|
+
label: "Local storage",
|
|
1119
|
+
value: diagnostics.localStorageSupported
|
|
1120
|
+
}
|
|
1121
|
+
]
|
|
1122
|
+
}
|
|
1123
|
+
];
|
|
1124
|
+
const criticalDiagnosticChecks = [
|
|
1125
|
+
{ label: "Desktop browser", value: diagnostics.desktopBrowser },
|
|
1126
|
+
{ label: "Chromium browser", value: diagnostics.chromiumBrowser },
|
|
1127
|
+
{ label: "Fullscreen API", value: diagnostics.fullscreenSupported },
|
|
1128
|
+
{ label: "Pointer lock", value: diagnostics.pointerLockSupported }
|
|
1129
|
+
];
|
|
1130
|
+
const warningDiagnosticChecks = [
|
|
1131
|
+
{ label: "Top-level tab", value: diagnostics.topLevelContext },
|
|
1132
|
+
{ label: "Secure context", value: diagnostics.secureContext },
|
|
1133
|
+
{ label: "Cross-origin isolation", value: diagnostics.crossOriginIsolation },
|
|
1134
|
+
{ label: "SharedArrayBuffer", value: diagnostics.sharedArrayBufferSupported },
|
|
1135
|
+
{ label: "Keyboard lock", value: diagnostics.keyboardLockSupported },
|
|
1136
|
+
{ label: "Gamepad API", value: diagnostics.gamepadSupported },
|
|
1137
|
+
{ label: "WebGL2", value: diagnostics.webgl2Supported }
|
|
1138
|
+
];
|
|
1139
|
+
const blockingDiagnostics = criticalDiagnosticChecks.filter((item) => !item.value);
|
|
1140
|
+
const advisoryDiagnostics = warningDiagnosticChecks.filter((item) => !item.value);
|
|
1141
|
+
const diagnosticsVerdict = blockingDiagnostics.length > 0 ? {
|
|
1142
|
+
label: "Blocked",
|
|
1143
|
+
tone: "#fca5a5",
|
|
1144
|
+
background: "rgba(127, 29, 29, 0.28)",
|
|
1145
|
+
border: "1px solid rgba(248, 113, 113, 0.24)",
|
|
1146
|
+
text: "A core requirement is missing for the intended embed flow."
|
|
1147
|
+
} : advisoryDiagnostics.length > 0 ? {
|
|
1148
|
+
label: "Limited",
|
|
1149
|
+
tone: "#fde68a",
|
|
1150
|
+
background: "rgba(120, 53, 15, 0.24)",
|
|
1151
|
+
border: "1px solid rgba(245, 158, 11, 0.22)",
|
|
1152
|
+
text: "The embed should run, but some features or performance may be reduced."
|
|
1153
|
+
} : {
|
|
1154
|
+
label: "Ready",
|
|
1155
|
+
tone: "#86efac",
|
|
1156
|
+
background: "rgba(20, 83, 45, 0.24)",
|
|
1157
|
+
border: "1px solid rgba(34, 197, 94, 0.22)",
|
|
1158
|
+
text: "All key browser, performance, and iframe capabilities are present."
|
|
1159
|
+
};
|
|
1160
|
+
return /* @__PURE__ */ jsxs2(
|
|
1161
|
+
"div",
|
|
1162
|
+
{
|
|
1163
|
+
className: props.className,
|
|
1164
|
+
style: {
|
|
1165
|
+
position: "relative",
|
|
1166
|
+
minHeight: "100vh",
|
|
1167
|
+
overflow: "hidden",
|
|
1168
|
+
padding: "32px 20px 48px",
|
|
1169
|
+
background: "radial-gradient(circle at top left, rgba(56, 189, 248, 0.18) 0%, rgba(2, 6, 23, 0) 34%), radial-gradient(circle at 85% 10%, rgba(37, 99, 235, 0.18) 0%, rgba(2, 6, 23, 0) 26%), linear-gradient(180deg, #020617 0%, #050816 48%, #020617 100%)",
|
|
1170
|
+
color: "#e5e7eb"
|
|
1171
|
+
},
|
|
1172
|
+
children: [
|
|
1173
|
+
/* @__PURE__ */ jsxs2(
|
|
1174
|
+
"div",
|
|
1175
|
+
{
|
|
1176
|
+
style: {
|
|
1177
|
+
position: "absolute",
|
|
1178
|
+
inset: 0,
|
|
1179
|
+
overflow: "hidden",
|
|
1180
|
+
pointerEvents: "none"
|
|
1181
|
+
},
|
|
1182
|
+
children: [
|
|
1183
|
+
/* @__PURE__ */ jsx2(
|
|
1184
|
+
"div",
|
|
1185
|
+
{
|
|
1186
|
+
style: {
|
|
1187
|
+
position: "absolute",
|
|
1188
|
+
top: "-120px",
|
|
1189
|
+
left: "-120px",
|
|
1190
|
+
width: "320px",
|
|
1191
|
+
height: "320px",
|
|
1192
|
+
borderRadius: "999px",
|
|
1193
|
+
background: "rgba(56, 189, 248, 0.12)",
|
|
1194
|
+
filter: "blur(60px)"
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
),
|
|
1198
|
+
/* @__PURE__ */ jsx2(
|
|
1199
|
+
"div",
|
|
1200
|
+
{
|
|
1201
|
+
style: {
|
|
1202
|
+
position: "absolute",
|
|
1203
|
+
right: "-80px",
|
|
1204
|
+
top: "120px",
|
|
1205
|
+
width: "280px",
|
|
1206
|
+
height: "280px",
|
|
1207
|
+
borderRadius: "999px",
|
|
1208
|
+
background: "rgba(37, 99, 235, 0.12)",
|
|
1209
|
+
filter: "blur(60px)"
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
)
|
|
1213
|
+
]
|
|
1214
|
+
}
|
|
1215
|
+
),
|
|
1216
|
+
/* @__PURE__ */ jsxs2("div", { style: { position: "relative", maxWidth: "1280px", margin: "0 auto" }, children: [
|
|
743
1217
|
/* @__PURE__ */ jsx2(
|
|
744
|
-
"
|
|
1218
|
+
"div",
|
|
745
1219
|
{
|
|
746
|
-
type: "button",
|
|
747
1220
|
style: {
|
|
748
|
-
...
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
fontWeight: "600"
|
|
1221
|
+
...panelStyle,
|
|
1222
|
+
marginBottom: "24px",
|
|
1223
|
+
padding: "28px",
|
|
1224
|
+
background: "linear-gradient(135deg, rgba(15, 23, 42, 0.92) 0%, rgba(8, 15, 30, 0.98) 55%, rgba(15, 23, 42, 0.92) 100%)"
|
|
753
1225
|
},
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
1226
|
+
children: /* @__PURE__ */ jsxs2(
|
|
1227
|
+
"div",
|
|
1228
|
+
{
|
|
1229
|
+
style: {
|
|
1230
|
+
display: "flex",
|
|
1231
|
+
flexWrap: "wrap",
|
|
1232
|
+
gap: "20px",
|
|
1233
|
+
justifyContent: "space-between",
|
|
1234
|
+
alignItems: "flex-start"
|
|
1235
|
+
},
|
|
1236
|
+
children: [
|
|
1237
|
+
/* @__PURE__ */ jsxs2("div", { style: { maxWidth: "720px" }, children: [
|
|
1238
|
+
/* @__PURE__ */ jsx2(
|
|
1239
|
+
"div",
|
|
1240
|
+
{
|
|
1241
|
+
style: {
|
|
1242
|
+
display: "inline-flex",
|
|
1243
|
+
alignItems: "center",
|
|
1244
|
+
gap: "10px",
|
|
1245
|
+
padding: "6px 12px",
|
|
1246
|
+
borderRadius: "999px",
|
|
1247
|
+
backgroundColor: "rgba(56, 189, 248, 0.12)",
|
|
1248
|
+
border: "1px solid rgba(125, 211, 252, 0.18)",
|
|
1249
|
+
color: "#7dd3fc",
|
|
1250
|
+
fontSize: "11px",
|
|
1251
|
+
fontWeight: 700,
|
|
1252
|
+
letterSpacing: "0.12em",
|
|
1253
|
+
textTransform: "uppercase"
|
|
1254
|
+
},
|
|
1255
|
+
children: "\u{1F9EA} Playruo QA Surface"
|
|
1256
|
+
}
|
|
1257
|
+
),
|
|
1258
|
+
/* @__PURE__ */ jsx2(
|
|
1259
|
+
"h1",
|
|
1260
|
+
{
|
|
1261
|
+
style: {
|
|
1262
|
+
margin: "16px 0 12px 0",
|
|
1263
|
+
fontSize: "clamp(32px, 4vw, 46px)",
|
|
1264
|
+
lineHeight: 1.05,
|
|
1265
|
+
letterSpacing: "-0.04em",
|
|
1266
|
+
color: "#f8fafc"
|
|
1267
|
+
},
|
|
1268
|
+
children: "Embed Tester"
|
|
1269
|
+
}
|
|
1270
|
+
),
|
|
1271
|
+
/* @__PURE__ */ jsx2(
|
|
1272
|
+
"p",
|
|
1273
|
+
{
|
|
1274
|
+
style: {
|
|
1275
|
+
margin: 0,
|
|
1276
|
+
maxWidth: "640px",
|
|
1277
|
+
color: "#94a3b8",
|
|
1278
|
+
fontSize: "16px",
|
|
1279
|
+
lineHeight: 1.7
|
|
1280
|
+
},
|
|
1281
|
+
children: "Edit configuration safely, apply changes only when you decide to, and keep runtime feedback visible without the UI fighting your typing."
|
|
1282
|
+
}
|
|
1283
|
+
)
|
|
1284
|
+
] }),
|
|
1285
|
+
/* @__PURE__ */ jsxs2(
|
|
1286
|
+
"div",
|
|
1287
|
+
{
|
|
1288
|
+
style: {
|
|
1289
|
+
display: "grid",
|
|
1290
|
+
gap: "12px",
|
|
1291
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(160px, 1fr))",
|
|
1292
|
+
flex: "1 1 320px"
|
|
1293
|
+
},
|
|
1294
|
+
children: [
|
|
1295
|
+
/* @__PURE__ */ jsxs2(
|
|
1296
|
+
"div",
|
|
1297
|
+
{
|
|
1298
|
+
style: {
|
|
1299
|
+
padding: "16px",
|
|
1300
|
+
borderRadius: "18px",
|
|
1301
|
+
backgroundColor: "rgba(15, 23, 42, 0.72)",
|
|
1302
|
+
border: "1px solid rgba(148, 163, 184, 0.14)"
|
|
1303
|
+
},
|
|
1304
|
+
children: [
|
|
1305
|
+
/* @__PURE__ */ jsx2("div", { style: { fontSize: "12px", color: "#94a3b8", marginBottom: "8px" }, children: "Active host" }),
|
|
1306
|
+
/* @__PURE__ */ jsx2("div", { style: { color: "#f8fafc", fontSize: "16px", fontWeight: 700 }, children: displayHost })
|
|
1307
|
+
]
|
|
1308
|
+
}
|
|
1309
|
+
),
|
|
1310
|
+
/* @__PURE__ */ jsxs2(
|
|
1311
|
+
"div",
|
|
1312
|
+
{
|
|
1313
|
+
style: {
|
|
1314
|
+
padding: "16px",
|
|
1315
|
+
borderRadius: "18px",
|
|
1316
|
+
backgroundColor: hasPendingConfigChanges ? "rgba(35, 23, 8, 0.72)" : "rgba(15, 23, 42, 0.72)",
|
|
1317
|
+
border: hasPendingConfigChanges ? "1px solid rgba(245, 158, 11, 0.24)" : "1px solid rgba(148, 163, 184, 0.14)"
|
|
1318
|
+
},
|
|
1319
|
+
children: [
|
|
1320
|
+
/* @__PURE__ */ jsx2("div", { style: { fontSize: "12px", color: "#94a3b8", marginBottom: "8px" }, children: "Config state" }),
|
|
1321
|
+
/* @__PURE__ */ jsxs2(
|
|
1322
|
+
"div",
|
|
1323
|
+
{
|
|
1324
|
+
style: {
|
|
1325
|
+
display: "flex",
|
|
1326
|
+
alignItems: "center",
|
|
1327
|
+
gap: "10px",
|
|
1328
|
+
color: hasPendingConfigChanges ? "#fbbf24" : "#86efac",
|
|
1329
|
+
fontSize: "16px",
|
|
1330
|
+
fontWeight: 700
|
|
1331
|
+
},
|
|
1332
|
+
children: [
|
|
1333
|
+
/* @__PURE__ */ jsx2("span", { style: buildIndicatorDotStyle(hasPendingConfigChanges) }),
|
|
1334
|
+
hasPendingConfigChanges ? `${pendingChangeCount} pending change(s)` : "Everything applied"
|
|
1335
|
+
]
|
|
1336
|
+
}
|
|
1337
|
+
)
|
|
1338
|
+
]
|
|
1339
|
+
}
|
|
1340
|
+
)
|
|
1341
|
+
]
|
|
1342
|
+
}
|
|
1343
|
+
)
|
|
1344
|
+
]
|
|
1345
|
+
}
|
|
1346
|
+
)
|
|
758
1347
|
}
|
|
759
|
-
)
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
1348
|
+
),
|
|
1349
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexWrap: "wrap", gap: "24px", alignItems: "flex-start" }, children: [
|
|
1350
|
+
/* @__PURE__ */ jsxs2("div", { style: { flex: "1 1 380px", minWidth: "320px" }, children: [
|
|
1351
|
+
/* @__PURE__ */ jsxs2("div", { style: { ...panelStyle, marginBottom: "18px" }, children: [
|
|
1352
|
+
/* @__PURE__ */ jsxs2(
|
|
1353
|
+
"div",
|
|
1354
|
+
{
|
|
1355
|
+
style: {
|
|
1356
|
+
display: "flex",
|
|
1357
|
+
flexWrap: "wrap",
|
|
1358
|
+
justifyContent: "space-between",
|
|
1359
|
+
gap: "12px",
|
|
1360
|
+
marginBottom: "18px"
|
|
1361
|
+
},
|
|
1362
|
+
children: [
|
|
1363
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
1364
|
+
/* @__PURE__ */ jsx2("h3", { style: sectionTitleStyle, children: "Configuration" }),
|
|
1365
|
+
/* @__PURE__ */ jsxs2("p", { style: { ...helperTextStyle, marginTop: "6px" }, children: [
|
|
1366
|
+
"Draft values stay local until you press ",
|
|
1367
|
+
/* @__PURE__ */ jsx2("strong", { style: { color: "#e2e8f0" }, children: "Apply" }),
|
|
1368
|
+
"."
|
|
1369
|
+
] })
|
|
1370
|
+
] }),
|
|
1371
|
+
/* @__PURE__ */ jsxs2("div", { style: buildIndicatorStyle(hasPendingConfigChanges), children: [
|
|
1372
|
+
/* @__PURE__ */ jsx2("span", { style: buildIndicatorDotStyle(hasPendingConfigChanges) }),
|
|
1373
|
+
hasPendingConfigChanges ? "Not applied" : "Applied"
|
|
1374
|
+
] })
|
|
1375
|
+
]
|
|
1376
|
+
}
|
|
1377
|
+
),
|
|
1378
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "grid", gap: "16px" }, children: [
|
|
1379
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
1380
|
+
/* @__PURE__ */ jsxs2("label", { htmlFor: "operation", style: labelStyle, children: [
|
|
1381
|
+
/* @__PURE__ */ jsx2("span", { children: "Operation" }),
|
|
1382
|
+
/* @__PURE__ */ jsxs2("span", { style: buildIndicatorStyle(isOperationPending), children: [
|
|
1383
|
+
/* @__PURE__ */ jsx2("span", { style: buildIndicatorDotStyle(isOperationPending) }),
|
|
1384
|
+
isOperationPending ? "Pending" : "Live"
|
|
1385
|
+
] })
|
|
1386
|
+
] }),
|
|
1387
|
+
/* @__PURE__ */ jsxs2("div", { style: buildInputShellStyle(isOperationPending), children: [
|
|
1388
|
+
/* @__PURE__ */ jsx2(
|
|
1389
|
+
"input",
|
|
1390
|
+
{
|
|
1391
|
+
id: "operation",
|
|
1392
|
+
style: inputStyle,
|
|
1393
|
+
onChange: (e) => setOperationDraft(e.target.value),
|
|
1394
|
+
placeholder: "e.g. iframe",
|
|
1395
|
+
value: operationDraft
|
|
1396
|
+
}
|
|
1397
|
+
),
|
|
1398
|
+
isOperationPending && /* @__PURE__ */ jsx2(
|
|
1399
|
+
"span",
|
|
1400
|
+
{
|
|
1401
|
+
"aria-hidden": "true",
|
|
1402
|
+
style: {
|
|
1403
|
+
fontSize: "16px",
|
|
1404
|
+
color: "#fbbf24",
|
|
1405
|
+
fontWeight: 700
|
|
1406
|
+
},
|
|
1407
|
+
children: "!"
|
|
1408
|
+
}
|
|
1409
|
+
)
|
|
1410
|
+
] }),
|
|
1411
|
+
/* @__PURE__ */ jsxs2("p", { style: helperTextStyle, children: [
|
|
1412
|
+
"Applied value: ",
|
|
1413
|
+
/* @__PURE__ */ jsx2("code", { style: codeStyle, children: appliedOperation })
|
|
1414
|
+
] })
|
|
1415
|
+
] }),
|
|
1416
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
1417
|
+
/* @__PURE__ */ jsxs2("label", { htmlFor: "storeUrl", style: labelStyle, children: [
|
|
1418
|
+
/* @__PURE__ */ jsx2("span", { children: "Store URL" }),
|
|
1419
|
+
/* @__PURE__ */ jsxs2("span", { style: buildIndicatorStyle(isStoreUrlPending), children: [
|
|
1420
|
+
/* @__PURE__ */ jsx2("span", { style: buildIndicatorDotStyle(isStoreUrlPending) }),
|
|
1421
|
+
isStoreUrlPending ? "Pending" : "Live"
|
|
1422
|
+
] })
|
|
1423
|
+
] }),
|
|
1424
|
+
/* @__PURE__ */ jsxs2("div", { style: buildInputShellStyle(isStoreUrlPending), children: [
|
|
1425
|
+
/* @__PURE__ */ jsx2(
|
|
1426
|
+
"input",
|
|
1427
|
+
{
|
|
1428
|
+
id: "storeUrl",
|
|
1429
|
+
style: inputStyle,
|
|
1430
|
+
onChange: (e) => setStoreUrlDraft(e.target.value),
|
|
1431
|
+
placeholder: "https://store.example.com",
|
|
1432
|
+
value: storeUrlDraft
|
|
1433
|
+
}
|
|
1434
|
+
),
|
|
1435
|
+
isStoreUrlPending && /* @__PURE__ */ jsx2(
|
|
1436
|
+
"span",
|
|
1437
|
+
{
|
|
1438
|
+
"aria-hidden": "true",
|
|
1439
|
+
style: {
|
|
1440
|
+
fontSize: "16px",
|
|
1441
|
+
color: "#fbbf24",
|
|
1442
|
+
fontWeight: 700
|
|
1443
|
+
},
|
|
1444
|
+
children: "!"
|
|
1445
|
+
}
|
|
1446
|
+
)
|
|
1447
|
+
] }),
|
|
1448
|
+
/* @__PURE__ */ jsxs2("p", { style: helperTextStyle, children: [
|
|
1449
|
+
"Applied value: ",
|
|
1450
|
+
/* @__PURE__ */ jsx2("code", { style: codeStyle, children: appliedStoreUrl })
|
|
1451
|
+
] })
|
|
1452
|
+
] })
|
|
1453
|
+
] }),
|
|
1454
|
+
/* @__PURE__ */ jsxs2(
|
|
1455
|
+
"div",
|
|
1456
|
+
{
|
|
1457
|
+
style: {
|
|
1458
|
+
display: "flex",
|
|
1459
|
+
flexWrap: "wrap",
|
|
1460
|
+
gap: "12px",
|
|
1461
|
+
marginTop: "20px"
|
|
1462
|
+
},
|
|
1463
|
+
children: [
|
|
1464
|
+
/* @__PURE__ */ jsx2(
|
|
1465
|
+
"button",
|
|
1466
|
+
{
|
|
1467
|
+
type: "button",
|
|
1468
|
+
style: buildButtonStyle("primary", !hasPendingConfigChanges),
|
|
1469
|
+
disabled: !hasPendingConfigChanges,
|
|
1470
|
+
onClick: handleApply,
|
|
1471
|
+
children: "Apply"
|
|
1472
|
+
}
|
|
1473
|
+
),
|
|
1474
|
+
/* @__PURE__ */ jsx2(
|
|
1475
|
+
"button",
|
|
1476
|
+
{
|
|
1477
|
+
type: "button",
|
|
1478
|
+
style: buildButtonStyle("secondary"),
|
|
1479
|
+
onClick: handleRestartSession,
|
|
1480
|
+
children: "Restart Session"
|
|
1481
|
+
}
|
|
1482
|
+
),
|
|
1483
|
+
/* @__PURE__ */ jsx2(
|
|
1484
|
+
"button",
|
|
1485
|
+
{
|
|
1486
|
+
type: "button",
|
|
1487
|
+
style: buildButtonStyle("ghost", !hasPendingConfigChanges),
|
|
1488
|
+
disabled: !hasPendingConfigChanges,
|
|
1489
|
+
onClick: handleResetDrafts,
|
|
1490
|
+
children: "Reset Drafts"
|
|
1491
|
+
}
|
|
1492
|
+
)
|
|
1493
|
+
]
|
|
1494
|
+
}
|
|
1495
|
+
)
|
|
1496
|
+
] }),
|
|
1497
|
+
/* @__PURE__ */ jsxs2("div", { style: { ...panelStyle, marginBottom: "18px" }, children: [
|
|
1498
|
+
/* @__PURE__ */ jsx2("h3", { style: sectionTitleStyle, children: "Runtime status" }),
|
|
1499
|
+
/* @__PURE__ */ jsx2("div", { style: { display: "flex", flexWrap: "wrap", gap: "10px", marginTop: "16px" }, children: statusItems.map((item) => /* @__PURE__ */ jsxs2("span", { style: buildStatusChipStyle(item.value), children: [
|
|
1500
|
+
/* @__PURE__ */ jsx2("span", { children: item.value ? "\u25CF" : "\u25CB" }),
|
|
1501
|
+
item.label
|
|
1502
|
+
] }, item.label)) }),
|
|
1503
|
+
!embedState.tryNow?.available && embedState.tryNow?.status && /* @__PURE__ */ jsxs2("p", { style: { ...helperTextStyle, marginTop: "14px" }, children: [
|
|
1504
|
+
"Try Now reason: ",
|
|
1505
|
+
/* @__PURE__ */ jsx2("span", { style: { color: "#cbd5e1" }, children: embedState.tryNow.status })
|
|
1506
|
+
] })
|
|
869
1507
|
] }),
|
|
870
|
-
|
|
1508
|
+
/* @__PURE__ */ jsxs2("div", { style: { ...panelStyle, marginBottom: "18px" }, children: [
|
|
1509
|
+
/* @__PURE__ */ jsx2("h3", { style: sectionTitleStyle, children: "Browser diagnostics" }),
|
|
1510
|
+
/* @__PURE__ */ jsxs2(
|
|
1511
|
+
"div",
|
|
1512
|
+
{
|
|
1513
|
+
style: {
|
|
1514
|
+
marginTop: "16px",
|
|
1515
|
+
padding: "16px 18px",
|
|
1516
|
+
borderRadius: "20px",
|
|
1517
|
+
background: diagnosticsVerdict.background,
|
|
1518
|
+
border: diagnosticsVerdict.border
|
|
1519
|
+
},
|
|
1520
|
+
children: [
|
|
1521
|
+
/* @__PURE__ */ jsxs2(
|
|
1522
|
+
"div",
|
|
1523
|
+
{
|
|
1524
|
+
style: {
|
|
1525
|
+
display: "flex",
|
|
1526
|
+
flexWrap: "wrap",
|
|
1527
|
+
justifyContent: "space-between",
|
|
1528
|
+
gap: "12px",
|
|
1529
|
+
alignItems: "center"
|
|
1530
|
+
},
|
|
1531
|
+
children: [
|
|
1532
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
1533
|
+
/* @__PURE__ */ jsx2(
|
|
1534
|
+
"div",
|
|
1535
|
+
{
|
|
1536
|
+
style: {
|
|
1537
|
+
color: diagnosticsVerdict.tone,
|
|
1538
|
+
fontSize: "12px",
|
|
1539
|
+
fontWeight: 700,
|
|
1540
|
+
letterSpacing: "0.1em",
|
|
1541
|
+
textTransform: "uppercase"
|
|
1542
|
+
},
|
|
1543
|
+
children: "Diagnostics verdict"
|
|
1544
|
+
}
|
|
1545
|
+
),
|
|
1546
|
+
/* @__PURE__ */ jsx2("div", { style: { color: "#f8fafc", fontSize: "20px", fontWeight: 700, marginTop: "6px" }, children: diagnosticsVerdict.label })
|
|
1547
|
+
] }),
|
|
1548
|
+
/* @__PURE__ */ jsx2("div", { style: { color: "#cbd5e1", fontSize: "13px", maxWidth: "420px", lineHeight: 1.6 }, children: diagnosticsVerdict.text })
|
|
1549
|
+
]
|
|
1550
|
+
}
|
|
1551
|
+
),
|
|
1552
|
+
(blockingDiagnostics.length > 0 || advisoryDiagnostics.length > 0) && /* @__PURE__ */ jsxs2(
|
|
1553
|
+
"div",
|
|
1554
|
+
{
|
|
1555
|
+
style: {
|
|
1556
|
+
display: "grid",
|
|
1557
|
+
gap: "10px",
|
|
1558
|
+
marginTop: "16px"
|
|
1559
|
+
},
|
|
1560
|
+
children: [
|
|
1561
|
+
blockingDiagnostics.length > 0 && /* @__PURE__ */ jsxs2("div", { style: { color: "#fca5a5", fontSize: "13px", lineHeight: 1.6 }, children: [
|
|
1562
|
+
"Blocking: ",
|
|
1563
|
+
blockingDiagnostics.map((item) => item.label).join(", ")
|
|
1564
|
+
] }),
|
|
1565
|
+
advisoryDiagnostics.length > 0 && /* @__PURE__ */ jsxs2("div", { style: { color: "#fde68a", fontSize: "13px", lineHeight: 1.6 }, children: [
|
|
1566
|
+
"Worth checking: ",
|
|
1567
|
+
advisoryDiagnostics.map((item) => item.label).join(", ")
|
|
1568
|
+
] })
|
|
1569
|
+
]
|
|
1570
|
+
}
|
|
1571
|
+
)
|
|
1572
|
+
]
|
|
1573
|
+
}
|
|
1574
|
+
),
|
|
1575
|
+
/* @__PURE__ */ jsx2(
|
|
1576
|
+
"div",
|
|
1577
|
+
{
|
|
1578
|
+
style: {
|
|
1579
|
+
display: "grid",
|
|
1580
|
+
gap: "14px",
|
|
1581
|
+
marginTop: "18px"
|
|
1582
|
+
},
|
|
1583
|
+
children: diagnosticGroups.map((group) => /* @__PURE__ */ jsxs2(
|
|
1584
|
+
"div",
|
|
1585
|
+
{
|
|
1586
|
+
style: {
|
|
1587
|
+
padding: "16px",
|
|
1588
|
+
borderRadius: "20px",
|
|
1589
|
+
backgroundColor: "rgba(15, 23, 42, 0.42)",
|
|
1590
|
+
border: "1px solid rgba(148, 163, 184, 0.12)"
|
|
1591
|
+
},
|
|
1592
|
+
children: [
|
|
1593
|
+
/* @__PURE__ */ jsx2(
|
|
1594
|
+
"div",
|
|
1595
|
+
{
|
|
1596
|
+
style: {
|
|
1597
|
+
color: "#e2e8f0",
|
|
1598
|
+
fontSize: "14px",
|
|
1599
|
+
fontWeight: 700,
|
|
1600
|
+
marginBottom: "14px"
|
|
1601
|
+
},
|
|
1602
|
+
children: group.title
|
|
1603
|
+
}
|
|
1604
|
+
),
|
|
1605
|
+
/* @__PURE__ */ jsx2(
|
|
1606
|
+
"div",
|
|
1607
|
+
{
|
|
1608
|
+
style: {
|
|
1609
|
+
display: "grid",
|
|
1610
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(190px, 1fr))",
|
|
1611
|
+
gap: "12px"
|
|
1612
|
+
},
|
|
1613
|
+
children: group.items.map((item) => /* @__PURE__ */ jsxs2(
|
|
1614
|
+
"div",
|
|
1615
|
+
{
|
|
1616
|
+
style: {
|
|
1617
|
+
padding: "14px 16px",
|
|
1618
|
+
borderRadius: "18px",
|
|
1619
|
+
backgroundColor: item.value ? "rgba(8, 31, 17, 0.72)" : "rgba(42, 12, 12, 0.52)",
|
|
1620
|
+
border: item.value ? "1px solid rgba(34, 197, 94, 0.18)" : "1px solid rgba(248, 113, 113, 0.18)"
|
|
1621
|
+
},
|
|
1622
|
+
children: [
|
|
1623
|
+
/* @__PURE__ */ jsx2("div", { style: { color: "#94a3b8", fontSize: "12px", marginBottom: "8px" }, children: item.label }),
|
|
1624
|
+
/* @__PURE__ */ jsxs2(
|
|
1625
|
+
"div",
|
|
1626
|
+
{
|
|
1627
|
+
style: {
|
|
1628
|
+
display: "flex",
|
|
1629
|
+
alignItems: "center",
|
|
1630
|
+
gap: "8px",
|
|
1631
|
+
color: item.value ? "#86efac" : "#fca5a5",
|
|
1632
|
+
fontWeight: 700
|
|
1633
|
+
},
|
|
1634
|
+
children: [
|
|
1635
|
+
/* @__PURE__ */ jsx2("span", { children: item.value ? "\u2713" : "\u2715" }),
|
|
1636
|
+
item.value ? "Available" : "Missing"
|
|
1637
|
+
]
|
|
1638
|
+
}
|
|
1639
|
+
),
|
|
1640
|
+
/* @__PURE__ */ jsx2("div", { style: { color: "#94a3b8", fontSize: "12px", lineHeight: 1.5, marginTop: "10px" }, children: item.detail })
|
|
1641
|
+
]
|
|
1642
|
+
},
|
|
1643
|
+
item.label
|
|
1644
|
+
))
|
|
1645
|
+
}
|
|
1646
|
+
)
|
|
1647
|
+
]
|
|
1648
|
+
},
|
|
1649
|
+
group.title
|
|
1650
|
+
))
|
|
1651
|
+
}
|
|
1652
|
+
)
|
|
1653
|
+
] }),
|
|
1654
|
+
/* @__PURE__ */ jsxs2("div", { style: panelStyle, children: [
|
|
1655
|
+
/* @__PURE__ */ jsxs2(
|
|
1656
|
+
"div",
|
|
1657
|
+
{
|
|
1658
|
+
style: {
|
|
1659
|
+
display: "flex",
|
|
1660
|
+
justifyContent: "space-between",
|
|
1661
|
+
alignItems: "center",
|
|
1662
|
+
gap: "12px",
|
|
1663
|
+
marginBottom: "16px"
|
|
1664
|
+
},
|
|
1665
|
+
children: [
|
|
1666
|
+
/* @__PURE__ */ jsx2("h3", { style: sectionTitleStyle, children: "Event log" }),
|
|
1667
|
+
/* @__PURE__ */ jsxs2("span", { style: { ...codeStyle, padding: "4px 10px" }, children: [
|
|
1668
|
+
eventLog.length,
|
|
1669
|
+
" recent events"
|
|
1670
|
+
] })
|
|
1671
|
+
]
|
|
1672
|
+
}
|
|
1673
|
+
),
|
|
1674
|
+
/* @__PURE__ */ jsx2(
|
|
1675
|
+
"div",
|
|
1676
|
+
{
|
|
1677
|
+
style: {
|
|
1678
|
+
background: "linear-gradient(180deg, rgba(2, 6, 23, 0.88) 0%, rgba(2, 6, 23, 0.64) 100%)",
|
|
1679
|
+
padding: "14px",
|
|
1680
|
+
borderRadius: "18px",
|
|
1681
|
+
minHeight: "220px",
|
|
1682
|
+
height: "min(46vh, 420px)",
|
|
1683
|
+
overflowY: "auto",
|
|
1684
|
+
fontFamily: '"SF Mono", "Roboto Mono", monospace',
|
|
1685
|
+
fontSize: "12px",
|
|
1686
|
+
border: "1px solid rgba(148, 163, 184, 0.12)"
|
|
1687
|
+
},
|
|
1688
|
+
children: eventLog.length ? /* @__PURE__ */ jsx2("div", { style: { display: "grid", gap: "10px" }, children: eventLog.map((event) => /* @__PURE__ */ jsxs2(
|
|
1689
|
+
"div",
|
|
1690
|
+
{
|
|
1691
|
+
style: {
|
|
1692
|
+
paddingBottom: "10px",
|
|
1693
|
+
borderBottom: "1px solid rgba(148, 163, 184, 0.08)"
|
|
1694
|
+
},
|
|
1695
|
+
children: [
|
|
1696
|
+
/* @__PURE__ */ jsx2("div", { style: { color: "#64748b", marginBottom: "4px" }, children: event.timestamp }),
|
|
1697
|
+
/* @__PURE__ */ jsx2("div", { style: { color: "#e2e8f0", lineHeight: 1.6 }, children: event.message })
|
|
1698
|
+
]
|
|
1699
|
+
},
|
|
1700
|
+
event.id
|
|
1701
|
+
)) }) : /* @__PURE__ */ jsx2("div", { style: { color: "#64748b" }, children: "No events yet. Start a session or apply a config change." })
|
|
1702
|
+
}
|
|
1703
|
+
)
|
|
1704
|
+
] })
|
|
1705
|
+
] }),
|
|
1706
|
+
/* @__PURE__ */ jsx2("div", { style: { flex: "1 1 560px", minWidth: "320px" }, children: /* @__PURE__ */ jsxs2("div", { style: { ...panelStyle, padding: "24px" }, children: [
|
|
871
1707
|
/* @__PURE__ */ jsxs2(
|
|
872
|
-
"
|
|
1708
|
+
"div",
|
|
873
1709
|
{
|
|
874
|
-
type: "button",
|
|
875
1710
|
style: {
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
fontWeight: "600",
|
|
883
|
-
cursor: actions.canTryNow ? "pointer" : "not-allowed",
|
|
884
|
-
opacity: actions.canTryNow ? 1 : 0.5
|
|
885
|
-
},
|
|
886
|
-
disabled: !actions.canTryNow,
|
|
887
|
-
onMouseEnter: (e) => {
|
|
888
|
-
if (actions.canTryNow) {
|
|
889
|
-
e.currentTarget.style.backgroundColor = "#15803d";
|
|
890
|
-
}
|
|
891
|
-
},
|
|
892
|
-
onMouseLeave: (e) => {
|
|
893
|
-
if (actions.canTryNow) {
|
|
894
|
-
e.currentTarget.style.backgroundColor = "#16a34a";
|
|
895
|
-
}
|
|
896
|
-
},
|
|
897
|
-
onClick: () => {
|
|
898
|
-
setHasUserClicked(true);
|
|
899
|
-
setShowIframe(true);
|
|
900
|
-
addEvent(embedState.hasPlayedOnce ? "User clicked - Resuming game" : "User clicked - Starting game with tryNow");
|
|
901
|
-
actions.tryNow();
|
|
1711
|
+
display: "flex",
|
|
1712
|
+
flexWrap: "wrap",
|
|
1713
|
+
justifyContent: "space-between",
|
|
1714
|
+
alignItems: "center",
|
|
1715
|
+
gap: "12px",
|
|
1716
|
+
marginBottom: "16px"
|
|
902
1717
|
},
|
|
903
1718
|
children: [
|
|
904
|
-
"
|
|
905
|
-
|
|
1719
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
1720
|
+
/* @__PURE__ */ jsx2("h3", { style: sectionTitleStyle, children: "Embed preview" }),
|
|
1721
|
+
/* @__PURE__ */ jsx2("p", { style: { ...helperTextStyle, marginTop: "6px" }, children: "The live iframe always reflects the applied configuration." })
|
|
1722
|
+
] }),
|
|
1723
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexWrap: "wrap", gap: "10px" }, children: [
|
|
1724
|
+
/* @__PURE__ */ jsxs2("span", { style: { ...codeStyle, padding: "6px 10px" }, children: [
|
|
1725
|
+
"Host: ",
|
|
1726
|
+
displayHost
|
|
1727
|
+
] }),
|
|
1728
|
+
/* @__PURE__ */ jsxs2("span", { style: { ...codeStyle, padding: "6px 10px" }, children: [
|
|
1729
|
+
"Operation: ",
|
|
1730
|
+
appliedOperation
|
|
1731
|
+
] })
|
|
1732
|
+
] })
|
|
906
1733
|
]
|
|
907
1734
|
}
|
|
908
1735
|
),
|
|
909
|
-
|
|
910
|
-
"
|
|
1736
|
+
hasPendingConfigChanges && /* @__PURE__ */ jsxs2(
|
|
1737
|
+
"div",
|
|
911
1738
|
{
|
|
912
|
-
type: "button",
|
|
913
1739
|
style: {
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1740
|
+
display: "flex",
|
|
1741
|
+
alignItems: "center",
|
|
1742
|
+
gap: "12px",
|
|
1743
|
+
padding: "14px 16px",
|
|
1744
|
+
marginBottom: "16px",
|
|
1745
|
+
borderRadius: "18px",
|
|
1746
|
+
backgroundColor: "rgba(35, 23, 8, 0.72)",
|
|
1747
|
+
border: "1px solid rgba(245, 158, 11, 0.22)",
|
|
1748
|
+
color: "#fde68a"
|
|
921
1749
|
},
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1750
|
+
children: [
|
|
1751
|
+
/* @__PURE__ */ jsx2("span", { style: buildIndicatorDotStyle(true) }),
|
|
1752
|
+
"Draft values are ready but not applied to the iframe yet."
|
|
1753
|
+
]
|
|
1754
|
+
}
|
|
1755
|
+
),
|
|
1756
|
+
/* @__PURE__ */ jsxs2(
|
|
1757
|
+
"div",
|
|
1758
|
+
{
|
|
1759
|
+
style: {
|
|
1760
|
+
position: "relative",
|
|
1761
|
+
minHeight: "640px",
|
|
1762
|
+
overflow: "hidden",
|
|
1763
|
+
borderRadius: "24px",
|
|
1764
|
+
border: "1px solid rgba(148, 163, 184, 0.14)",
|
|
1765
|
+
background: "linear-gradient(180deg, rgba(3, 7, 18, 0.86) 0%, rgba(2, 6, 23, 1) 100%)",
|
|
1766
|
+
boxShadow: "inset 0 1px 0 rgba(255, 255, 255, 0.04)"
|
|
927
1767
|
},
|
|
928
|
-
children:
|
|
1768
|
+
children: [
|
|
1769
|
+
/* @__PURE__ */ jsxs2(
|
|
1770
|
+
"div",
|
|
1771
|
+
{
|
|
1772
|
+
style: {
|
|
1773
|
+
display: "flex",
|
|
1774
|
+
alignItems: "center",
|
|
1775
|
+
justifyContent: "space-between",
|
|
1776
|
+
gap: "12px",
|
|
1777
|
+
padding: "14px 18px",
|
|
1778
|
+
borderBottom: "1px solid rgba(148, 163, 184, 0.08)",
|
|
1779
|
+
backgroundColor: "rgba(15, 23, 42, 0.52)"
|
|
1780
|
+
},
|
|
1781
|
+
children: [
|
|
1782
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
1783
|
+
/* @__PURE__ */ jsx2("span", { style: { width: "10px", height: "10px", borderRadius: "999px", backgroundColor: "#f97316" } }),
|
|
1784
|
+
/* @__PURE__ */ jsx2("span", { style: { width: "10px", height: "10px", borderRadius: "999px", backgroundColor: "#facc15" } }),
|
|
1785
|
+
/* @__PURE__ */ jsx2("span", { style: { width: "10px", height: "10px", borderRadius: "999px", backgroundColor: "#4ade80" } })
|
|
1786
|
+
] }),
|
|
1787
|
+
/* @__PURE__ */ jsxs2("span", { style: { color: "#94a3b8", fontSize: "12px", fontFamily: '"SF Mono", "Roboto Mono", monospace' }, children: [
|
|
1788
|
+
"/embed?operation=",
|
|
1789
|
+
appliedOperation
|
|
1790
|
+
] })
|
|
1791
|
+
]
|
|
1792
|
+
}
|
|
1793
|
+
),
|
|
1794
|
+
/* @__PURE__ */ jsx2(
|
|
1795
|
+
PlayruoEmbed,
|
|
1796
|
+
{
|
|
1797
|
+
baseUrl: props.baseUrl,
|
|
1798
|
+
className: "w-full h-full absolute inset-0",
|
|
1799
|
+
iframeRef,
|
|
1800
|
+
onDemoCompleted: handleDemoCompleted,
|
|
1801
|
+
onError: handleError,
|
|
1802
|
+
onEvent: handleEvent,
|
|
1803
|
+
onPurchaseRequest: handlePurchaseRequest,
|
|
1804
|
+
onReady: handleReady,
|
|
1805
|
+
onStateChange: handleStateChange,
|
|
1806
|
+
operation: appliedOperation,
|
|
1807
|
+
renderState: ({ actions, message, status }) => /* @__PURE__ */ jsx2(Fragment, { children: !hasUserClicked && /* @__PURE__ */ jsx2(
|
|
1808
|
+
"div",
|
|
1809
|
+
{
|
|
1810
|
+
style: {
|
|
1811
|
+
position: "absolute",
|
|
1812
|
+
inset: "53px 0 0 0",
|
|
1813
|
+
display: "flex",
|
|
1814
|
+
alignItems: "center",
|
|
1815
|
+
justifyContent: "center",
|
|
1816
|
+
padding: "24px",
|
|
1817
|
+
background: "linear-gradient(180deg, rgba(2, 6, 23, 0.4) 0%, rgba(2, 6, 23, 0.84) 70%, rgba(2, 6, 23, 0.9) 100%)",
|
|
1818
|
+
backdropFilter: "blur(12px)",
|
|
1819
|
+
zIndex: 50
|
|
1820
|
+
},
|
|
1821
|
+
children: /* @__PURE__ */ jsxs2(
|
|
1822
|
+
"div",
|
|
1823
|
+
{
|
|
1824
|
+
style: {
|
|
1825
|
+
width: "min(100%, 420px)",
|
|
1826
|
+
padding: "28px",
|
|
1827
|
+
borderRadius: "28px",
|
|
1828
|
+
border: "1px solid rgba(148, 163, 184, 0.18)",
|
|
1829
|
+
background: "linear-gradient(180deg, rgba(15, 23, 42, 0.94) 0%, rgba(7, 12, 24, 0.98) 100%)",
|
|
1830
|
+
boxShadow: "0 32px 72px rgba(0, 0, 0, 0.35)"
|
|
1831
|
+
},
|
|
1832
|
+
children: [
|
|
1833
|
+
/* @__PURE__ */ jsx2(
|
|
1834
|
+
"div",
|
|
1835
|
+
{
|
|
1836
|
+
style: {
|
|
1837
|
+
display: "inline-flex",
|
|
1838
|
+
alignItems: "center",
|
|
1839
|
+
gap: "10px",
|
|
1840
|
+
padding: "6px 12px",
|
|
1841
|
+
borderRadius: "999px",
|
|
1842
|
+
backgroundColor: "rgba(56, 189, 248, 0.12)",
|
|
1843
|
+
border: "1px solid rgba(125, 211, 252, 0.18)",
|
|
1844
|
+
color: "#7dd3fc",
|
|
1845
|
+
fontSize: "11px",
|
|
1846
|
+
fontWeight: 700,
|
|
1847
|
+
letterSpacing: "0.08em",
|
|
1848
|
+
textTransform: "uppercase"
|
|
1849
|
+
},
|
|
1850
|
+
children: "Live overlay"
|
|
1851
|
+
}
|
|
1852
|
+
),
|
|
1853
|
+
/* @__PURE__ */ jsx2(
|
|
1854
|
+
"h4",
|
|
1855
|
+
{
|
|
1856
|
+
style: {
|
|
1857
|
+
margin: "18px 0 10px 0",
|
|
1858
|
+
color: "#f8fafc",
|
|
1859
|
+
fontSize: "28px",
|
|
1860
|
+
letterSpacing: "-0.03em"
|
|
1861
|
+
},
|
|
1862
|
+
children: embedState.hasPlayedOnce ? "Resume the session" : "Start the demo"
|
|
1863
|
+
}
|
|
1864
|
+
),
|
|
1865
|
+
/* @__PURE__ */ jsxs2("p", { style: { margin: 0, color: "#94a3b8", lineHeight: 1.7 }, children: [
|
|
1866
|
+
"Status: ",
|
|
1867
|
+
/* @__PURE__ */ jsx2("span", { style: { color: "#f8fafc", fontWeight: 700 }, children: status })
|
|
1868
|
+
] }),
|
|
1869
|
+
message && /* @__PURE__ */ jsx2("p", { style: { margin: "10px 0 0 0", color: "#cbd5e1", lineHeight: 1.7 }, children: message }),
|
|
1870
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexWrap: "wrap", gap: "12px", marginTop: "24px" }, children: [
|
|
1871
|
+
/* @__PURE__ */ jsxs2(
|
|
1872
|
+
"button",
|
|
1873
|
+
{
|
|
1874
|
+
type: "button",
|
|
1875
|
+
style: buildButtonStyle("primary", !actions.canTryNow),
|
|
1876
|
+
disabled: !actions.canTryNow,
|
|
1877
|
+
onClick: () => {
|
|
1878
|
+
setHasUserClicked(true);
|
|
1879
|
+
setShowIframe(true);
|
|
1880
|
+
addEvent(
|
|
1881
|
+
embedState.hasPlayedOnce ? "User clicked - Resuming game" : "User clicked - Starting game with tryNow"
|
|
1882
|
+
);
|
|
1883
|
+
actions.tryNow();
|
|
1884
|
+
},
|
|
1885
|
+
children: [
|
|
1886
|
+
"\u{1F3AE} ",
|
|
1887
|
+
embedState.hasPlayedOnce ? "Resume game" : "Try demo now"
|
|
1888
|
+
]
|
|
1889
|
+
}
|
|
1890
|
+
),
|
|
1891
|
+
actions.canBuyNow && /* @__PURE__ */ jsx2(
|
|
1892
|
+
"button",
|
|
1893
|
+
{
|
|
1894
|
+
type: "button",
|
|
1895
|
+
style: buildButtonStyle("secondary"),
|
|
1896
|
+
onClick: () => {
|
|
1897
|
+
addEvent("Buy Now clicked");
|
|
1898
|
+
actions.buyNow();
|
|
1899
|
+
},
|
|
1900
|
+
children: "Buy Now"
|
|
1901
|
+
}
|
|
1902
|
+
)
|
|
1903
|
+
] })
|
|
1904
|
+
]
|
|
1905
|
+
}
|
|
1906
|
+
)
|
|
1907
|
+
}
|
|
1908
|
+
) }),
|
|
1909
|
+
showIframe,
|
|
1910
|
+
storeUrl: appliedStoreUrl
|
|
1911
|
+
},
|
|
1912
|
+
key
|
|
1913
|
+
)
|
|
1914
|
+
]
|
|
929
1915
|
}
|
|
930
1916
|
)
|
|
931
|
-
] }) })
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
] }) })
|
|
938
|
-
] })
|
|
939
|
-
] }) });
|
|
1917
|
+
] }) })
|
|
1918
|
+
] })
|
|
1919
|
+
] })
|
|
1920
|
+
]
|
|
1921
|
+
}
|
|
1922
|
+
);
|
|
940
1923
|
};
|
|
941
1924
|
|
|
942
1925
|
// src/post-message-types.ts
|
|
@@ -944,7 +1927,7 @@ var isPlayruoEmbedMessage = (data) => {
|
|
|
944
1927
|
if (!data || typeof data !== "object") return false;
|
|
945
1928
|
const msg = data;
|
|
946
1929
|
if (typeof msg.type !== "string") return false;
|
|
947
|
-
return msg.type === "playruo_ready" || msg.type === "playruo_state_update" || msg.type === "playruo_purchase_request" || msg.type === "playruo_demo_completed" || msg.type === "playruo_error" || msg.type === "playruo_session_over" || msg.type === "playruo_stream_start" || msg.type === "playruo_stream_stop";
|
|
1930
|
+
return msg.type === "playruo_ready" || msg.type === "playruo_state_update" || msg.type === "playruo_purchase_request" || msg.type === "playruo_demo_completed" || msg.type === "playruo_error" || msg.type === "playruo_session_over" || msg.type === "playruo_stream_start" || msg.type === "playruo_stream_stop" || msg.type === "REQUEST_EXIT_FULLSCREEN" || msg.type === "playruo_event";
|
|
948
1931
|
};
|
|
949
1932
|
var isPlayruoInternalMessage = (data) => {
|
|
950
1933
|
if (!data || typeof data !== "object") return false;
|