@lumiastream/ui 0.2.7 → 0.2.8-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +61 -2
- package/dist/index.js +1238 -375
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3111,6 +3111,36 @@ function listenerPlaceholderContext(listener) {
|
|
|
3111
3111
|
}
|
|
3112
3112
|
return {};
|
|
3113
3113
|
}
|
|
3114
|
+
var SE_WIDGET_TYPE_LABELS = {
|
|
3115
|
+
"subscriber-latest": "Latest subscriber",
|
|
3116
|
+
"subscriber-new-latest": "Latest new subscriber",
|
|
3117
|
+
"subscriber-resub-latest": "Latest resubscriber",
|
|
3118
|
+
"subscriber-gifted-latest": "Latest gifted sub",
|
|
3119
|
+
"subscriber-alltime-gifter": "Top all-time gifter",
|
|
3120
|
+
"follower-latest": "Latest follower",
|
|
3121
|
+
"cheer-latest": "Latest cheer",
|
|
3122
|
+
"cheer-total": "Total cheers",
|
|
3123
|
+
"tip-latest": "Latest tip",
|
|
3124
|
+
"tip-total": "Total tips",
|
|
3125
|
+
"se-widget-bit-boss": "Bit Boss",
|
|
3126
|
+
"se-widget-hype-cup": "Hype Cup",
|
|
3127
|
+
"se-widget-custom-event-list": "Custom widget",
|
|
3128
|
+
"se-widget-credit-roll": "Credits",
|
|
3129
|
+
"se-widget-media-share": "Media share"
|
|
3130
|
+
};
|
|
3131
|
+
function defaultLabelForSEWidget(widget) {
|
|
3132
|
+
const trimmed = typeof widget.name === "string" ? widget.name.trim() : "";
|
|
3133
|
+
if (trimmed) return trimmed;
|
|
3134
|
+
const override = SE_WIDGET_TYPE_LABELS[widget.type];
|
|
3135
|
+
if (override) return override;
|
|
3136
|
+
const stripped = widget.type.replace(/^se-widget-/, "");
|
|
3137
|
+
const words = stripped.split("-").filter(Boolean);
|
|
3138
|
+
if (words.length === 0) return widget.type;
|
|
3139
|
+
const first = words[0];
|
|
3140
|
+
const head = first.charAt(0).toUpperCase() + first.slice(1);
|
|
3141
|
+
const tail = words.slice(1).join(" ");
|
|
3142
|
+
return tail ? `${head} ${tail}` : head;
|
|
3143
|
+
}
|
|
3114
3144
|
function translateSeText(input, listener) {
|
|
3115
3145
|
if (!input) return "";
|
|
3116
3146
|
const ctx = listener ? listenerPlaceholderContext(listener) : {};
|
|
@@ -3288,7 +3318,7 @@ function buildUnit(widget, lumiaType, moduleExtras) {
|
|
|
3288
3318
|
version: 1,
|
|
3289
3319
|
settings: {
|
|
3290
3320
|
type: lumiaType,
|
|
3291
|
-
title: widget
|
|
3321
|
+
title: defaultLabelForSEWidget(widget),
|
|
3292
3322
|
locked: widget.locked ?? false
|
|
3293
3323
|
},
|
|
3294
3324
|
lights: [],
|
|
@@ -4480,6 +4510,116 @@ function hasMarketplaceCandidates(seWidgetType) {
|
|
|
4480
4510
|
return getMarketplaceCandidates(seWidgetType).length > 0;
|
|
4481
4511
|
}
|
|
4482
4512
|
|
|
4513
|
+
// src/se-import/api/seClient.ts
|
|
4514
|
+
var SEAuthError = class extends Error {
|
|
4515
|
+
constructor(code, message) {
|
|
4516
|
+
super(message);
|
|
4517
|
+
this.code = code;
|
|
4518
|
+
this.name = "SEAuthError";
|
|
4519
|
+
}
|
|
4520
|
+
};
|
|
4521
|
+
function decodeBase64Url(s) {
|
|
4522
|
+
const b64 = s.replace(/-/g, "+").replace(/_/g, "/");
|
|
4523
|
+
const padding = "===".slice((b64.length + 3) % 4);
|
|
4524
|
+
const padded = b64 + (padding.length < 3 ? padding : "");
|
|
4525
|
+
if (typeof atob === "function") return atob(padded);
|
|
4526
|
+
return Buffer.from(padded, "base64").toString("binary");
|
|
4527
|
+
}
|
|
4528
|
+
function decodeJwtPayload(jwt) {
|
|
4529
|
+
if (typeof jwt !== "string" || !jwt.trim()) {
|
|
4530
|
+
throw new SEAuthError("invalid-jwt", "No token provided.");
|
|
4531
|
+
}
|
|
4532
|
+
const parts = jwt.trim().split(".");
|
|
4533
|
+
if (parts.length !== 3) {
|
|
4534
|
+
throw new SEAuthError("invalid-jwt", "Token is not a valid JWT (expected 3 dot-separated parts).");
|
|
4535
|
+
}
|
|
4536
|
+
let raw;
|
|
4537
|
+
try {
|
|
4538
|
+
raw = decodeBase64Url(parts[1] ?? "");
|
|
4539
|
+
} catch {
|
|
4540
|
+
throw new SEAuthError("invalid-jwt", "Token payload is not valid base64.");
|
|
4541
|
+
}
|
|
4542
|
+
let parsed;
|
|
4543
|
+
try {
|
|
4544
|
+
parsed = JSON.parse(raw);
|
|
4545
|
+
} catch {
|
|
4546
|
+
throw new SEAuthError("invalid-jwt", "Token payload is not valid JSON.");
|
|
4547
|
+
}
|
|
4548
|
+
const claims = parsed;
|
|
4549
|
+
if (typeof claims.channel !== "string" || typeof claims.authToken !== "string") {
|
|
4550
|
+
throw new SEAuthError("invalid-jwt", "Token payload is missing the 'channel' or 'authToken' claim \u2014 not a StreamElements account token.");
|
|
4551
|
+
}
|
|
4552
|
+
if (typeof claims.exp === "number" && claims.exp * 1e3 < Date.now()) {
|
|
4553
|
+
throw new SEAuthError("expired", "This StreamElements token has expired. Generate a new one on the SE Account page.");
|
|
4554
|
+
}
|
|
4555
|
+
return claims;
|
|
4556
|
+
}
|
|
4557
|
+
var SEClient = class _SEClient {
|
|
4558
|
+
constructor(claims) {
|
|
4559
|
+
this.claims = claims;
|
|
4560
|
+
}
|
|
4561
|
+
static fromJwt(jwt) {
|
|
4562
|
+
return new _SEClient(decodeJwtPayload(jwt));
|
|
4563
|
+
}
|
|
4564
|
+
get channelId() {
|
|
4565
|
+
return this.claims.channel;
|
|
4566
|
+
}
|
|
4567
|
+
get provider() {
|
|
4568
|
+
return this.claims.provider;
|
|
4569
|
+
}
|
|
4570
|
+
get providerId() {
|
|
4571
|
+
return this.claims.provider_id;
|
|
4572
|
+
}
|
|
4573
|
+
get userId() {
|
|
4574
|
+
return this.claims.user;
|
|
4575
|
+
}
|
|
4576
|
+
get jti() {
|
|
4577
|
+
return this.claims.jti;
|
|
4578
|
+
}
|
|
4579
|
+
get expiresAt() {
|
|
4580
|
+
return new Date(this.claims.exp * 1e3);
|
|
4581
|
+
}
|
|
4582
|
+
// Convenience for provenance stamping on imported entities. Single source
|
|
4583
|
+
// of truth so every mapper writes the same shape.
|
|
4584
|
+
provenance() {
|
|
4585
|
+
return {
|
|
4586
|
+
jti: this.claims.jti,
|
|
4587
|
+
channelId: this.claims.channel,
|
|
4588
|
+
provider: this.claims.provider,
|
|
4589
|
+
importedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4590
|
+
};
|
|
4591
|
+
}
|
|
4592
|
+
async get(path) {
|
|
4593
|
+
const res = await fetch(`https://api.streamelements.com${path}`, {
|
|
4594
|
+
method: "GET",
|
|
4595
|
+
headers: {
|
|
4596
|
+
Authorization: `apikey ${this.claims.authToken}`,
|
|
4597
|
+
Accept: "application/json"
|
|
4598
|
+
}
|
|
4599
|
+
});
|
|
4600
|
+
if (res.status === 401) {
|
|
4601
|
+
throw new SEAuthError("unauthorized", "StreamElements rejected the token. Generate a new one and try again.");
|
|
4602
|
+
}
|
|
4603
|
+
if (res.status === 403) {
|
|
4604
|
+
throw new SEAuthError("forbidden", "Your StreamElements token does not have permission for this resource.");
|
|
4605
|
+
}
|
|
4606
|
+
if (!res.ok) {
|
|
4607
|
+
let detail = "";
|
|
4608
|
+
try {
|
|
4609
|
+
const body = await res.json();
|
|
4610
|
+
if (body?.message) detail = ` \u2014 ${body.message}`;
|
|
4611
|
+
} catch {
|
|
4612
|
+
}
|
|
4613
|
+
throw new Error(`StreamElements API returned HTTP ${res.status}${detail}`);
|
|
4614
|
+
}
|
|
4615
|
+
return await res.json();
|
|
4616
|
+
}
|
|
4617
|
+
};
|
|
4618
|
+
async function fetchUsableChannels(client) {
|
|
4619
|
+
const me = await client.get("/kappa/v2/users/current");
|
|
4620
|
+
return (me.channels ?? []).filter((c) => c.authorized !== false && c.inactive !== true);
|
|
4621
|
+
}
|
|
4622
|
+
|
|
4483
4623
|
// src/se-import/ui/SEImportWizard.tsx
|
|
4484
4624
|
import { useCallback as useCallback3, useEffect as useEffect6, useMemo as useMemo5, useRef as useRef4, useState as useState6 } from "react";
|
|
4485
4625
|
|
|
@@ -4528,7 +4668,7 @@ function MarketplacePicker({ seWidgetType, fetchMarketplaceOverlay, CustomEmbed,
|
|
|
4528
4668
|
/* @__PURE__ */ jsx12("code", { children: seWidgetType }),
|
|
4529
4669
|
" yet. Use AI generation or skip the widget for now."
|
|
4530
4670
|
] }),
|
|
4531
|
-
/* @__PURE__ */ jsx12("div", { className: "ui-flex-row", style: { marginTop: 8 }, children: /* @__PURE__ */ jsx12(
|
|
4671
|
+
/* @__PURE__ */ jsx12("div", { className: "ui-flex-row", style: { marginTop: 8 }, children: /* @__PURE__ */ jsx12(LSButton, { type: "button", color: "secondary", onClick: onCancel, label: "Close" }) })
|
|
4532
4672
|
] });
|
|
4533
4673
|
}
|
|
4534
4674
|
return /* @__PURE__ */ jsxs6("div", { className: "ui-flex-column ui-gap-2", style: { padding: 16, minHeight: 420 }, children: [
|
|
@@ -4539,15 +4679,15 @@ function MarketplacePicker({ seWidgetType, fetchMarketplaceOverlay, CustomEmbed,
|
|
|
4539
4679
|
" with a layer from a curated Lumia Marketplace overlay."
|
|
4540
4680
|
] }),
|
|
4541
4681
|
/* @__PURE__ */ jsx12("div", { className: "ui-flex-row ui-gap-2", style: { flexWrap: "wrap", marginTop: 4 }, children: candidates.map((c) => /* @__PURE__ */ jsx12(
|
|
4542
|
-
|
|
4682
|
+
LSButton,
|
|
4543
4683
|
{
|
|
4544
4684
|
type: "button",
|
|
4545
|
-
|
|
4685
|
+
color: c.id === activeId ? "primary" : "secondary",
|
|
4546
4686
|
onClick: () => {
|
|
4547
4687
|
setActiveId(c.id);
|
|
4548
4688
|
setActiveLayerId(null);
|
|
4549
4689
|
},
|
|
4550
|
-
|
|
4690
|
+
label: c.loading ? `Loading #${c.id}\u2026` : c.error ? `#${c.id} (error)` : c.overlay?.name ?? `Overlay #${c.id}`
|
|
4551
4691
|
},
|
|
4552
4692
|
c.id
|
|
4553
4693
|
)) }),
|
|
@@ -4562,13 +4702,13 @@ function MarketplacePicker({ seWidgetType, fetchMarketplaceOverlay, CustomEmbed,
|
|
|
4562
4702
|
/* @__PURE__ */ jsxs6("div", { style: { flex: "0 0 200px", display: "flex", flexDirection: "column", gap: 4, maxHeight: 320, overflowY: "auto" }, children: [
|
|
4563
4703
|
/* @__PURE__ */ jsx12("div", { style: { fontSize: 12, fontWeight: 600, opacity: 0.8 }, children: "Layers" }),
|
|
4564
4704
|
activeLayers.map((l) => /* @__PURE__ */ jsx12(
|
|
4565
|
-
|
|
4705
|
+
LSButton,
|
|
4566
4706
|
{
|
|
4567
4707
|
type: "button",
|
|
4568
|
-
|
|
4708
|
+
color: l.id === activeLayerId ? "primary" : "secondary",
|
|
4569
4709
|
style: { justifyContent: "flex-start", textAlign: "left" },
|
|
4570
4710
|
onClick: () => setActiveLayerId(l.id),
|
|
4571
|
-
|
|
4711
|
+
label: /* @__PURE__ */ jsxs6("div", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
|
|
4572
4712
|
/* @__PURE__ */ jsx12("div", { style: { fontSize: 12, fontWeight: 600 }, children: l.label }),
|
|
4573
4713
|
/* @__PURE__ */ jsx12("div", { style: { fontSize: 10, opacity: 0.7 }, children: l.type })
|
|
4574
4714
|
] })
|
|
@@ -4580,15 +4720,15 @@ function MarketplacePicker({ seWidgetType, fetchMarketplaceOverlay, CustomEmbed,
|
|
|
4580
4720
|
/* @__PURE__ */ jsx12("div", { style: { flex: 1, minHeight: 240, background: "rgba(0,0,0,0.3)", borderRadius: 6, overflow: "hidden" }, children: /* @__PURE__ */ jsx12(ActiveLayerPreview, { overlay: activeCandidate.overlay, layerId: activeLayerId, CustomEmbed }) })
|
|
4581
4721
|
] }),
|
|
4582
4722
|
/* @__PURE__ */ jsxs6("div", { className: "ui-flex-row ui-gap-2", style: { marginTop: 12, justifyContent: "flex-end" }, children: [
|
|
4583
|
-
/* @__PURE__ */ jsx12(
|
|
4723
|
+
/* @__PURE__ */ jsx12(LSButton, { type: "button", color: "secondary", variant: "outlined", onClick: onCancel, label: "Cancel" }),
|
|
4584
4724
|
/* @__PURE__ */ jsx12(
|
|
4585
|
-
|
|
4725
|
+
LSButton,
|
|
4586
4726
|
{
|
|
4587
4727
|
type: "button",
|
|
4588
|
-
|
|
4728
|
+
color: "primary",
|
|
4589
4729
|
onClick: handleConfirm,
|
|
4590
4730
|
disabled: !activeCandidate?.overlay || !activeLayerId,
|
|
4591
|
-
|
|
4731
|
+
label: "Use this layer"
|
|
4592
4732
|
}
|
|
4593
4733
|
)
|
|
4594
4734
|
] })
|
|
@@ -4622,51 +4762,140 @@ function ActiveLayerPreview({ overlay, layerId, CustomEmbed }) {
|
|
|
4622
4762
|
] });
|
|
4623
4763
|
}
|
|
4624
4764
|
|
|
4765
|
+
// src/se-import/ui/SEImportWizard.css
|
|
4766
|
+
styleInject('.se-import,\n.se-import * {\n box-sizing: border-box;\n}\n.se-import {\n --se-bg: #17162a;\n --se-surface: #27264a;\n --se-panel: #171b38;\n --se-panel-2: #202449;\n --se-border: rgba(116, 124, 211, 0.24);\n --se-border-strong: rgba(126, 128, 255, 0.58);\n --se-text: #f5f4ff;\n --se-muted: #bab8d2;\n --se-primary: #ff4076;\n --se-purple: #393853;\n --se-green: #06c96f;\n --se-warn: #f7a42b;\n width: 100%;\n min-width: min(680px, 100%);\n color: var(--se-text);\n font-family: inherit;\n}\n.se-import__shell {\n border-radius: 0;\n padding: 28px 48px 24px;\n}\n.se-import__header {\n display: grid;\n justify-items: center;\n gap: 42px;\n}\n.se-import__title {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n font-size: 20px;\n font-weight: 500;\n}\n.se-import-stepper {\n display: grid;\n width: min(760px, 100%);\n grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));\n}\n.se-import-step {\n position: relative;\n display: grid;\n justify-items: center;\n gap: 12px;\n min-width: 0;\n color: rgba(255, 255, 255, 0.72);\n}\n.se-import-step__label {\n color: var(--se-text);\n font-size: 18px;\n line-height: 1.1;\n}\n.se-import-step__line {\n position: absolute;\n top: 42px;\n left: 50%;\n width: 100%;\n height: 2px;\n background: rgba(255, 255, 255, 0.16);\n}\n.se-import-step:last-child .se-import-step__line {\n display: none;\n}\n.se-import-step__dot {\n z-index: 1;\n display: grid;\n width: 22px;\n height: 22px;\n place-items: center;\n border-radius: 50%;\n background: #47485e;\n color: #fff;\n font-size: 13px;\n font-weight: 700;\n line-height: 1;\n}\n.se-import-step--active .se-import-step__dot {\n background: var(--se-primary);\n}\n.se-import-step--done .se-import-step__dot {\n background: var(--se-green);\n}\n.se-import-step--done .se-import-step__line {\n background: var(--se-green);\n}\n.se-import-step--done + .se-import-step--active .se-import-step__line {\n background:\n linear-gradient(\n 90deg,\n var(--se-green),\n var(--se-primary));\n}\n.se-import__content {\n display: grid;\n min-height: 470px;\n place-items: center;\n padding: 64px 0 28px;\n}\n.se-import-panel {\n width: min(100%, 1080px);\n padding: 28px;\n}\n.se-import-panel--narrow {\n width: min(100%, 1140px);\n}\n.se-import-panel--medium {\n width: min(100%, 880px);\n}\n.se-import-panel--wide {\n width: min(100%, 1000px);\n}\n.se-import-panel--confirm {\n width: min(100%, 800px);\n}\n.se-import-panel h2,\n.se-import-panel h3,\n.se-import-panel p {\n margin: 0;\n}\n.se-import-panel h2 {\n font-size: 26px;\n font-weight: 700;\n line-height: 1.15;\n}\n.se-import-panel > p {\n margin-top: 14px;\n color: var(--se-muted);\n font-size: 16px;\n line-height: 1.45;\n}\n.se-import-field {\n margin-top: 34px;\n}\n.se-import-field .mui-ls-input {\n --ls-control-height: 66px;\n}\n.se-import-field .MuiInputLabel-root {\n color: var(--se-text);\n font-weight: 700;\n}\n.se-import-field .MuiInputLabel-root.Mui-focused {\n color: #dfe1ff;\n}\n.se-import-field .MuiInputBase-root {\n background: rgba(28, 32, 66, 0.85);\n box-shadow: inset 0 0 0 3px rgba(255, 255, 255, 0.04);\n font-size: 18px;\n}\n.se-import-field .MuiOutlinedInput-notchedOutline {\n border-color: var(--se-border-strong) !important;\n}\n.se-import-help {\n display: flex;\n gap: 18px;\n margin-top: 30px;\n border: 1px solid var(--se-purple);\n border-radius: 12px;\n padding: 24px;\n color: var(--white2);\n}\n.se-import-help__icon {\n display: grid;\n width: 30px;\n height: 30px;\n flex: 0 0 auto;\n place-items: center;\n border: 1px solid var(--se-purple);\n border-radius: 50%;\n color: var(--white2);\n font-weight: 800;\n}\n.se-import-help__title {\n color: var(--se-text);\n font-size: 18px;\n font-weight: 700;\n}\n.se-import-help ol {\n margin: 16px 0 0;\n padding-left: 18px;\n font-size: 15px;\n line-height: 1.7;\n}\n.se-import-help a {\n color: var(--primary);\n font-weight: 700;\n}\n.se-import-help--info {\n align-items: center;\n}\n.se-import-section-title {\n display: flex;\n gap: 1rem;\n margin-bottom: 1.5rem;\n}\n.se-import-section-title__num {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 46px;\n height: 46px;\n border: 1px solid var(--se-purple);\n border-radius: 50%;\n font-size: 1.5rem;\n font-weight: 800;\n}\n.se-import-section-title__content {\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n.se-import-section-title h3 {\n font-size: 18px;\n font-weight: 800;\n}\n.se-import-section-title p {\n margin-top: 4px;\n color: var(--se-muted);\n font-size: 14px;\n}\n.se-import-grid {\n display: grid;\n gap: 8px;\n margin-top: 10px;\n}\n.se-import-grid--four {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n}\n.se-import-grid--two {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n.se-import-stat {\n min-height: 116px;\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 8px;\n background:\n linear-gradient(\n 135deg,\n rgba(42, 47, 92, 0.9),\n rgba(33, 38, 78, 0.9));\n padding: 24px 22px;\n}\n.se-import-stat--success {\n background:\n linear-gradient(\n 135deg,\n rgba(12, 91, 86, 0.72),\n rgba(32, 65, 76, 0.8));\n border-color: rgba(19, 201, 126, 0.25);\n}\n.se-import-stat--info {\n border-color: rgba(116, 104, 255, 0.8);\n box-shadow: inset 3px 0 0 #6e76ff;\n}\n.se-import-stat--warn,\n.se-import-stat--muted {\n box-shadow: inset 3px 0 0 var(--se-warn);\n}\n.se-import-stat__label {\n color: var(--se-muted);\n font-size: 12px;\n font-weight: 800;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n.se-import-stat__value {\n margin-top: 12px;\n color: #fff;\n font-size: 30px;\n font-weight: 800;\n line-height: 1;\n}\n.se-import-stat__sub {\n margin-top: 8px;\n color: var(--se-muted);\n font-size: 13px;\n}\n.se-import-option {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto auto;\n align-items: center;\n gap: 18px;\n border: 1px solid var(--se-purple);\n border-radius: 12px;\n background:\n linear-gradient(\n 135deg,\n rgba(35, 39, 81, 0.95),\n rgba(31, 35, 73, 0.95));\n box-shadow: inset 3px 0 0 var(--se-primary);\n cursor: pointer;\n padding: 22px;\n margin-bottom: 1rem;\n}\n.se-import-option--disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n.se-import-option__icon {\n display: grid;\n width: 26px;\n height: 26px;\n place-items: center;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.22);\n color: #d8dbff;\n font-weight: 800;\n}\n.se-import-option__body {\n display: grid;\n gap: 8px;\n min-width: 0;\n}\n.se-import-option__title {\n font-size: 17px;\n font-weight: 800;\n}\n.se-import-option__copy {\n color: var(--se-muted);\n font-size: 14px;\n line-height: 1.45;\n}\n.se-import-option__count {\n color: #fff;\n font-size: 16px;\n}\n.se-import-option input {\n position: absolute;\n opacity: 0;\n pointer-events: none;\n}\n.se-import-toggle {\n position: relative;\n width: 48px;\n height: 28px;\n border-radius: 999px;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);\n}\n.se-import-toggle::after {\n position: absolute;\n top: 4px;\n left: 4px;\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: #fff;\n content: "";\n transition: transform 160ms ease;\n}\n.se-import-option input:checked + .se-import-toggle {\n background: var(--primary);\n}\n.se-import-option input:checked + .se-import-toggle::after {\n transform: translateX(20px);\n}\n.se-import-advanced {\n margin-top: 26px;\n border-radius: 10px;\n background: rgba(32, 36, 73, 0.7);\n padding: 24px;\n}\n.se-import-advanced summary {\n cursor: pointer;\n font-size: 18px;\n font-weight: 700;\n}\n.se-import-advanced p {\n margin-top: 10px;\n color: var(--se-muted);\n}\n.se-import-transfer {\n position: relative;\n display: grid;\n width: min(720px, 100%);\n min-height: 190px;\n grid-template-columns: 180px minmax(260px, 1fr) 180px;\n align-items: center;\n gap: 28px;\n margin: 0 auto 60px;\n}\n.se-import-transfer__source {\n position: relative;\n display: grid;\n width: 160px;\n height: 160px;\n place-items: center;\n animation: se-import-source-bounce 1.8s ease-in-out infinite;\n}\n.se-import-transfer__source::before {\n top: -13px;\n left: -13px;\n box-shadow: 155px 0 0 var(--se-primary);\n}\n.se-import-transfer__source::after {\n bottom: -13px;\n left: -13px;\n box-shadow: 155px 0 0 var(--se-primary);\n}\n.se-import-transfer__source img {\n width: 192px;\n height: 192px;\n object-fit: contain;\n}\n.se-import-transfer__source--lumia {\n animation-delay: 0.22s;\n}\n.se-import-transfer__files {\n position: relative;\n height: 130px;\n}\n.se-import-transfer__file {\n position: absolute;\n top: 50%;\n left: -18px;\n width: 56px;\n height: 66px;\n object-fit: contain;\n transform: translateY(-50%);\n filter: drop-shadow(0 10px 12px rgba(8, 9, 25, 0.25));\n animation: se-import-file-fly 2.4s cubic-bezier(0.35, 0, 0.25, 1) infinite;\n}\n.se-import-transfer__file--one {\n animation-delay: 0s;\n}\n.se-import-transfer__file--two {\n animation-delay: 0.38s;\n}\n.se-import-transfer__file--three {\n animation-delay: 0.76s;\n}\n.se-import-transfer__file--four {\n animation-delay: 1.14s;\n}\n@keyframes se-import-source-bounce {\n 0%, 100% {\n transform: translateY(0) scale(1);\n }\n 50% {\n transform: translateY(-8px) scale(1.025);\n }\n}\n@keyframes se-import-file-fly {\n 0% {\n opacity: 0;\n transform: translate(-10px, -50%) scale(0.82) rotate(-8deg);\n }\n 12% {\n opacity: 1;\n }\n 45% {\n transform: translate(145px, calc(-50% - 18px)) scale(1.08) rotate(5deg);\n }\n 82% {\n opacity: 1;\n }\n 100% {\n opacity: 0;\n transform: translate(330px, -50%) scale(0.9) rotate(10deg);\n }\n}\n.se-import-mirror-head {\n display: flex;\n align-items: end;\n justify-content: space-between;\n gap: 20px;\n}\n.se-import-mirror-head p {\n margin-top: 14px;\n color: var(--se-muted);\n font-size: 16px;\n}\n.se-import-mirror-head span {\n flex: 0 0 auto;\n color: var(--se-muted);\n font-weight: 700;\n}\n.se-import-progress {\n width: 100%;\n height: 14px;\n margin-top: 28px;\n overflow: hidden;\n border: 0;\n border-radius: 999px;\n background: rgba(255, 64, 118, 0.1);\n}\n.se-import-progress::-webkit-progress-bar {\n background: rgba(255, 64, 118, 0.1);\n}\n.se-import-progress::-webkit-progress-value {\n border-radius: 999px;\n background:\n linear-gradient(\n 90deg,\n #ff4076,\n #e7295f);\n}\n.se-import-progress::-moz-progress-bar {\n border-radius: 999px;\n background:\n linear-gradient(\n 90deg,\n #ff4076,\n #e7295f);\n}\n.se-import-asset-list {\n max-height: 360px;\n margin-top: 22px;\n overflow-y: auto;\n border-top: 1px solid rgba(255, 255, 255, 0.08);\n}\n.se-import-asset-row {\n display: grid;\n grid-template-columns: 32px minmax(0, 1fr) auto auto;\n align-items: center;\n gap: 14px;\n min-height: 42px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n color: var(--se-muted);\n font-size: 13px;\n}\n.se-import-asset-row__icon {\n width: 24px;\n height: 28px;\n justify-self: end;\n object-fit: contain;\n}\n.se-import-asset-row__url {\n overflow: hidden;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.se-import-asset-row__state {\n color: #9b8cff;\n font-weight: 800;\n}\n.se-import-asset-row--done .se-import-asset-row__state,\n.se-import-asset-row--reused .se-import-asset-row__state {\n color: var(--se-green);\n}\n.se-import-asset-row--failed .se-import-asset-row__state,\n.se-import-asset-row__error {\n color: #ff8080;\n}\n.se-import-link-button {\n border: 0;\n background: transparent;\n color: #ff9ab6;\n cursor: pointer;\n font: inherit;\n font-weight: 800;\n}\n.se-import-overview {\n margin-top: 28px;\n border: 1px solid var(--se-border);\n border-radius: 12px;\n background: rgba(26, 30, 61, 0.62);\n padding: 28px;\n}\n.se-import-overview h3 {\n margin-bottom: 18px;\n font-size: 18px;\n font-weight: 800;\n}\n.se-import-row {\n display: grid;\n grid-template-columns: 190px minmax(0, 1fr) auto;\n gap: 18px;\n align-items: center;\n min-height: 48px;\n border-top: 1px solid rgba(255, 255, 255, 0.08);\n color: var(--se-muted);\n}\n.se-import-row strong {\n min-width: 0;\n overflow: hidden;\n color: var(--se-text);\n font-weight: 600;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.se-import-row em {\n color: var(--se-muted);\n font-style: normal;\n}\n.se-import-review-card {\n display: flex;\n justify-content: space-between;\n gap: 18px;\n border: 1px solid var(--se-border);\n border-radius: 10px;\n background: rgba(30, 34, 71, 0.8);\n padding: 20px;\n}\n.se-import-review-card__type {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n font-weight: 800;\n}\n.se-import-review-card p {\n margin-top: 8px;\n color: var(--se-muted);\n line-height: 1.45;\n}\n.se-import-review-card__status {\n flex: 0 0 auto;\n color: #facc15;\n font-size: 11px;\n font-weight: 800;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n.se-import-review-bulk,\n.se-import-actions--inline {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: 10px;\n margin-top: 16px;\n}\n.se-import-muted {\n margin-top: 16px;\n color: var(--se-muted);\n font-size: 13px;\n}\n.se-import-generated {\n display: grid;\n gap: 12px;\n margin-top: 18px;\n}\n.se-import-generated__title {\n font-weight: 800;\n}\n.se-import-preview {\n width: 100%;\n height: 260px;\n border: 1px solid var(--se-border);\n border-radius: 8px;\n background: repeating-conic-gradient(#1a1c20 0% 25%, #1d1f24 0% 50%) 50% / 20px 20px;\n}\n.se-import-code {\n margin-top: 16px;\n}\n.se-import-code summary {\n cursor: pointer;\n color: var(--se-muted);\n font-size: 13px;\n}\n.se-import-code pre {\n max-height: 220px;\n margin: 10px 0 0;\n overflow: auto;\n border-radius: 8px;\n background: rgba(0, 0, 0, 0.28);\n padding: 12px;\n color: #d8dcff;\n font-size: 12px;\n}\n.se-import-error {\n margin-top: 18px;\n border: 1px solid rgba(239, 68, 68, 0.45);\n border-radius: 8px;\n background: rgba(220, 38, 38, 0.12);\n padding: 12px;\n color: #fca5a5;\n}\n.se-import-error__title {\n font-weight: 800;\n}\n.se-import-error__hint {\n margin-top: 6px;\n white-space: pre-wrap;\n}\n.se-import-actions {\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n margin-top: 8px;\n}\n@media (max-width: 900px) {\n .se-import__shell {\n min-height: 0;\n padding: 24px 18px;\n }\n .se-import__content {\n min-height: 0;\n padding-top: 32px;\n }\n .se-import-stepper {\n grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));\n }\n .se-import-step__label {\n font-size: 13px;\n }\n .se-import-grid--four,\n .se-import-grid--two,\n .se-import-transfer {\n grid-template-columns: 1fr;\n }\n .se-import-transfer {\n justify-items: center;\n }\n .se-import-transfer__files {\n width: min(360px, 100%);\n }\n .se-import-option,\n .se-import-row,\n .se-import-asset-row {\n grid-template-columns: 1fr;\n }\n .se-import-mirror-head,\n .se-import-review-card {\n align-items: flex-start;\n flex-direction: column;\n }\n}\n');
|
|
4767
|
+
|
|
4625
4768
|
// src/se-import/ui/SEImportWizard.tsx
|
|
4626
4769
|
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4770
|
+
var sourceSEIcon = new URL("../../assets/source_se.svg", import.meta.url).href;
|
|
4771
|
+
var sourceLumiaIcon = new URL(
|
|
4772
|
+
"../../assets/source_lumia.svg",
|
|
4773
|
+
import.meta.url
|
|
4774
|
+
).href;
|
|
4775
|
+
var audioFileIcon = new URL("../../assets/audio_file.svg", import.meta.url).href;
|
|
4776
|
+
var imageFileIcon = new URL("../../assets/img_file.svg", import.meta.url).href;
|
|
4777
|
+
var videoFileIcon = new URL("../../assets/video_file.svg", import.meta.url).href;
|
|
4778
|
+
var audioIcon = new URL("../../assets/sound.svg", import.meta.url).href;
|
|
4779
|
+
var imageIcon = new URL("../../assets/img.svg", import.meta.url).href;
|
|
4780
|
+
var videoIcon = new URL("../../assets/video.svg", import.meta.url).href;
|
|
4781
|
+
var CORE_STEPS = [
|
|
4782
|
+
{ key: "connect", label: "Connect" },
|
|
4783
|
+
{ key: "url", label: "Load" },
|
|
4784
|
+
{ key: "discovery", label: "Discovery" },
|
|
4785
|
+
{ key: "options", label: "Options" },
|
|
4786
|
+
{ key: "mirror", label: "Assets" },
|
|
4787
|
+
{ key: "confirm", label: "Confirm" }
|
|
4788
|
+
];
|
|
4789
|
+
function stepClass(done, active) {
|
|
4790
|
+
return [
|
|
4791
|
+
"se-import-step",
|
|
4792
|
+
done && "se-import-step--done",
|
|
4793
|
+
active && "se-import-step--active"
|
|
4794
|
+
].filter(Boolean).join(" ");
|
|
4633
4795
|
}
|
|
4634
|
-
function
|
|
4635
|
-
|
|
4636
|
-
return /* @__PURE__ */ jsx13("div", { style: { height: 6, borderRadius: 3, background: "var(--ui-bg-elevated, #2a2c31)", overflow: "hidden" }, children: /* @__PURE__ */ jsx13("div", { style: { height: "100%", width: `${pct}%`, background: "#6a6ffc", transition: "width 240ms" } }) });
|
|
4796
|
+
function panelClass(extra) {
|
|
4797
|
+
return ["se-import-panel", extra].filter(Boolean).join(" ");
|
|
4637
4798
|
}
|
|
4638
4799
|
function ErrorPanel({ message, hint }) {
|
|
4639
|
-
return /* @__PURE__ */ jsxs7("div", {
|
|
4640
|
-
/* @__PURE__ */ jsx13("div", {
|
|
4641
|
-
hint && /* @__PURE__ */ jsx13("div", {
|
|
4800
|
+
return /* @__PURE__ */ jsxs7("div", { className: "se-import-error", children: [
|
|
4801
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-error__title", children: message }),
|
|
4802
|
+
hint && /* @__PURE__ */ jsx13("div", { className: "se-import-error__hint", children: hint })
|
|
4642
4803
|
] });
|
|
4643
4804
|
}
|
|
4644
|
-
function
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4805
|
+
function Field({
|
|
4806
|
+
label,
|
|
4807
|
+
value,
|
|
4808
|
+
onChange,
|
|
4809
|
+
placeholder,
|
|
4810
|
+
disabled
|
|
4811
|
+
}) {
|
|
4812
|
+
return /* @__PURE__ */ jsx13("div", { className: "se-import-field", children: /* @__PURE__ */ jsx13(
|
|
4813
|
+
LSInput,
|
|
4814
|
+
{
|
|
4815
|
+
label,
|
|
4816
|
+
value,
|
|
4817
|
+
onChange: (_, next) => onChange(String(next ?? "")),
|
|
4818
|
+
placeholder,
|
|
4819
|
+
disabled
|
|
4820
|
+
}
|
|
4821
|
+
) });
|
|
4822
|
+
}
|
|
4823
|
+
function ProgressBar({ value, max }) {
|
|
4824
|
+
return /* @__PURE__ */ jsx13(
|
|
4825
|
+
"progress",
|
|
4826
|
+
{
|
|
4827
|
+
className: "se-import-progress",
|
|
4828
|
+
value: max > 0 ? value : 0,
|
|
4829
|
+
max: max || 1
|
|
4830
|
+
}
|
|
4831
|
+
);
|
|
4832
|
+
}
|
|
4833
|
+
function StatusCard({
|
|
4834
|
+
label,
|
|
4835
|
+
value,
|
|
4836
|
+
sub,
|
|
4837
|
+
tone = "neutral"
|
|
4838
|
+
}) {
|
|
4839
|
+
return /* @__PURE__ */ jsxs7("div", { className: `se-import-stat se-import-stat--${tone}`, children: [
|
|
4840
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-stat__label", children: label }),
|
|
4841
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-stat__value", children: value }),
|
|
4842
|
+
sub && /* @__PURE__ */ jsx13("div", { className: "se-import-stat__sub", children: sub })
|
|
4653
4843
|
] });
|
|
4654
4844
|
}
|
|
4655
4845
|
function CoverageCards({ coverage }) {
|
|
4656
4846
|
const byStatus = useMemo5(() => {
|
|
4657
4847
|
const acc = { direct: 0, partial: 0, template: 0, placeholder: 0 };
|
|
4658
|
-
for (const
|
|
4848
|
+
for (const item of coverage.mappings) acc[item.status] += item.count;
|
|
4659
4849
|
return acc;
|
|
4660
4850
|
}, [coverage]);
|
|
4661
|
-
const pct = (
|
|
4662
|
-
return /* @__PURE__ */ jsxs7("div", { className: "
|
|
4663
|
-
/* @__PURE__ */ jsx13(
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4851
|
+
const pct = (value) => coverage.totalWidgets > 0 ? Math.round(value / coverage.totalWidgets * 100) : 0;
|
|
4852
|
+
return /* @__PURE__ */ jsxs7("div", { className: "se-import-grid se-import-grid--four", children: [
|
|
4853
|
+
/* @__PURE__ */ jsx13(
|
|
4854
|
+
StatusCard,
|
|
4855
|
+
{
|
|
4856
|
+
label: "Direct",
|
|
4857
|
+
value: byStatus.direct,
|
|
4858
|
+
sub: `${pct(byStatus.direct)}%`,
|
|
4859
|
+
tone: "success"
|
|
4860
|
+
}
|
|
4861
|
+
),
|
|
4862
|
+
/* @__PURE__ */ jsx13(
|
|
4863
|
+
StatusCard,
|
|
4864
|
+
{
|
|
4865
|
+
label: "Partial",
|
|
4866
|
+
value: byStatus.partial,
|
|
4867
|
+
sub: `${pct(byStatus.partial)}%`,
|
|
4868
|
+
tone: "info"
|
|
4869
|
+
}
|
|
4870
|
+
),
|
|
4871
|
+
/* @__PURE__ */ jsx13(
|
|
4872
|
+
StatusCard,
|
|
4873
|
+
{
|
|
4874
|
+
label: "Template",
|
|
4875
|
+
value: byStatus.template,
|
|
4876
|
+
sub: `${pct(byStatus.template)}%`,
|
|
4877
|
+
tone: "warn"
|
|
4878
|
+
}
|
|
4879
|
+
),
|
|
4880
|
+
/* @__PURE__ */ jsx13(
|
|
4881
|
+
StatusCard,
|
|
4882
|
+
{
|
|
4883
|
+
label: "Placeholder",
|
|
4884
|
+
value: byStatus.placeholder,
|
|
4885
|
+
sub: `${pct(byStatus.placeholder)}%`,
|
|
4886
|
+
tone: "muted"
|
|
4887
|
+
}
|
|
4888
|
+
)
|
|
4667
4889
|
] });
|
|
4668
4890
|
}
|
|
4669
|
-
function CustomOverlayPreview({
|
|
4891
|
+
function CustomOverlayPreview({
|
|
4892
|
+
html,
|
|
4893
|
+
css,
|
|
4894
|
+
js,
|
|
4895
|
+
data,
|
|
4896
|
+
width,
|
|
4897
|
+
height
|
|
4898
|
+
}) {
|
|
4670
4899
|
const srcdoc = useMemo5(() => {
|
|
4671
4900
|
const safeData = JSON.stringify(data ?? {});
|
|
4672
4901
|
const safeJs = JSON.stringify(`(async () => { ${js || ""} })()`);
|
|
@@ -4682,219 +4911,636 @@ try { eval(${safeJs}); } catch(e) { document.body.insertAdjacentHTML('beforeend'
|
|
|
4682
4911
|
"iframe",
|
|
4683
4912
|
{
|
|
4684
4913
|
title: "ai-preview",
|
|
4914
|
+
className: "se-import-preview",
|
|
4685
4915
|
sandbox: "allow-scripts",
|
|
4686
4916
|
srcDoc: srcdoc,
|
|
4687
|
-
style: { width: "100%", height: 260, border: "1px solid var(--ui-border, #2a2c31)", borderRadius: 6, background: "repeating-conic-gradient(#1a1c20 0% 25%, #1d1f24 0% 50%) 50% / 20px 20px" },
|
|
4688
4917
|
"data-canvas-width": width,
|
|
4689
4918
|
"data-canvas-height": height
|
|
4690
4919
|
}
|
|
4691
4920
|
);
|
|
4692
4921
|
}
|
|
4693
|
-
function
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4922
|
+
function StepHeader({
|
|
4923
|
+
number,
|
|
4924
|
+
title,
|
|
4925
|
+
subtitle
|
|
4926
|
+
}) {
|
|
4927
|
+
return /* @__PURE__ */ jsxs7("div", { className: "se-import-section-title", children: [
|
|
4928
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-section-title__num", children: number }),
|
|
4929
|
+
/* @__PURE__ */ jsxs7("div", { className: "se-import-section-title__content", children: [
|
|
4930
|
+
/* @__PURE__ */ jsx13("h3", { children: title }),
|
|
4931
|
+
subtitle && /* @__PURE__ */ jsx13("p", { children: subtitle })
|
|
4932
|
+
] })
|
|
4933
|
+
] });
|
|
4934
|
+
}
|
|
4935
|
+
function StepConnect({
|
|
4936
|
+
jwt,
|
|
4937
|
+
setJwt,
|
|
4938
|
+
error,
|
|
4939
|
+
busy,
|
|
4940
|
+
channels,
|
|
4941
|
+
selectedChannelId,
|
|
4942
|
+
setSelectedChannelId,
|
|
4943
|
+
onUseUrl
|
|
4944
|
+
}) {
|
|
4945
|
+
return /* @__PURE__ */ jsxs7("div", { className: panelClass("se-import-panel--narrow"), children: [
|
|
4946
|
+
/* @__PURE__ */ jsx13(
|
|
4947
|
+
StepHeader,
|
|
4948
|
+
{
|
|
4949
|
+
number: 1,
|
|
4950
|
+
title: "Connect your StreamElements account",
|
|
4951
|
+
subtitle: "Paste your StreamElements JWT to import overlays, live counters, chat commands, loyalty points, watch time, and recent events. The token is read in your browser only \u2014 Lumia never sends it to our servers."
|
|
4952
|
+
}
|
|
4953
|
+
),
|
|
4954
|
+
/* @__PURE__ */ jsx13(
|
|
4955
|
+
Field,
|
|
4956
|
+
{
|
|
4957
|
+
label: "StreamElements JWT",
|
|
4958
|
+
value: jwt,
|
|
4959
|
+
onChange: setJwt,
|
|
4960
|
+
placeholder: "eyJhbGciOi...",
|
|
4961
|
+
disabled: busy
|
|
4962
|
+
}
|
|
4963
|
+
),
|
|
4964
|
+
channels && channels.length > 1 && /* @__PURE__ */ jsxs7("div", { className: "se-import-help se-import-help--info", children: [
|
|
4965
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-help__icon", children: "i" }),
|
|
4966
|
+
/* @__PURE__ */ jsxs7("div", { children: [
|
|
4967
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-help__title", children: "Pick a channel" }),
|
|
4968
|
+
/* @__PURE__ */ jsx13("p", { children: "This account has multiple StreamElements channels. Choose which one to import from." }),
|
|
4969
|
+
/* @__PURE__ */ jsx13("div", { style: { display: "grid", gap: 8, marginTop: 12 }, children: channels.map((c) => /* @__PURE__ */ jsxs7(
|
|
4970
|
+
"label",
|
|
4971
|
+
{
|
|
4972
|
+
style: {
|
|
4973
|
+
display: "flex",
|
|
4974
|
+
alignItems: "center",
|
|
4975
|
+
gap: 10,
|
|
4976
|
+
padding: "8px 12px",
|
|
4977
|
+
border: "1px solid var(--se-border)",
|
|
4978
|
+
borderRadius: 8,
|
|
4979
|
+
background: selectedChannelId === c._id ? "rgba(255, 64, 118, 0.12)" : "transparent",
|
|
4980
|
+
cursor: "pointer"
|
|
4981
|
+
},
|
|
4982
|
+
children: [
|
|
4983
|
+
/* @__PURE__ */ jsx13(
|
|
4984
|
+
"input",
|
|
4985
|
+
{
|
|
4986
|
+
type: "radio",
|
|
4987
|
+
name: "se-channel",
|
|
4988
|
+
checked: selectedChannelId === c._id,
|
|
4989
|
+
onChange: () => setSelectedChannelId(c._id)
|
|
4990
|
+
}
|
|
4991
|
+
),
|
|
4992
|
+
c.avatar && /* @__PURE__ */ jsx13("img", { src: c.avatar, alt: "", width: 24, height: 24, style: { borderRadius: "50%" } }),
|
|
4993
|
+
/* @__PURE__ */ jsxs7("div", { style: { display: "flex", flexDirection: "column" }, children: [
|
|
4994
|
+
/* @__PURE__ */ jsx13("span", { style: { fontWeight: 700 }, children: c.displayName ?? c.username }),
|
|
4995
|
+
/* @__PURE__ */ jsxs7("span", { style: { fontSize: 12, color: "var(--se-muted)" }, children: [
|
|
4996
|
+
c.provider,
|
|
4997
|
+
" \xB7 ",
|
|
4998
|
+
c.username
|
|
4999
|
+
] })
|
|
5000
|
+
] })
|
|
5001
|
+
]
|
|
5002
|
+
},
|
|
5003
|
+
c._id
|
|
5004
|
+
)) })
|
|
5005
|
+
] })
|
|
4699
5006
|
] }),
|
|
4700
|
-
/* @__PURE__ */
|
|
4701
|
-
|
|
4702
|
-
/* @__PURE__ */
|
|
4703
|
-
|
|
4704
|
-
/* @__PURE__ */ jsxs7("
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
5007
|
+
/* @__PURE__ */ jsxs7("div", { className: "se-import-help", children: [
|
|
5008
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-help__icon", children: "i" }),
|
|
5009
|
+
/* @__PURE__ */ jsxs7("div", { children: [
|
|
5010
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-help__title", children: "How to find your JWT" }),
|
|
5011
|
+
/* @__PURE__ */ jsxs7("ol", { children: [
|
|
5012
|
+
/* @__PURE__ */ jsxs7("li", { children: [
|
|
5013
|
+
"Open",
|
|
5014
|
+
" ",
|
|
5015
|
+
/* @__PURE__ */ jsx13(
|
|
5016
|
+
"a",
|
|
5017
|
+
{
|
|
5018
|
+
href: "https://streamelements.com/dashboard/account/channels",
|
|
5019
|
+
target: "_blank",
|
|
5020
|
+
rel: "noreferrer",
|
|
5021
|
+
children: "streamelements.com/dashboard/account/channels"
|
|
5022
|
+
}
|
|
5023
|
+
),
|
|
5024
|
+
"."
|
|
5025
|
+
] }),
|
|
5026
|
+
/* @__PURE__ */ jsxs7("li", { children: [
|
|
5027
|
+
"Click ",
|
|
5028
|
+
/* @__PURE__ */ jsx13("strong", { children: "Show JWT Token" }),
|
|
5029
|
+
" for the channel you want to import."
|
|
5030
|
+
] }),
|
|
5031
|
+
/* @__PURE__ */ jsx13("li", { children: "Copy the entire token and paste it above." }),
|
|
5032
|
+
/* @__PURE__ */ jsxs7("li", { children: [
|
|
5033
|
+
"When you're done, click ",
|
|
5034
|
+
/* @__PURE__ */ jsx13("strong", { children: "Revoke" }),
|
|
5035
|
+
" on the same page so the token stops working."
|
|
5036
|
+
] })
|
|
5037
|
+
] })
|
|
4716
5038
|
] })
|
|
4717
5039
|
] }),
|
|
5040
|
+
/* @__PURE__ */ jsxs7("div", { style: { marginTop: 16, fontSize: 13, color: "var(--se-muted)" }, children: [
|
|
5041
|
+
"Prefer to import just a single overlay without logging in?",
|
|
5042
|
+
" ",
|
|
5043
|
+
/* @__PURE__ */ jsx13(
|
|
5044
|
+
"a",
|
|
5045
|
+
{
|
|
5046
|
+
href: "#",
|
|
5047
|
+
onClick: (e) => {
|
|
5048
|
+
e.preventDefault();
|
|
5049
|
+
onUseUrl();
|
|
5050
|
+
},
|
|
5051
|
+
style: { color: "var(--se-primary)", fontWeight: 700 },
|
|
5052
|
+
children: "Use a public preview URL instead"
|
|
5053
|
+
}
|
|
5054
|
+
),
|
|
5055
|
+
"."
|
|
5056
|
+
] }),
|
|
4718
5057
|
error && /* @__PURE__ */ jsx13(ErrorPanel, { message: error.message, hint: error.hint })
|
|
4719
5058
|
] });
|
|
4720
5059
|
}
|
|
4721
|
-
function
|
|
5060
|
+
function StepURL({
|
|
5061
|
+
url,
|
|
5062
|
+
setUrl,
|
|
5063
|
+
error,
|
|
5064
|
+
busy
|
|
5065
|
+
}) {
|
|
5066
|
+
return /* @__PURE__ */ jsxs7("div", { className: panelClass("se-import-panel--narrow"), children: [
|
|
5067
|
+
/* @__PURE__ */ jsx13(
|
|
5068
|
+
StepHeader,
|
|
5069
|
+
{
|
|
5070
|
+
number: 1,
|
|
5071
|
+
title: "Paste your StreamElements overlay URL",
|
|
5072
|
+
subtitle: "This should be the public preview URL of your overlay. It includes the\n access token."
|
|
5073
|
+
}
|
|
5074
|
+
),
|
|
5075
|
+
/* @__PURE__ */ jsx13(
|
|
5076
|
+
LSInput,
|
|
5077
|
+
{
|
|
5078
|
+
label: "Overlay URL",
|
|
5079
|
+
value: url,
|
|
5080
|
+
onChange: setUrl,
|
|
5081
|
+
placeholder: "https://streamelements.com/overlay/<id>/<token>",
|
|
5082
|
+
disabled: busy
|
|
5083
|
+
}
|
|
5084
|
+
),
|
|
5085
|
+
/* @__PURE__ */ jsxs7("div", { className: "se-import-help", children: [
|
|
5086
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-help__icon", children: "i" }),
|
|
5087
|
+
/* @__PURE__ */ jsxs7("div", { children: [
|
|
5088
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-help__title", children: "How to find the overlay URL" }),
|
|
5089
|
+
/* @__PURE__ */ jsxs7("ol", { children: [
|
|
5090
|
+
/* @__PURE__ */ jsxs7("li", { children: [
|
|
5091
|
+
"Open",
|
|
5092
|
+
" ",
|
|
5093
|
+
/* @__PURE__ */ jsx13(
|
|
5094
|
+
"a",
|
|
5095
|
+
{
|
|
5096
|
+
href: "https://streamelements.com/dashboard/overlays",
|
|
5097
|
+
target: "_blank",
|
|
5098
|
+
rel: "noreferrer",
|
|
5099
|
+
children: "streamelements.com/dashboard/overlays"
|
|
5100
|
+
}
|
|
5101
|
+
),
|
|
5102
|
+
"."
|
|
5103
|
+
] }),
|
|
5104
|
+
/* @__PURE__ */ jsx13("li", { children: "Click the overlay you want to bring over." }),
|
|
5105
|
+
/* @__PURE__ */ jsx13("li", { children: "Click Copy URL in the top right of the editor." }),
|
|
5106
|
+
/* @__PURE__ */ jsx13("li", { children: "Paste it above." })
|
|
5107
|
+
] })
|
|
5108
|
+
] })
|
|
5109
|
+
] }),
|
|
5110
|
+
error && /* @__PURE__ */ jsx13(ErrorPanel, { message: error.message, hint: error.hint })
|
|
5111
|
+
] });
|
|
5112
|
+
}
|
|
5113
|
+
function StepDiscovery({
|
|
5114
|
+
result,
|
|
5115
|
+
assetCount
|
|
5116
|
+
}) {
|
|
4722
5117
|
const widgets = result.coverage.totalWidgets;
|
|
4723
5118
|
const reviewCount = result.reviewItems.length;
|
|
4724
|
-
const customCount = result.coverage.mappings.find(
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
/* @__PURE__ */ jsx13(
|
|
4732
|
-
/* @__PURE__ */ jsx13(
|
|
4733
|
-
/* @__PURE__ */ jsx13(
|
|
5119
|
+
const customCount = result.coverage.mappings.find(
|
|
5120
|
+
(item) => item.seType === "se-widget-custom-event-list"
|
|
5121
|
+
)?.count ?? 0;
|
|
5122
|
+
const alertCount = result.coverage.mappings.filter((item) => item.lumiaType === "alert").reduce((sum, item) => sum + item.count, 0);
|
|
5123
|
+
return /* @__PURE__ */ jsxs7("div", { className: panelClass("se-import-panel--wide"), children: [
|
|
5124
|
+
/* @__PURE__ */ jsx13(StepHeader, { number: 2, title: "Here's what we found in your overlay" }),
|
|
5125
|
+
/* @__PURE__ */ jsxs7("div", { className: "se-import-grid se-import-grid--four", children: [
|
|
5126
|
+
/* @__PURE__ */ jsx13(StatusCard, { label: "Total widgets", value: widgets }),
|
|
5127
|
+
/* @__PURE__ */ jsx13(StatusCard, { label: "Alerts", value: alertCount }),
|
|
5128
|
+
/* @__PURE__ */ jsx13(
|
|
5129
|
+
StatusCard,
|
|
5130
|
+
{
|
|
5131
|
+
label: "Custom widgets",
|
|
5132
|
+
value: customCount,
|
|
5133
|
+
sub: customCount > 0 ? "uses the SE compatibility shim" : void 0
|
|
5134
|
+
}
|
|
5135
|
+
),
|
|
5136
|
+
/* @__PURE__ */ jsx13(
|
|
5137
|
+
StatusCard,
|
|
5138
|
+
{
|
|
5139
|
+
label: "SE-hosted assets",
|
|
5140
|
+
value: assetCount,
|
|
5141
|
+
sub: assetCount > 0 ? "can be mirrored to Lumia storage" : "no migration needed"
|
|
5142
|
+
}
|
|
5143
|
+
)
|
|
4734
5144
|
] }),
|
|
4735
|
-
/* @__PURE__ */ jsx13(
|
|
5145
|
+
/* @__PURE__ */ jsx13(CoverageCards, { coverage: result.coverage }),
|
|
5146
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-grid se-import-grid--two", children: /* @__PURE__ */ jsx13(
|
|
5147
|
+
StatusCard,
|
|
5148
|
+
{
|
|
5149
|
+
label: "Need review",
|
|
5150
|
+
value: reviewCount,
|
|
5151
|
+
sub: reviewCount > 0 ? "manual choice needed" : "everything looks good",
|
|
5152
|
+
tone: reviewCount > 0 ? "warn" : "success"
|
|
5153
|
+
}
|
|
5154
|
+
) })
|
|
4736
5155
|
] });
|
|
4737
5156
|
}
|
|
4738
|
-
function
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
5157
|
+
function StepOptions({
|
|
5158
|
+
options,
|
|
5159
|
+
setOptions,
|
|
5160
|
+
assetCount
|
|
5161
|
+
}) {
|
|
5162
|
+
return /* @__PURE__ */ jsxs7("div", { className: panelClass("se-import-panel--medium"), children: [
|
|
5163
|
+
/* @__PURE__ */ jsx13(StepHeader, { number: 3, title: "Options", subtitle: "Choose how to handle your assets" }),
|
|
5164
|
+
/* @__PURE__ */ jsxs7(
|
|
5165
|
+
"label",
|
|
5166
|
+
{
|
|
5167
|
+
className: `se-import-option ${assetCount === 0 ? "se-import-option--disabled" : ""}`,
|
|
5168
|
+
children: [
|
|
5169
|
+
/* @__PURE__ */ jsx13("span", { className: "se-import-option__icon", children: "\u21A5" }),
|
|
5170
|
+
/* @__PURE__ */ jsxs7("span", { className: "se-import-option__body", children: [
|
|
5171
|
+
/* @__PURE__ */ jsx13("span", { className: "se-import-option__title", children: "Mirror StreamElements assets to Lumia storage" }),
|
|
5172
|
+
/* @__PURE__ */ jsx13("span", { className: "se-import-option__copy", children: "Downloads every cdn.streamelements.com URL referenced in the overlay, uploads it to your Lumia asset library, then rewrites the URLs." })
|
|
5173
|
+
] }),
|
|
5174
|
+
/* @__PURE__ */ jsxs7("span", { className: "se-import-option__count", children: [
|
|
5175
|
+
assetCount,
|
|
5176
|
+
" files"
|
|
5177
|
+
] }),
|
|
5178
|
+
/* @__PURE__ */ jsx13(
|
|
5179
|
+
"input",
|
|
5180
|
+
{
|
|
5181
|
+
type: "checkbox",
|
|
5182
|
+
checked: options.mirrorAssets,
|
|
5183
|
+
disabled: assetCount === 0,
|
|
5184
|
+
onChange: (e) => setOptions({ ...options, mirrorAssets: e.target.checked })
|
|
5185
|
+
}
|
|
5186
|
+
),
|
|
5187
|
+
/* @__PURE__ */ jsx13("span", { className: "se-import-toggle" })
|
|
5188
|
+
]
|
|
5189
|
+
}
|
|
5190
|
+
),
|
|
5191
|
+
/* @__PURE__ */ jsx13(
|
|
5192
|
+
LSInput,
|
|
5193
|
+
{
|
|
5194
|
+
label: "Overlay name",
|
|
5195
|
+
value: options.name,
|
|
5196
|
+
onChange: (e) => setOptions({ ...options, name: e.target.value })
|
|
5197
|
+
}
|
|
5198
|
+
)
|
|
4743
5199
|
] });
|
|
4744
5200
|
}
|
|
4745
|
-
function
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
5201
|
+
function mirrorLabel(state) {
|
|
5202
|
+
if (state === "fetching") return "Fetching";
|
|
5203
|
+
if (state === "done") return "Downloaded";
|
|
5204
|
+
if (state === "reused") return "Reused";
|
|
5205
|
+
if (state === "kept-on-cdn") return "Kept on CDN";
|
|
5206
|
+
if (state === "failed") return "Failed";
|
|
5207
|
+
return "Queued";
|
|
5208
|
+
}
|
|
5209
|
+
function fileTypeIcon(url) {
|
|
5210
|
+
const ext = filenameFromURL(url).split(".").pop()?.toLowerCase();
|
|
5211
|
+
if (ext === "mp3" || ext === "wav" || ext === "ogg") return audioIcon;
|
|
5212
|
+
if (ext === "webm" || ext === "mp4" || ext === "mov") return videoIcon;
|
|
5213
|
+
return imageIcon;
|
|
5214
|
+
}
|
|
5215
|
+
function AssetTransferAnimation() {
|
|
5216
|
+
return /* @__PURE__ */ jsxs7("div", { className: "se-import-transfer", "aria-hidden": "true", children: [
|
|
5217
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-transfer__source se-import-transfer__source--se", children: /* @__PURE__ */ jsx13("img", { src: sourceSEIcon, alt: "" }) }),
|
|
5218
|
+
/* @__PURE__ */ jsxs7("div", { className: "se-import-transfer__files", children: [
|
|
5219
|
+
/* @__PURE__ */ jsx13(
|
|
5220
|
+
"img",
|
|
5221
|
+
{
|
|
5222
|
+
className: "se-import-transfer__file se-import-transfer__file--one",
|
|
5223
|
+
src: imageFileIcon,
|
|
5224
|
+
alt: ""
|
|
5225
|
+
}
|
|
5226
|
+
),
|
|
5227
|
+
/* @__PURE__ */ jsx13(
|
|
5228
|
+
"img",
|
|
5229
|
+
{
|
|
5230
|
+
className: "se-import-transfer__file se-import-transfer__file--two",
|
|
5231
|
+
src: audioFileIcon,
|
|
5232
|
+
alt: ""
|
|
5233
|
+
}
|
|
5234
|
+
),
|
|
5235
|
+
/* @__PURE__ */ jsx13(
|
|
5236
|
+
"img",
|
|
5237
|
+
{
|
|
5238
|
+
className: "se-import-transfer__file se-import-transfer__file--three",
|
|
5239
|
+
src: imageFileIcon,
|
|
5240
|
+
alt: ""
|
|
5241
|
+
}
|
|
5242
|
+
),
|
|
5243
|
+
/* @__PURE__ */ jsx13(
|
|
5244
|
+
"img",
|
|
5245
|
+
{
|
|
5246
|
+
className: "se-import-transfer__file se-import-transfer__file--four",
|
|
5247
|
+
src: videoFileIcon,
|
|
5248
|
+
alt: ""
|
|
5249
|
+
}
|
|
5250
|
+
)
|
|
4765
5251
|
] }),
|
|
4766
|
-
/* @__PURE__ */ jsx13(
|
|
5252
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-transfer__source se-import-transfer__source--lumia", children: /* @__PURE__ */ jsx13("img", { src: sourceLumiaIcon, alt: "" }) })
|
|
4767
5253
|
] });
|
|
4768
5254
|
}
|
|
4769
|
-
function StepMirror({
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
const
|
|
4775
|
-
const
|
|
4776
|
-
const
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
/* @__PURE__ */ jsx13(
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
5255
|
+
function StepMirror({
|
|
5256
|
+
rows,
|
|
5257
|
+
running,
|
|
5258
|
+
onRetry
|
|
5259
|
+
}) {
|
|
5260
|
+
const done = rows.filter((row) => row.state === "done").length;
|
|
5261
|
+
const reused = rows.filter((row) => row.state === "reused").length;
|
|
5262
|
+
const keptOnCdn = rows.filter((row) => row.state === "kept-on-cdn").length;
|
|
5263
|
+
const failed = rows.filter((row) => row.state === "failed").length;
|
|
5264
|
+
const completed = done + reused + keptOnCdn + failed;
|
|
5265
|
+
const summary = running ? `Downloading... (${done + reused + keptOnCdn}/${rows.length})` : `Finished. ${done} mirrored${reused ? `, ${reused} reused` : ""}${keptOnCdn ? `, ${keptOnCdn} kept on CDN` : ""}${failed ? `, ${failed} failed` : ""}.`;
|
|
5266
|
+
return /* @__PURE__ */ jsxs7("div", { className: panelClass("se-import-panel--wide"), children: [
|
|
5267
|
+
/* @__PURE__ */ jsx13(StepHeader, { number: 4, title: "Mirroring assets", subtitle: "We're downloading your assets from StreamElements and preparing them for import." }),
|
|
5268
|
+
/* @__PURE__ */ jsx13(AssetTransferAnimation, {}),
|
|
5269
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-mirror-head", children: /* @__PURE__ */ jsx13("span", { children: summary }) }),
|
|
5270
|
+
/* @__PURE__ */ jsx13(ProgressBar, { value: completed, max: rows.length }),
|
|
5271
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-asset-list", children: rows.map((row, index) => /* @__PURE__ */ jsxs7(
|
|
5272
|
+
"div",
|
|
5273
|
+
{
|
|
5274
|
+
className: `se-import-asset-row se-import-asset-row--${row.state}`,
|
|
5275
|
+
children: [
|
|
5276
|
+
/* @__PURE__ */ jsx13(
|
|
5277
|
+
"img",
|
|
5278
|
+
{
|
|
5279
|
+
className: "se-import-asset-row__icon",
|
|
5280
|
+
src: fileTypeIcon(row.url),
|
|
5281
|
+
alt: ""
|
|
5282
|
+
}
|
|
5283
|
+
),
|
|
5284
|
+
/* @__PURE__ */ jsx13("span", { className: "se-import-asset-row__url", title: row.url, children: row.url }),
|
|
5285
|
+
/* @__PURE__ */ jsx13("span", { className: "se-import-asset-row__state", children: mirrorLabel(row.state) }),
|
|
5286
|
+
row.state === "failed" && /* @__PURE__ */ jsx13(
|
|
5287
|
+
LSButton,
|
|
5288
|
+
{
|
|
5289
|
+
type: "button",
|
|
5290
|
+
variant: "text",
|
|
5291
|
+
color: "secondary",
|
|
5292
|
+
size: "small",
|
|
5293
|
+
className: "se-import-link-button",
|
|
5294
|
+
onClick: () => onRetry(index),
|
|
5295
|
+
label: "Retry"
|
|
5296
|
+
}
|
|
5297
|
+
),
|
|
5298
|
+
row.error && /* @__PURE__ */ jsx13("span", { className: "se-import-asset-row__error", children: row.error })
|
|
5299
|
+
]
|
|
5300
|
+
},
|
|
5301
|
+
row.url
|
|
5302
|
+
)) })
|
|
4799
5303
|
] });
|
|
4800
5304
|
}
|
|
4801
|
-
function StepReview({
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
5305
|
+
function StepReview({
|
|
5306
|
+
item,
|
|
5307
|
+
index,
|
|
5308
|
+
total,
|
|
5309
|
+
state,
|
|
5310
|
+
error,
|
|
5311
|
+
generated,
|
|
5312
|
+
canvas,
|
|
5313
|
+
onSkip,
|
|
5314
|
+
onKeep,
|
|
5315
|
+
onGenerate,
|
|
5316
|
+
onAccept,
|
|
5317
|
+
onRetry,
|
|
5318
|
+
onPickMarketplace,
|
|
5319
|
+
onKeepAllPlaceholders,
|
|
5320
|
+
onSkipAll,
|
|
5321
|
+
remainingCount,
|
|
5322
|
+
marketplaceAvailable
|
|
5323
|
+
}) {
|
|
5324
|
+
return /* @__PURE__ */ jsxs7("div", { className: panelClass("se-import-panel--medium"), children: [
|
|
5325
|
+
/* @__PURE__ */ jsx13(
|
|
5326
|
+
StepHeader,
|
|
5327
|
+
{
|
|
5328
|
+
number: 4,
|
|
5329
|
+
title: `Review widget ${index + 1} of ${total}`,
|
|
5330
|
+
subtitle: "Choose how to handle this unsupported StreamElements widget"
|
|
5331
|
+
}
|
|
5332
|
+
),
|
|
5333
|
+
/* @__PURE__ */ jsxs7("div", { className: "se-import-review-card", children: [
|
|
5334
|
+
/* @__PURE__ */ jsxs7("div", { children: [
|
|
5335
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-review-card__type", children: item.seWidget.type }),
|
|
5336
|
+
/* @__PURE__ */ jsx13("p", { children: item.reason })
|
|
4809
5337
|
] }),
|
|
4810
|
-
/* @__PURE__ */
|
|
4811
|
-
item.flaggedOff && /* @__PURE__ */ jsx13("div", { style: { fontSize: 10, padding: "2px 8px", borderRadius: 4, background: "rgba(234, 179, 8, 0.2)", color: "#facc15", textTransform: "uppercase", letterSpacing: 0.5, fontWeight: 600 }, children: "Auto-import disabled" }),
|
|
4812
|
-
/* @__PURE__ */ jsx13("div", { style: { fontSize: 11, opacity: 0.7, textTransform: "uppercase", letterSpacing: 0.5 }, children: item.status })
|
|
4813
|
-
] })
|
|
5338
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-review-card__status", children: item.flaggedOff ? "Auto-import disabled" : item.status })
|
|
4814
5339
|
] }),
|
|
4815
|
-
remainingCount > 1 && /*
|
|
4816
|
-
|
|
5340
|
+
remainingCount > 1 && /* Bulk-action row — shortcut to wrap up the review step when there are still
|
|
5341
|
+
several unactioned widgets and the user doesn't want to walk each one. */
|
|
5342
|
+
/* @__PURE__ */ jsxs7("div", { className: "se-import-review-bulk", children: [
|
|
5343
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
4817
5344
|
remainingCount,
|
|
4818
5345
|
" remaining"
|
|
4819
5346
|
] }),
|
|
4820
|
-
/* @__PURE__ */ jsx13(
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
5347
|
+
/* @__PURE__ */ jsx13(
|
|
5348
|
+
LSButton,
|
|
5349
|
+
{
|
|
5350
|
+
type: "button",
|
|
5351
|
+
color: "secondary",
|
|
5352
|
+
variant: "contained",
|
|
5353
|
+
onClick: onKeepAllPlaceholders,
|
|
5354
|
+
label: "Keep all placeholders"
|
|
5355
|
+
}
|
|
5356
|
+
),
|
|
5357
|
+
/* @__PURE__ */ jsx13(
|
|
5358
|
+
LSButton,
|
|
5359
|
+
{
|
|
5360
|
+
type: "button",
|
|
5361
|
+
color: "secondary",
|
|
5362
|
+
variant: "contained",
|
|
5363
|
+
onClick: onSkipAll,
|
|
5364
|
+
label: "Skip all"
|
|
5365
|
+
}
|
|
5366
|
+
)
|
|
4826
5367
|
] }),
|
|
4827
|
-
state === "generating" && /* @__PURE__ */ jsx13("div", {
|
|
4828
|
-
state === "generated" && generated && /* @__PURE__ */ jsxs7(
|
|
4829
|
-
/* @__PURE__ */ jsx13("div", {
|
|
5368
|
+
state === "generating" && /* @__PURE__ */ jsx13("div", { className: "se-import-muted", children: "Generating with AI. This can take 30-90 seconds." }),
|
|
5369
|
+
state === "generated" && generated && /* @__PURE__ */ jsxs7("div", { className: "se-import-generated", children: [
|
|
5370
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-generated__title", children: "Preview" }),
|
|
4830
5371
|
(() => {
|
|
4831
5372
|
const landing = getAILandingBounds(item.seWidget, canvas);
|
|
4832
|
-
return /* @__PURE__ */ jsx13(
|
|
5373
|
+
return /* @__PURE__ */ jsx13(
|
|
5374
|
+
CustomOverlayPreview,
|
|
5375
|
+
{
|
|
5376
|
+
html: generated.html ?? "",
|
|
5377
|
+
css: generated.css ?? "",
|
|
5378
|
+
js: generated.js ?? "",
|
|
5379
|
+
data: generated.data ?? {},
|
|
5380
|
+
width: landing.width,
|
|
5381
|
+
height: landing.height
|
|
5382
|
+
}
|
|
5383
|
+
);
|
|
4833
5384
|
})(),
|
|
4834
|
-
/* @__PURE__ */ jsxs7("details", { children: [
|
|
4835
|
-
/* @__PURE__ */ jsx13("summary", {
|
|
4836
|
-
/* @__PURE__ */
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
/* @__PURE__ */ jsx13("summary", { style: { cursor: "pointer", fontSize: 12 }, children: "JS" }),
|
|
4846
|
-
/* @__PURE__ */ jsx13("pre", { style: { fontSize: 11, padding: 8, background: "rgba(0,0,0,0.25)", borderRadius: 4, maxHeight: 160, overflow: "auto" }, children: generated.js || "" })
|
|
4847
|
-
] })
|
|
5385
|
+
/* @__PURE__ */ jsxs7("details", { className: "se-import-code", children: [
|
|
5386
|
+
/* @__PURE__ */ jsx13("summary", { children: "Generated code" }),
|
|
5387
|
+
/* @__PURE__ */ jsx13("pre", { children: JSON.stringify(
|
|
5388
|
+
{
|
|
5389
|
+
html: generated.html ?? "",
|
|
5390
|
+
css: generated.css ?? "",
|
|
5391
|
+
js: generated.js ?? ""
|
|
5392
|
+
},
|
|
5393
|
+
null,
|
|
5394
|
+
2
|
|
5395
|
+
) })
|
|
4848
5396
|
] })
|
|
4849
5397
|
] }),
|
|
4850
5398
|
error && /* @__PURE__ */ jsx13(ErrorPanel, { message: error }),
|
|
4851
|
-
/* @__PURE__ */ jsxs7("details", { children: [
|
|
4852
|
-
/* @__PURE__ */ jsx13("summary", {
|
|
4853
|
-
/* @__PURE__ */ jsx13("pre", {
|
|
5399
|
+
/* @__PURE__ */ jsxs7("details", { className: "se-import-code", children: [
|
|
5400
|
+
/* @__PURE__ */ jsx13("summary", { children: "Original StreamElements config" }),
|
|
5401
|
+
/* @__PURE__ */ jsx13("pre", { children: JSON.stringify(item.seWidget.variables ?? {}, null, 2) })
|
|
4854
5402
|
] }),
|
|
4855
|
-
/* @__PURE__ */ jsx13("div", { className: "
|
|
4856
|
-
/* @__PURE__ */ jsx13(
|
|
4857
|
-
|
|
4858
|
-
|
|
5403
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-actions se-import-actions--inline", children: state === "generated" ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
5404
|
+
/* @__PURE__ */ jsx13(
|
|
5405
|
+
LSButton,
|
|
5406
|
+
{
|
|
5407
|
+
type: "button",
|
|
5408
|
+
color: "secondary",
|
|
5409
|
+
onClick: onRetry,
|
|
5410
|
+
label: "Try again"
|
|
5411
|
+
}
|
|
5412
|
+
),
|
|
5413
|
+
/* @__PURE__ */ jsx13(
|
|
5414
|
+
LSButton,
|
|
5415
|
+
{
|
|
5416
|
+
type: "button",
|
|
5417
|
+
color: "secondary",
|
|
5418
|
+
onClick: onSkip,
|
|
5419
|
+
label: "Skip this widget"
|
|
5420
|
+
}
|
|
5421
|
+
),
|
|
5422
|
+
/* @__PURE__ */ jsx13(
|
|
5423
|
+
LSButton,
|
|
5424
|
+
{
|
|
5425
|
+
type: "button",
|
|
5426
|
+
color: "primary",
|
|
5427
|
+
onClick: onAccept,
|
|
5428
|
+
label: "Use this and continue"
|
|
5429
|
+
}
|
|
5430
|
+
)
|
|
4859
5431
|
] }) : /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
4860
|
-
!item.flaggedOff && /* @__PURE__ */ jsx13(
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
5432
|
+
!item.flaggedOff && /* @__PURE__ */ jsx13(
|
|
5433
|
+
LSButton,
|
|
5434
|
+
{
|
|
5435
|
+
type: "button",
|
|
5436
|
+
color: "secondary",
|
|
5437
|
+
onClick: onKeep,
|
|
5438
|
+
disabled: state === "generating",
|
|
5439
|
+
label: "Keep placeholder"
|
|
5440
|
+
}
|
|
5441
|
+
),
|
|
5442
|
+
/* @__PURE__ */ jsx13(
|
|
5443
|
+
LSButton,
|
|
5444
|
+
{
|
|
5445
|
+
type: "button",
|
|
5446
|
+
color: "secondary",
|
|
5447
|
+
onClick: onSkip,
|
|
5448
|
+
disabled: state === "generating",
|
|
5449
|
+
label: "Skip"
|
|
5450
|
+
}
|
|
5451
|
+
),
|
|
5452
|
+
marketplaceAvailable && /* @__PURE__ */ jsx13(
|
|
5453
|
+
LSButton,
|
|
5454
|
+
{
|
|
5455
|
+
type: "button",
|
|
5456
|
+
color: "secondary",
|
|
5457
|
+
onClick: onPickMarketplace,
|
|
5458
|
+
disabled: state === "generating",
|
|
5459
|
+
label: "Pick from Marketplace"
|
|
5460
|
+
}
|
|
5461
|
+
),
|
|
5462
|
+
/* @__PURE__ */ jsx13(
|
|
5463
|
+
LSButton,
|
|
5464
|
+
{
|
|
5465
|
+
type: "button",
|
|
5466
|
+
color: "primary",
|
|
5467
|
+
onClick: onGenerate,
|
|
5468
|
+
disabled: state === "generating",
|
|
5469
|
+
label: state === "generating" ? "Generating..." : "Generate with AI"
|
|
5470
|
+
}
|
|
5471
|
+
)
|
|
4864
5472
|
] }) }),
|
|
4865
|
-
item.flaggedOff && !marketplaceAvailable && state !== "generated" && /* @__PURE__ */ jsx13("div", {
|
|
5473
|
+
item.flaggedOff && !marketplaceAvailable && state !== "generated" && /* @__PURE__ */ jsx13("div", { className: "se-import-muted", children: "No curated Marketplace replacement is configured for this widget yet." })
|
|
4866
5474
|
] });
|
|
4867
5475
|
}
|
|
4868
|
-
function StepConfirm({
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
5476
|
+
function StepConfirm({
|
|
5477
|
+
result,
|
|
5478
|
+
options,
|
|
5479
|
+
mirrorRows,
|
|
5480
|
+
rowStates
|
|
5481
|
+
}) {
|
|
5482
|
+
const widgets = result.coverage.totalWidgets;
|
|
5483
|
+
const alertCount = result.coverage.mappings.filter((item) => item.lumiaType === "alert").reduce((sum, item) => sum + item.count, 0);
|
|
5484
|
+
const mirrored = mirrorRows.filter(
|
|
5485
|
+
(row) => row.state === "done" || row.state === "reused" || row.state === "kept-on-cdn"
|
|
5486
|
+
).length;
|
|
4872
5487
|
const reviewBuckets = Object.values(rowStates).reduce(
|
|
4873
|
-
(acc,
|
|
4874
|
-
acc[
|
|
5488
|
+
(acc, item) => {
|
|
5489
|
+
acc[item.state] = (acc[item.state] ?? 0) + 1;
|
|
4875
5490
|
return acc;
|
|
4876
5491
|
},
|
|
4877
5492
|
{}
|
|
4878
5493
|
);
|
|
4879
|
-
return /* @__PURE__ */ jsxs7("div", { className: "
|
|
4880
|
-
/* @__PURE__ */ jsx13(
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
5494
|
+
return /* @__PURE__ */ jsxs7("div", { className: panelClass("se-import-panel--confirm"), children: [
|
|
5495
|
+
/* @__PURE__ */ jsx13(
|
|
5496
|
+
StepHeader,
|
|
5497
|
+
{
|
|
5498
|
+
number: 5,
|
|
5499
|
+
title: "Confirm",
|
|
5500
|
+
subtitle: "Review and confirm your import"
|
|
5501
|
+
}
|
|
5502
|
+
),
|
|
5503
|
+
/* @__PURE__ */ jsxs7("div", { className: "se-import-overview", children: [
|
|
5504
|
+
/* @__PURE__ */ jsx13("h3", { children: "Overview" }),
|
|
5505
|
+
/* @__PURE__ */ jsx13(Row, { label: "Overlay", value: options.name || result.overlay.name }),
|
|
5506
|
+
/* @__PURE__ */ jsx13(Row, { label: "Widgets", value: `${widgets}` }),
|
|
5507
|
+
/* @__PURE__ */ jsx13(Row, { label: "Alerts", value: `${alertCount}` }),
|
|
5508
|
+
/* @__PURE__ */ jsx13(
|
|
5509
|
+
Row,
|
|
5510
|
+
{
|
|
5511
|
+
label: "Assets to import",
|
|
5512
|
+
value: `${mirrorRows.length}`,
|
|
5513
|
+
meta: options.mirrorAssets ? `Mirrored to Lumia storage (${mirrored})` : "Skipped"
|
|
5514
|
+
}
|
|
5515
|
+
),
|
|
5516
|
+
/* @__PURE__ */ jsx13(
|
|
5517
|
+
Row,
|
|
5518
|
+
{
|
|
5519
|
+
label: "Import behavior",
|
|
5520
|
+
value: options.mirrorAssets ? "Mirror assets and rewrite URLs" : "Keep original asset URLs"
|
|
5521
|
+
}
|
|
5522
|
+
),
|
|
5523
|
+
reviewBuckets.generated ? /* @__PURE__ */ jsx13(Row, { label: "Generated with AI", value: `${reviewBuckets.generated}` }) : null,
|
|
5524
|
+
reviewBuckets.skipped ? /* @__PURE__ */ jsx13(Row, { label: "Skipped", value: `${reviewBuckets.skipped}` }) : null,
|
|
5525
|
+
reviewBuckets.kept ? /* @__PURE__ */ jsx13(Row, { label: "Kept as placeholder", value: `${reviewBuckets.kept}` }) : null
|
|
4888
5526
|
] })
|
|
4889
5527
|
] });
|
|
4890
5528
|
}
|
|
4891
|
-
function Row({
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
5529
|
+
function Row({
|
|
5530
|
+
label,
|
|
5531
|
+
value,
|
|
5532
|
+
meta
|
|
5533
|
+
}) {
|
|
5534
|
+
return /* @__PURE__ */ jsxs7("div", { className: "se-import-row", children: [
|
|
5535
|
+
/* @__PURE__ */ jsx13("span", { children: label }),
|
|
5536
|
+
/* @__PURE__ */ jsx13("strong", { children: value }),
|
|
5537
|
+
meta && /* @__PURE__ */ jsx13("em", { children: meta })
|
|
4895
5538
|
] });
|
|
4896
5539
|
}
|
|
4897
|
-
function SEImportWizard({
|
|
5540
|
+
function SEImportWizard({
|
|
5541
|
+
bindings,
|
|
5542
|
+
initialUrl = ""
|
|
5543
|
+
}) {
|
|
4898
5544
|
const {
|
|
4899
5545
|
fetchMarketplaceOverlay,
|
|
4900
5546
|
generateAICustomCode,
|
|
@@ -4908,25 +5554,90 @@ function SEImportWizard({ bindings }) {
|
|
|
4908
5554
|
t
|
|
4909
5555
|
} = bindings;
|
|
4910
5556
|
const translate = (key, fallback) => t ? t(key) ?? fallback : fallback;
|
|
4911
|
-
const [step, setStep] = useState6("
|
|
4912
|
-
const [
|
|
5557
|
+
const [step, setStep] = useState6("connect");
|
|
5558
|
+
const [jwt, setJwt] = useState6("");
|
|
5559
|
+
const [seClient, setSeClient] = useState6(null);
|
|
5560
|
+
const [channels, setChannels] = useState6(null);
|
|
5561
|
+
const [selectedChannelId, setSelectedChannelId] = useState6(null);
|
|
5562
|
+
const [connectError, setConnectError] = useState6(null);
|
|
5563
|
+
const [connecting, setConnecting] = useState6(false);
|
|
5564
|
+
const [url, setUrl] = useState6(initialUrl);
|
|
4913
5565
|
const [loadError, setLoadError] = useState6(null);
|
|
4914
5566
|
const [loading, setLoading] = useState6(false);
|
|
4915
5567
|
const [result, setResult] = useState6(null);
|
|
4916
|
-
const [originalReviewItems, setOriginalReviewItems] = useState6(
|
|
4917
|
-
|
|
4918
|
-
|
|
5568
|
+
const [originalReviewItems, setOriginalReviewItems] = useState6(
|
|
5569
|
+
[]
|
|
5570
|
+
);
|
|
5571
|
+
const [options, setOptions] = useState6({
|
|
5572
|
+
mirrorAssets: true,
|
|
5573
|
+
name: ""
|
|
5574
|
+
});
|
|
4919
5575
|
const [mirrorRows, setMirrorRows] = useState6([]);
|
|
4920
5576
|
const [mirrorRunning, setMirrorRunning] = useState6(false);
|
|
4921
|
-
const mirrorStartedRef = useRef4(false);
|
|
4922
5577
|
const [rowStates, setRowStates] = useState6({});
|
|
4923
5578
|
const [reviewIndex, setReviewIndex] = useState6(0);
|
|
4924
5579
|
const [importing, setImporting] = useState6(false);
|
|
5580
|
+
const [marketplacePickerOpen, setMarketplacePickerOpen] = useState6(false);
|
|
5581
|
+
const mirrorStartedRef = useRef4(false);
|
|
5582
|
+
const mirrorAbortRef = useRef4(null);
|
|
5583
|
+
const filenameCacheRef = useRef4(/* @__PURE__ */ new Map());
|
|
5584
|
+
const assetUrls = useMemo5(
|
|
5585
|
+
() => result ? findSEAssetURLs(result.overlay) : [],
|
|
5586
|
+
[result]
|
|
5587
|
+
);
|
|
5588
|
+
const currentItem = originalReviewItems[reviewIndex];
|
|
5589
|
+
const currentRow = currentItem ? rowStates[currentItem.moduleId] ?? { state: "pending" } : void 0;
|
|
5590
|
+
const handleConnect = useCallback3(async () => {
|
|
5591
|
+
setConnectError(null);
|
|
5592
|
+
let client;
|
|
5593
|
+
try {
|
|
5594
|
+
client = SEClient.fromJwt(jwt);
|
|
5595
|
+
} catch (e) {
|
|
5596
|
+
if (e instanceof SEAuthError) {
|
|
5597
|
+
const hint = e.code === "expired" ? "Generate a new JWT on streamelements.com/dashboard/account/channels." : void 0;
|
|
5598
|
+
setConnectError({ message: e.message, hint });
|
|
5599
|
+
} else {
|
|
5600
|
+
setConnectError({
|
|
5601
|
+
message: e instanceof Error ? e.message : "Could not read that token."
|
|
5602
|
+
});
|
|
5603
|
+
}
|
|
5604
|
+
return;
|
|
5605
|
+
}
|
|
5606
|
+
setConnecting(true);
|
|
5607
|
+
try {
|
|
5608
|
+
const usable = await fetchUsableChannels(client);
|
|
5609
|
+
const preferred = usable.find((c) => c._id === client.channelId) ?? usable[0];
|
|
5610
|
+
if (!preferred) {
|
|
5611
|
+
setConnectError({
|
|
5612
|
+
message: "No authorized StreamElements channels found on this account."
|
|
5613
|
+
});
|
|
5614
|
+
return;
|
|
5615
|
+
}
|
|
5616
|
+
setSeClient(client);
|
|
5617
|
+
setChannels(usable);
|
|
5618
|
+
setSelectedChannelId(preferred._id);
|
|
5619
|
+
} catch (e) {
|
|
5620
|
+
if (e instanceof SEAuthError) {
|
|
5621
|
+
const hint = e.code === "unauthorized" ? "Generate a new JWT on streamelements.com/dashboard/account/channels." : void 0;
|
|
5622
|
+
setConnectError({ message: e.message, hint });
|
|
5623
|
+
bindings.onAuthError?.(e);
|
|
5624
|
+
} else {
|
|
5625
|
+
setConnectError({
|
|
5626
|
+
message: e instanceof Error ? e.message : "Could not reach StreamElements."
|
|
5627
|
+
});
|
|
5628
|
+
}
|
|
5629
|
+
} finally {
|
|
5630
|
+
setConnecting(false);
|
|
5631
|
+
}
|
|
5632
|
+
}, [bindings, jwt]);
|
|
4925
5633
|
const handleLoad = useCallback3(async () => {
|
|
4926
5634
|
setLoadError(null);
|
|
4927
5635
|
const parts = extractSEPreviewParts(url);
|
|
4928
5636
|
if (!parts) {
|
|
4929
|
-
setLoadError({
|
|
5637
|
+
setLoadError({
|
|
5638
|
+
message: "That doesn't look like a StreamElements overlay URL.",
|
|
5639
|
+
hint: "Expected: https://streamelements.com/overlay/<overlayId>/<token>"
|
|
5640
|
+
});
|
|
4930
5641
|
return;
|
|
4931
5642
|
}
|
|
4932
5643
|
setLoading(true);
|
|
@@ -4934,51 +5645,82 @@ function SEImportWizard({ bindings }) {
|
|
|
4934
5645
|
const bootstrap = await fetchSEBootstrap(parts);
|
|
4935
5646
|
const imported = importSEBootstrap(bootstrap);
|
|
4936
5647
|
setResult(imported);
|
|
4937
|
-
setOptions((
|
|
5648
|
+
setOptions((previous) => ({ ...previous, name: imported.overlay.name }));
|
|
4938
5649
|
setOriginalReviewItems(imported.reviewItems);
|
|
4939
|
-
setRowStates(
|
|
5650
|
+
setRowStates(
|
|
5651
|
+
Object.fromEntries(
|
|
5652
|
+
imported.reviewItems.map((item) => [
|
|
5653
|
+
item.moduleId,
|
|
5654
|
+
{ state: "pending" }
|
|
5655
|
+
])
|
|
5656
|
+
)
|
|
5657
|
+
);
|
|
4940
5658
|
setReviewIndex(0);
|
|
4941
5659
|
setStep("discovery");
|
|
4942
|
-
} catch (
|
|
4943
|
-
setLoadError({
|
|
5660
|
+
} catch (error) {
|
|
5661
|
+
setLoadError({
|
|
5662
|
+
message: "Could not load the overlay.",
|
|
5663
|
+
hint: error?.message
|
|
5664
|
+
});
|
|
4944
5665
|
} finally {
|
|
4945
5666
|
setLoading(false);
|
|
4946
5667
|
}
|
|
4947
5668
|
}, [url]);
|
|
4948
|
-
const mirrorAbortRef = useRef4(null);
|
|
4949
5669
|
const processAssetRow = useCallback3(
|
|
4950
5670
|
async (assetUrl, idx, existingByFilename, signal) => {
|
|
4951
5671
|
const filename = filenameFromURL(assetUrl);
|
|
4952
5672
|
const reuseUrl = existingByFilename.get(filename);
|
|
4953
5673
|
if (reuseUrl) {
|
|
4954
|
-
setResult(
|
|
5674
|
+
setResult(
|
|
5675
|
+
(current) => current ? {
|
|
5676
|
+
...current,
|
|
5677
|
+
overlay: rewriteAssetURLs(current.overlay, {
|
|
5678
|
+
[assetUrl]: reuseUrl
|
|
5679
|
+
})
|
|
5680
|
+
} : current
|
|
5681
|
+
);
|
|
4955
5682
|
return { state: "reused", newUrl: reuseUrl };
|
|
4956
5683
|
}
|
|
4957
|
-
if (filename.toLowerCase().endsWith(".svg"))
|
|
5684
|
+
if (filename.toLowerCase().endsWith(".svg"))
|
|
4958
5685
|
return { state: "kept-on-cdn", newUrl: assetUrl };
|
|
4959
|
-
|
|
4960
|
-
|
|
5686
|
+
setMirrorRows(
|
|
5687
|
+
(previous) => previous.map(
|
|
5688
|
+
(row, i) => i === idx ? { ...row, state: "fetching", error: void 0 } : row
|
|
5689
|
+
)
|
|
5690
|
+
);
|
|
4961
5691
|
try {
|
|
4962
|
-
const newUrl = await mirrorOneAsset(
|
|
5692
|
+
const newUrl = await mirrorOneAsset(
|
|
5693
|
+
assetUrl,
|
|
5694
|
+
(file) => uploadAsset(file),
|
|
5695
|
+
signal
|
|
5696
|
+
);
|
|
4963
5697
|
existingByFilename.set(filename, newUrl);
|
|
4964
|
-
setResult(
|
|
5698
|
+
setResult(
|
|
5699
|
+
(current) => current ? {
|
|
5700
|
+
...current,
|
|
5701
|
+
overlay: rewriteAssetURLs(current.overlay, {
|
|
5702
|
+
[assetUrl]: newUrl
|
|
5703
|
+
})
|
|
5704
|
+
} : current
|
|
5705
|
+
);
|
|
4965
5706
|
return { state: "done", newUrl };
|
|
4966
|
-
} catch (
|
|
4967
|
-
if (
|
|
5707
|
+
} catch (error) {
|
|
5708
|
+
if (error?.name === "AbortError" || signal?.aborted)
|
|
4968
5709
|
return { state: "pending" };
|
|
4969
|
-
}
|
|
4970
|
-
return { state: "failed", error: extractErrorMessage(err) };
|
|
5710
|
+
return { state: "failed", error: extractErrorMessage(error) };
|
|
4971
5711
|
}
|
|
4972
5712
|
},
|
|
4973
5713
|
[uploadAsset]
|
|
4974
5714
|
);
|
|
4975
|
-
const filenameCacheRef = useRef4(/* @__PURE__ */ new Map());
|
|
4976
5715
|
const runMirror = useCallback3(async () => {
|
|
4977
5716
|
if (!result) return;
|
|
4978
5717
|
mirrorAbortRef.current = new AbortController();
|
|
4979
5718
|
const signal = mirrorAbortRef.current.signal;
|
|
4980
5719
|
setMirrorRunning(true);
|
|
4981
|
-
const initialRows = assetUrls.map((
|
|
5720
|
+
const initialRows = assetUrls.map((assetUrl) => ({
|
|
5721
|
+
url: assetUrl,
|
|
5722
|
+
state: "pending"
|
|
5723
|
+
}));
|
|
4982
5724
|
setMirrorRows(initialRows);
|
|
4983
5725
|
const existingByFilename = /* @__PURE__ */ new Map();
|
|
4984
5726
|
for (const asset of existingAssets ?? []) {
|
|
@@ -4987,17 +5729,17 @@ function SEImportWizard({ bindings }) {
|
|
|
4987
5729
|
}
|
|
4988
5730
|
filenameCacheRef.current = existingByFilename;
|
|
4989
5731
|
for (let i = 0; i < initialRows.length; i += 1) {
|
|
4990
|
-
if (signal.aborted)
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5732
|
+
if (signal.aborted) break;
|
|
5733
|
+
const outcome = await processAssetRow(
|
|
5734
|
+
initialRows[i].url,
|
|
5735
|
+
i,
|
|
5736
|
+
existingByFilename,
|
|
5737
|
+
signal
|
|
5738
|
+
);
|
|
5739
|
+
if (signal.aborted) break;
|
|
5740
|
+
setMirrorRows(
|
|
5741
|
+
(previous) => previous.map((row, idx) => idx === i ? { ...row, ...outcome } : row)
|
|
5742
|
+
);
|
|
5001
5743
|
}
|
|
5002
5744
|
setMirrorRunning(false);
|
|
5003
5745
|
}, [assetUrls, existingAssets, processAssetRow, result]);
|
|
@@ -5005,8 +5747,15 @@ function SEImportWizard({ bindings }) {
|
|
|
5005
5747
|
async (idx) => {
|
|
5006
5748
|
const rowUrl = mirrorRows[idx]?.url;
|
|
5007
5749
|
if (!rowUrl) return;
|
|
5008
|
-
const outcome = await processAssetRow(
|
|
5009
|
-
|
|
5750
|
+
const outcome = await processAssetRow(
|
|
5751
|
+
rowUrl,
|
|
5752
|
+
idx,
|
|
5753
|
+
filenameCacheRef.current,
|
|
5754
|
+
mirrorAbortRef.current?.signal
|
|
5755
|
+
);
|
|
5756
|
+
setMirrorRows(
|
|
5757
|
+
(previous) => previous.map((row, i) => i === idx ? { ...row, ...outcome } : row)
|
|
5758
|
+
);
|
|
5010
5759
|
},
|
|
5011
5760
|
[mirrorRows, processAssetRow]
|
|
5012
5761
|
);
|
|
@@ -5016,15 +5765,23 @@ function SEImportWizard({ bindings }) {
|
|
|
5016
5765
|
void runMirror();
|
|
5017
5766
|
}
|
|
5018
5767
|
}, [step, runMirror]);
|
|
5019
|
-
const currentItem = originalReviewItems[reviewIndex];
|
|
5020
|
-
const currentRow = currentItem ? rowStates[currentItem.moduleId] ?? { state: "pending" } : void 0;
|
|
5021
5768
|
const advanceReview = useCallback3(() => {
|
|
5022
|
-
if (reviewIndex + 1 < originalReviewItems.length)
|
|
5769
|
+
if (reviewIndex + 1 < originalReviewItems.length)
|
|
5770
|
+
setReviewIndex(reviewIndex + 1);
|
|
5023
5771
|
else setStep("confirm");
|
|
5024
5772
|
}, [originalReviewItems.length, reviewIndex]);
|
|
5025
|
-
const setRow = useCallback3(
|
|
5026
|
-
|
|
5027
|
-
|
|
5773
|
+
const setRow = useCallback3(
|
|
5774
|
+
(moduleId, patch) => {
|
|
5775
|
+
setRowStates((previous) => ({
|
|
5776
|
+
...previous,
|
|
5777
|
+
[moduleId]: {
|
|
5778
|
+
...previous[moduleId] ?? { state: "pending" },
|
|
5779
|
+
...patch
|
|
5780
|
+
}
|
|
5781
|
+
}));
|
|
5782
|
+
},
|
|
5783
|
+
[]
|
|
5784
|
+
);
|
|
5028
5785
|
const handleKeep = () => {
|
|
5029
5786
|
if (!result || !currentItem) return;
|
|
5030
5787
|
setResult(applyReviewAction(result, currentItem.moduleId, "keep"));
|
|
@@ -5041,22 +5798,43 @@ function SEImportWizard({ bindings }) {
|
|
|
5041
5798
|
if (!currentItem || !result) return;
|
|
5042
5799
|
setRow(currentItem.moduleId, { state: "generating", error: void 0 });
|
|
5043
5800
|
try {
|
|
5044
|
-
const canvas = {
|
|
5045
|
-
|
|
5801
|
+
const canvas = {
|
|
5802
|
+
width: result.overlay.settings.metadata.width,
|
|
5803
|
+
height: result.overlay.settings.metadata.height
|
|
5804
|
+
};
|
|
5805
|
+
const generated = await generateAICustomCode(
|
|
5806
|
+
buildAIPromptForSEWidget(currentItem.seWidget, canvas)
|
|
5807
|
+
);
|
|
5046
5808
|
setRow(currentItem.moduleId, { state: "generated", generated });
|
|
5047
|
-
} catch (
|
|
5048
|
-
setRow(currentItem.moduleId, {
|
|
5809
|
+
} catch (error) {
|
|
5810
|
+
setRow(currentItem.moduleId, {
|
|
5811
|
+
state: "failed",
|
|
5812
|
+
error: error?.message ?? "AI generation failed."
|
|
5813
|
+
});
|
|
5049
5814
|
}
|
|
5050
5815
|
};
|
|
5051
5816
|
const handleAcceptGenerated = () => {
|
|
5052
5817
|
if (!result || !currentItem || !currentRow?.generated) return;
|
|
5053
|
-
setResult(
|
|
5818
|
+
setResult(
|
|
5819
|
+
applyReviewAction(
|
|
5820
|
+
result,
|
|
5821
|
+
currentItem.moduleId,
|
|
5822
|
+
"ai",
|
|
5823
|
+
currentRow.generated
|
|
5824
|
+
)
|
|
5825
|
+
);
|
|
5054
5826
|
advanceReview();
|
|
5055
5827
|
};
|
|
5056
|
-
const [marketplacePickerOpen, setMarketplacePickerOpen] = useState6(false);
|
|
5057
5828
|
const handlePickMarketplace = (transplant) => {
|
|
5058
5829
|
if (!result || !currentItem) return;
|
|
5059
|
-
setResult(
|
|
5830
|
+
setResult(
|
|
5831
|
+
applyReviewAction(
|
|
5832
|
+
result,
|
|
5833
|
+
currentItem.moduleId,
|
|
5834
|
+
"marketplace",
|
|
5835
|
+
transplant
|
|
5836
|
+
)
|
|
5837
|
+
);
|
|
5060
5838
|
setRow(currentItem.moduleId, { state: "kept" });
|
|
5061
5839
|
setMarketplacePickerOpen(false);
|
|
5062
5840
|
advanceReview();
|
|
@@ -5066,22 +5844,22 @@ function SEImportWizard({ bindings }) {
|
|
|
5066
5844
|
const patch = {};
|
|
5067
5845
|
for (const item of originalReviewItems) {
|
|
5068
5846
|
const rowState = rowStates[item.moduleId]?.state ?? "pending";
|
|
5069
|
-
if (rowState !== "pending")
|
|
5070
|
-
|
|
5071
|
-
if (item.status !== "placeholder" && item.status !== "template") continue;
|
|
5847
|
+
if (rowState !== "pending" || item.flaggedOff || item.status !== "placeholder" && item.status !== "template")
|
|
5848
|
+
continue;
|
|
5072
5849
|
patch[item.moduleId] = { state: "kept" };
|
|
5073
5850
|
}
|
|
5074
|
-
if (Object.keys(patch).length)
|
|
5075
|
-
|
|
5851
|
+
if (Object.keys(patch).length)
|
|
5852
|
+
setRowStates((previous) => ({ ...previous, ...patch }));
|
|
5853
|
+
const remainingIndex = originalReviewItems.findIndex(
|
|
5854
|
+
(item) => (patch[item.moduleId]?.state ?? rowStates[item.moduleId]?.state ?? "pending") === "pending"
|
|
5855
|
+
);
|
|
5076
5856
|
if (remainingIndex >= 0) {
|
|
5077
5857
|
setReviewIndex(remainingIndex);
|
|
5078
5858
|
const remainingItem = originalReviewItems[remainingIndex];
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
notify.warning("Review the remaining widget before continuing.");
|
|
5084
|
-
}
|
|
5859
|
+
const actionText = remainingItem?.flaggedOff && hasMarketplaceCandidates(remainingItem.seWidget.type) ? "Skip, Marketplace, or Generate with AI" : "Skip or Generate with AI";
|
|
5860
|
+
notify.warning(
|
|
5861
|
+
remainingItem?.flaggedOff ? `Choose ${actionText} for the flagged-off widget.` : "Review the remaining widget before continuing."
|
|
5862
|
+
);
|
|
5085
5863
|
return;
|
|
5086
5864
|
}
|
|
5087
5865
|
setStep("confirm");
|
|
@@ -5100,10 +5878,11 @@ function SEImportWizard({ bindings }) {
|
|
|
5100
5878
|
setStep("confirm");
|
|
5101
5879
|
return;
|
|
5102
5880
|
}
|
|
5103
|
-
const nextLayers = (result.overlay.settings.layers ?? []).filter(
|
|
5881
|
+
const nextLayers = (result.overlay.settings.layers ?? []).filter(
|
|
5882
|
+
(layer) => !toSkip.has(layer.id)
|
|
5883
|
+
);
|
|
5104
5884
|
const modules = { ...result.overlay.settings.modules ?? {} };
|
|
5105
5885
|
for (const id of toSkip) delete modules[id];
|
|
5106
|
-
const reviewItems = result.reviewItems.filter((r) => !toSkip.has(r.moduleId));
|
|
5107
5886
|
setResult({
|
|
5108
5887
|
...result,
|
|
5109
5888
|
overlay: {
|
|
@@ -5111,9 +5890,11 @@ function SEImportWizard({ bindings }) {
|
|
|
5111
5890
|
settings: { ...result.overlay.settings, layers: nextLayers, modules },
|
|
5112
5891
|
layers_count: nextLayers.length
|
|
5113
5892
|
},
|
|
5114
|
-
reviewItems
|
|
5893
|
+
reviewItems: result.reviewItems.filter(
|
|
5894
|
+
(item) => !toSkip.has(item.moduleId)
|
|
5895
|
+
)
|
|
5115
5896
|
});
|
|
5116
|
-
setRowStates((
|
|
5897
|
+
setRowStates((previous) => ({ ...previous, ...patch }));
|
|
5117
5898
|
setStep("confirm");
|
|
5118
5899
|
};
|
|
5119
5900
|
const handleFinalImport = useCallback3(async () => {
|
|
@@ -5126,157 +5907,235 @@ function SEImportWizard({ bindings }) {
|
|
|
5126
5907
|
settings: result.overlay.settings
|
|
5127
5908
|
};
|
|
5128
5909
|
const { uuid } = await saveOverlay(body);
|
|
5129
|
-
notify.success(
|
|
5910
|
+
notify.success("Imported overlay from StreamElements.");
|
|
5130
5911
|
mirrorAbortRef.current?.abort();
|
|
5131
5912
|
onClose();
|
|
5132
5913
|
if (uuid) onComplete({ overlayId: uuid });
|
|
5133
|
-
} catch (
|
|
5134
|
-
notify.error(`Import failed: ${extractErrorMessage(
|
|
5914
|
+
} catch (error) {
|
|
5915
|
+
notify.error(`Import failed: ${extractErrorMessage(error)}`);
|
|
5135
5916
|
} finally {
|
|
5136
5917
|
setImporting(false);
|
|
5137
5918
|
}
|
|
5138
5919
|
}, [notify, onClose, onComplete, options.name, result, saveOverlay]);
|
|
5139
|
-
const
|
|
5920
|
+
const visibleSteps = useMemo5(() => {
|
|
5921
|
+
const showMirrorStep = options.mirrorAssets && (assetUrls.length > 0 || mirrorRows.length > 0 || step === "mirror");
|
|
5922
|
+
const steps = CORE_STEPS.filter(
|
|
5923
|
+
(item) => item.key !== "mirror" || showMirrorStep
|
|
5924
|
+
);
|
|
5925
|
+
if (originalReviewItems.length > 0)
|
|
5926
|
+
steps.splice(Math.max(steps.length - 1, 0), 0, {
|
|
5927
|
+
key: "review",
|
|
5928
|
+
label: `Review (${originalReviewItems.length})`
|
|
5929
|
+
});
|
|
5930
|
+
return steps;
|
|
5931
|
+
}, [
|
|
5932
|
+
assetUrls.length,
|
|
5933
|
+
mirrorRows.length,
|
|
5934
|
+
options.mirrorAssets,
|
|
5935
|
+
originalReviewItems.length,
|
|
5936
|
+
step
|
|
5937
|
+
]);
|
|
5140
5938
|
const goBack = () => {
|
|
5939
|
+
const currentIndex = visibleSteps.findIndex((item) => item.key === step);
|
|
5141
5940
|
if (step === "review" && reviewIndex > 0) {
|
|
5142
5941
|
setReviewIndex(reviewIndex - 1);
|
|
5143
5942
|
return;
|
|
5144
5943
|
}
|
|
5145
|
-
|
|
5146
|
-
if (idx <= 0) return;
|
|
5147
|
-
let prev = stepOrder[idx - 1];
|
|
5148
|
-
if (prev === "mirror" && !options.mirrorAssets) prev = stepOrder[idx - 2];
|
|
5149
|
-
if (prev) setStep(prev);
|
|
5944
|
+
if (currentIndex > 0) setStep(visibleSteps[currentIndex - 1].key);
|
|
5150
5945
|
};
|
|
5151
5946
|
const goNext = () => {
|
|
5152
|
-
if (step === "
|
|
5153
|
-
void
|
|
5154
|
-
|
|
5155
|
-
}
|
|
5156
|
-
if (step === "discovery") {
|
|
5157
|
-
setStep("options");
|
|
5158
|
-
return;
|
|
5159
|
-
}
|
|
5160
|
-
if (step === "options") {
|
|
5161
|
-
if (options.mirrorAssets && assetUrls.length > 0) setStep("mirror");
|
|
5162
|
-
else if (originalReviewItems.length > 0) setStep("review");
|
|
5163
|
-
else setStep("confirm");
|
|
5164
|
-
return;
|
|
5165
|
-
}
|
|
5166
|
-
if (step === "mirror") {
|
|
5167
|
-
if (originalReviewItems.length > 0) setStep("review");
|
|
5168
|
-
else setStep("confirm");
|
|
5947
|
+
if (step === "connect") {
|
|
5948
|
+
if (!seClient) return void handleConnect();
|
|
5949
|
+
setStep("url");
|
|
5169
5950
|
return;
|
|
5170
5951
|
}
|
|
5952
|
+
if (step === "url") return void handleLoad();
|
|
5171
5953
|
if (step === "review") {
|
|
5172
|
-
if (currentItem)
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
return;
|
|
5180
|
-
}
|
|
5181
|
-
handleKeep();
|
|
5182
|
-
} else {
|
|
5183
|
-
advanceReview();
|
|
5954
|
+
if (!currentItem) return;
|
|
5955
|
+
if (currentRow?.state === "generated") return handleAcceptGenerated();
|
|
5956
|
+
if (currentRow?.state === "pending") {
|
|
5957
|
+
if (currentItem.flaggedOff) {
|
|
5958
|
+
const actionText = hasMarketplaceCandidates(currentItem.seWidget.type) ? "Skip, Marketplace, or Generate with AI" : "Skip or Generate with AI";
|
|
5959
|
+
notify.warning(`Choose ${actionText} for the flagged-off widget.`);
|
|
5960
|
+
return;
|
|
5184
5961
|
}
|
|
5962
|
+
return handleKeep();
|
|
5185
5963
|
}
|
|
5186
|
-
return;
|
|
5187
|
-
}
|
|
5188
|
-
if (step === "confirm") {
|
|
5189
|
-
void handleFinalImport();
|
|
5190
|
-
return;
|
|
5964
|
+
return advanceReview();
|
|
5191
5965
|
}
|
|
5966
|
+
if (step === "confirm") return void handleFinalImport();
|
|
5967
|
+
const currentIndex = visibleSteps.findIndex((item) => item.key === step);
|
|
5968
|
+
if (currentIndex >= 0)
|
|
5969
|
+
setStep(visibleSteps[currentIndex + 1]?.key ?? "confirm");
|
|
5192
5970
|
};
|
|
5193
5971
|
const nextLabel = (() => {
|
|
5194
|
-
if (step === "
|
|
5195
|
-
|
|
5196
|
-
if (step === "
|
|
5197
|
-
if (step === "mirror") return mirrorRunning ? "Working
|
|
5198
|
-
if (step === "review")
|
|
5199
|
-
|
|
5200
|
-
|
|
5972
|
+
if (step === "connect")
|
|
5973
|
+
return connecting ? "Connecting..." : seClient ? "Continue" : "Connect";
|
|
5974
|
+
if (step === "url") return loading ? "Loading..." : "Load overlay";
|
|
5975
|
+
if (step === "mirror") return mirrorRunning ? "Working..." : "Continue";
|
|
5976
|
+
if (step === "review")
|
|
5977
|
+
return currentRow?.state === "generated" ? "Use & continue" : "Continue";
|
|
5978
|
+
if (step === "confirm")
|
|
5979
|
+
return importing ? "Importing..." : "Create overlay";
|
|
5980
|
+
return "Continue";
|
|
5201
5981
|
})();
|
|
5202
5982
|
const nextDisabled = (() => {
|
|
5983
|
+
if (step === "connect")
|
|
5984
|
+
return connecting || !seClient && !jwt.trim();
|
|
5203
5985
|
if (step === "url") return loading || !url.trim();
|
|
5204
5986
|
if (step === "mirror") return mirrorRunning;
|
|
5205
|
-
if (step === "review")
|
|
5987
|
+
if (step === "review")
|
|
5988
|
+
return currentRow?.state === "generating" || currentRow?.state === "pending" && currentItem?.flaggedOff;
|
|
5206
5989
|
if (step === "confirm") return importing;
|
|
5207
5990
|
return false;
|
|
5208
5991
|
})();
|
|
5209
|
-
const
|
|
5210
|
-
|
|
5211
|
-
{
|
|
5212
|
-
|
|
5213
|
-
{ key: "options", label: "Options" },
|
|
5214
|
-
...options.mirrorAssets && assetUrls.length > 0 ? [{ key: "mirror", label: "Assets" }] : [],
|
|
5215
|
-
...originalReviewItems.length > 0 ? [{ key: "review", label: `Review (${originalReviewItems.length})` }] : [],
|
|
5216
|
-
{ key: "confirm", label: "Confirm" }
|
|
5217
|
-
];
|
|
5218
|
-
return /* @__PURE__ */ jsxs7("div", { className: "ui-flex-column ui-gap-2", style: { minWidth: 680 }, children: [
|
|
5219
|
-
result && /* @__PURE__ */ jsx13("div", { className: "ui-flex-row ui-gap-2", style: { flexWrap: "wrap", paddingBottom: 8, borderBottom: "1px solid var(--ui-border, #2a2c31)" }, children: visibleSteps.map((s, i) => /* @__PURE__ */ jsx13(StepDot, { num: i + 1, label: s.label, active: s.key === step, done: visibleSteps.findIndex((v) => v.key === step) > i }, s.key)) }),
|
|
5220
|
-
step === "url" && /* @__PURE__ */ jsx13(StepURL, { url, setUrl, error: loadError, busy: loading }),
|
|
5221
|
-
step === "discovery" && result && /* @__PURE__ */ jsx13(StepDiscovery, { result, assetCount: assetUrls.length }),
|
|
5222
|
-
step === "options" && /* @__PURE__ */ jsx13(StepOptions, { options, setOptions, assetCount: assetUrls.length }),
|
|
5223
|
-
step === "mirror" && /* @__PURE__ */ jsx13(StepMirror, { rows: mirrorRows, running: mirrorRunning, onRetry: retryMirrorRow }),
|
|
5224
|
-
step === "review" && currentItem && result && !marketplacePickerOpen && /* @__PURE__ */ jsx13(
|
|
5225
|
-
StepReview,
|
|
5226
|
-
{
|
|
5227
|
-
item: currentItem,
|
|
5228
|
-
index: reviewIndex,
|
|
5229
|
-
total: originalReviewItems.length,
|
|
5230
|
-
state: currentRow?.state ?? "pending",
|
|
5231
|
-
error: currentRow?.error,
|
|
5232
|
-
generated: currentRow?.generated,
|
|
5233
|
-
canvas: { width: result.overlay.settings.metadata.width, height: result.overlay.settings.metadata.height },
|
|
5234
|
-
onSkip: handleSkip,
|
|
5235
|
-
onKeep: handleKeep,
|
|
5236
|
-
onGenerate: handleGenerate,
|
|
5237
|
-
onAccept: handleAcceptGenerated,
|
|
5238
|
-
onRetry: handleGenerate,
|
|
5239
|
-
onPickMarketplace: () => setMarketplacePickerOpen(true),
|
|
5240
|
-
onKeepAllPlaceholders: handleKeepAllPlaceholders,
|
|
5241
|
-
onSkipAll: handleSkipAll,
|
|
5242
|
-
remainingCount: originalReviewItems.filter((r) => (rowStates[r.moduleId]?.state ?? "pending") === "pending").length,
|
|
5243
|
-
marketplaceAvailable: hasMarketplaceCandidates(currentItem.seWidget.type)
|
|
5244
|
-
}
|
|
5245
|
-
),
|
|
5246
|
-
step === "review" && currentItem && marketplacePickerOpen && /* @__PURE__ */ jsx13(
|
|
5247
|
-
MarketplacePicker,
|
|
5992
|
+
const activeIndex = visibleSteps.findIndex((item) => item.key === step);
|
|
5993
|
+
return /* @__PURE__ */ jsx13("div", { className: "se-import", children: /* @__PURE__ */ jsxs7("div", { className: "se-import__shell", children: [
|
|
5994
|
+
/* @__PURE__ */ jsx13("header", { className: "se-import__header", children: /* @__PURE__ */ jsx13("div", { className: "se-import-stepper", children: visibleSteps.map((item, index) => /* @__PURE__ */ jsxs7(
|
|
5995
|
+
"div",
|
|
5248
5996
|
{
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5997
|
+
className: stepClass(
|
|
5998
|
+
index < activeIndex,
|
|
5999
|
+
index === activeIndex
|
|
6000
|
+
),
|
|
6001
|
+
children: [
|
|
6002
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-step__label", children: item.label }),
|
|
6003
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-step__line" }),
|
|
6004
|
+
/* @__PURE__ */ jsx13("div", { className: "se-import-step__dot", children: index < activeIndex ? "\u2713" : index + 1 })
|
|
6005
|
+
]
|
|
6006
|
+
},
|
|
6007
|
+
item.key
|
|
6008
|
+
)) }) }),
|
|
6009
|
+
/* @__PURE__ */ jsxs7("main", { className: "se-import__content", children: [
|
|
6010
|
+
step === "connect" && /* @__PURE__ */ jsx13(
|
|
6011
|
+
StepConnect,
|
|
6012
|
+
{
|
|
6013
|
+
jwt,
|
|
6014
|
+
setJwt,
|
|
6015
|
+
error: connectError,
|
|
6016
|
+
busy: connecting,
|
|
6017
|
+
channels,
|
|
6018
|
+
selectedChannelId,
|
|
6019
|
+
setSelectedChannelId,
|
|
6020
|
+
onUseUrl: () => setStep("url")
|
|
6021
|
+
}
|
|
6022
|
+
),
|
|
6023
|
+
step === "url" && /* @__PURE__ */ jsx13(
|
|
6024
|
+
StepURL,
|
|
6025
|
+
{
|
|
6026
|
+
url,
|
|
6027
|
+
setUrl,
|
|
6028
|
+
error: loadError,
|
|
6029
|
+
busy: loading
|
|
6030
|
+
}
|
|
6031
|
+
),
|
|
6032
|
+
step === "discovery" && result && /* @__PURE__ */ jsx13(StepDiscovery, { result, assetCount: assetUrls.length }),
|
|
6033
|
+
step === "options" && /* @__PURE__ */ jsx13(
|
|
6034
|
+
StepOptions,
|
|
6035
|
+
{
|
|
6036
|
+
options,
|
|
6037
|
+
setOptions,
|
|
6038
|
+
assetCount: assetUrls.length
|
|
6039
|
+
}
|
|
6040
|
+
),
|
|
6041
|
+
step === "mirror" && /* @__PURE__ */ jsx13(
|
|
6042
|
+
StepMirror,
|
|
6043
|
+
{
|
|
6044
|
+
rows: mirrorRows,
|
|
6045
|
+
running: mirrorRunning,
|
|
6046
|
+
onRetry: retryMirrorRow
|
|
6047
|
+
}
|
|
6048
|
+
),
|
|
6049
|
+
step === "review" && currentItem && result && !marketplacePickerOpen && /* @__PURE__ */ jsx13(
|
|
6050
|
+
StepReview,
|
|
6051
|
+
{
|
|
6052
|
+
item: currentItem,
|
|
6053
|
+
index: reviewIndex,
|
|
6054
|
+
total: originalReviewItems.length,
|
|
6055
|
+
state: currentRow?.state ?? "pending",
|
|
6056
|
+
error: currentRow?.error,
|
|
6057
|
+
generated: currentRow?.generated,
|
|
6058
|
+
canvas: {
|
|
6059
|
+
width: result.overlay.settings.metadata.width,
|
|
6060
|
+
height: result.overlay.settings.metadata.height
|
|
6061
|
+
},
|
|
6062
|
+
onSkip: handleSkip,
|
|
6063
|
+
onKeep: handleKeep,
|
|
6064
|
+
onGenerate: handleGenerate,
|
|
6065
|
+
onAccept: handleAcceptGenerated,
|
|
6066
|
+
onRetry: handleGenerate,
|
|
6067
|
+
onPickMarketplace: () => setMarketplacePickerOpen(true),
|
|
6068
|
+
onKeepAllPlaceholders: handleKeepAllPlaceholders,
|
|
6069
|
+
onSkipAll: handleSkipAll,
|
|
6070
|
+
remainingCount: originalReviewItems.filter(
|
|
6071
|
+
(item) => (rowStates[item.moduleId]?.state ?? "pending") === "pending"
|
|
6072
|
+
).length,
|
|
6073
|
+
marketplaceAvailable: hasMarketplaceCandidates(
|
|
6074
|
+
currentItem.seWidget.type
|
|
6075
|
+
)
|
|
6076
|
+
}
|
|
6077
|
+
),
|
|
6078
|
+
step === "review" && currentItem && marketplacePickerOpen && /* @__PURE__ */ jsx13("div", { className: panelClass("se-import-panel--wide"), children: /* @__PURE__ */ jsx13(
|
|
6079
|
+
MarketplacePicker,
|
|
6080
|
+
{
|
|
6081
|
+
seWidgetType: currentItem.seWidget.type,
|
|
6082
|
+
fetchMarketplaceOverlay,
|
|
6083
|
+
CustomEmbed,
|
|
6084
|
+
onPick: handlePickMarketplace,
|
|
6085
|
+
onCancel: () => setMarketplacePickerOpen(false)
|
|
6086
|
+
}
|
|
6087
|
+
) }),
|
|
6088
|
+
step === "confirm" && result && /* @__PURE__ */ jsx13(
|
|
6089
|
+
StepConfirm,
|
|
6090
|
+
{
|
|
6091
|
+
result,
|
|
6092
|
+
options,
|
|
6093
|
+
mirrorRows,
|
|
6094
|
+
rowStates
|
|
6095
|
+
}
|
|
6096
|
+
)
|
|
6097
|
+
] }),
|
|
6098
|
+
/* @__PURE__ */ jsxs7("footer", { className: "se-import-actions", children: [
|
|
5258
6099
|
/* @__PURE__ */ jsx13(
|
|
5259
|
-
|
|
6100
|
+
LSButton,
|
|
5260
6101
|
{
|
|
5261
6102
|
type: "button",
|
|
5262
|
-
|
|
6103
|
+
color: "secondary",
|
|
5263
6104
|
onClick: () => {
|
|
5264
6105
|
mirrorAbortRef.current?.abort();
|
|
5265
6106
|
onClose();
|
|
5266
6107
|
},
|
|
5267
6108
|
disabled: loading || importing,
|
|
5268
|
-
|
|
6109
|
+
label: translate("action.cancel", "Cancel")
|
|
6110
|
+
}
|
|
6111
|
+
),
|
|
6112
|
+
activeIndex > 0 && /* @__PURE__ */ jsx13(
|
|
6113
|
+
LSButton,
|
|
6114
|
+
{
|
|
6115
|
+
type: "button",
|
|
6116
|
+
color: "secondary",
|
|
6117
|
+
onClick: goBack,
|
|
6118
|
+
disabled: loading || importing || mirrorRunning || currentRow?.state === "generating",
|
|
6119
|
+
label: "Back"
|
|
5269
6120
|
}
|
|
5270
6121
|
),
|
|
5271
|
-
|
|
5272
|
-
|
|
6122
|
+
/* @__PURE__ */ jsx13(
|
|
6123
|
+
LSButton,
|
|
6124
|
+
{
|
|
6125
|
+
type: "button",
|
|
6126
|
+
color: "primary",
|
|
6127
|
+
onClick: goNext,
|
|
6128
|
+
disabled: nextDisabled,
|
|
6129
|
+
label: nextLabel
|
|
6130
|
+
}
|
|
6131
|
+
)
|
|
5273
6132
|
] })
|
|
5274
|
-
] });
|
|
6133
|
+
] }) });
|
|
5275
6134
|
}
|
|
5276
6135
|
function extractErrorMessage(err) {
|
|
5277
6136
|
if (!err) return "Failed";
|
|
5278
|
-
const
|
|
5279
|
-
return
|
|
6137
|
+
const error = err;
|
|
6138
|
+
return error?.response?.data?.message || error?.response?.data?.error || error?.message || "Failed";
|
|
5280
6139
|
}
|
|
5281
6140
|
|
|
5282
6141
|
// src/se-import/index.ts
|
|
@@ -5403,7 +6262,7 @@ function importSEBootstrap(bootstrap) {
|
|
|
5403
6262
|
const module = {
|
|
5404
6263
|
id: lumiaGroupId,
|
|
5405
6264
|
loaded: true,
|
|
5406
|
-
settings: { title: w
|
|
6265
|
+
settings: { title: defaultLabelForSEWidget(w), type: "group" },
|
|
5407
6266
|
lights: [],
|
|
5408
6267
|
css: {},
|
|
5409
6268
|
content: {
|
|
@@ -5623,6 +6482,8 @@ export {
|
|
|
5623
6482
|
LSVariableInputProvider,
|
|
5624
6483
|
MEDIA_PREVIEW_USER_LEVEL_VALUES,
|
|
5625
6484
|
MarketplacePicker,
|
|
6485
|
+
SEAuthError,
|
|
6486
|
+
SEClient,
|
|
5626
6487
|
SEImportWizard,
|
|
5627
6488
|
SE_IMPORT_FLAGS,
|
|
5628
6489
|
SE_WIDGET_TO_MARKETPLACE_CANDIDATES,
|
|
@@ -5631,9 +6492,11 @@ export {
|
|
|
5631
6492
|
buildBootstrapUrl,
|
|
5632
6493
|
buildChatMessageContent,
|
|
5633
6494
|
codeMirrorlinterOptions,
|
|
6495
|
+
decodeJwtPayload,
|
|
5634
6496
|
extractSEOverlayId,
|
|
5635
6497
|
extractSEPreviewParts,
|
|
5636
6498
|
fetchSEBootstrap,
|
|
6499
|
+
fetchUsableChannels,
|
|
5637
6500
|
filenameFromURL,
|
|
5638
6501
|
findSEAssetURLs,
|
|
5639
6502
|
getAILandingBounds,
|