fix frontend SVG results and downloads
This commit is contained in:
@@ -10,6 +10,18 @@ const DEFAULT_FORM = {
|
||||
variant_count: 2,
|
||||
};
|
||||
|
||||
function downloadSvgAsset(asset) {
|
||||
const blob = new Blob([asset.svg], { type: asset.media_type || "image/svg+xml;charset=utf-8" });
|
||||
const objectUrl = URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.href = objectUrl;
|
||||
link.download = asset.name || "game-asset.svg";
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
window.setTimeout(() => URL.revokeObjectURL(objectUrl), 0);
|
||||
}
|
||||
|
||||
export function App() {
|
||||
const [config, setConfig] = useState(null);
|
||||
const [session, setSession] = useState(null);
|
||||
@@ -201,7 +213,10 @@ export function App() {
|
||||
<div className="svg-preview" dangerouslySetInnerHTML={{ __html: asset.svg }} />
|
||||
<div className="asset-meta">
|
||||
<strong>{asset.name}</strong>
|
||||
<button type="button" onClick={() => navigator.clipboard?.writeText(asset.svg)}>Copy SVG</button>
|
||||
<div className="asset-actions">
|
||||
<button type="button" onClick={() => downloadSvgAsset(asset)}>Download SVG</button>
|
||||
<button className="secondary" type="button" onClick={() => navigator.clipboard?.writeText(asset.svg)}>Copy SVG</button>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
export const CONFIG_URL = import.meta.env.DEV ? "/config.json" : "./config.json";
|
||||
export const CONFIG_URL = import.meta.env?.DEV ? "/config.json" : "./config.json";
|
||||
|
||||
export function unwrapSkillResponse(payload) {
|
||||
if (payload && typeof payload === "object" && "result" in payload) {
|
||||
return payload.result;
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
export async function requestJson(url, init = {}) {
|
||||
const response = await fetch(url, { credentials: "same-origin", ...init });
|
||||
@@ -43,11 +50,12 @@ export async function callSkill(config, skillName, args) {
|
||||
if (config.auth?.invokeRequiresSession) {
|
||||
await requireSession(config);
|
||||
}
|
||||
const data = await requestJson(`${config.endpoints.invoke}/${encodeURIComponent(skillName)}`, {
|
||||
const payload = await requestJson(`${config.endpoints.invoke}/${encodeURIComponent(skillName)}`, {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({ arguments: args }),
|
||||
});
|
||||
const data = unwrapSkillResponse(payload);
|
||||
if (data?.status === "setup_required") {
|
||||
throw new Error(data.warning || "Backend setup is required before this action can run.");
|
||||
}
|
||||
|
||||
@@ -46,5 +46,7 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monos
|
||||
.svg-preview svg { max-width: 100%; height: auto; image-rendering: pixelated; }
|
||||
.asset-meta { padding: 14px; align-items: start; }
|
||||
.asset-meta strong { overflow-wrap: anywhere; }
|
||||
.asset-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
|
||||
.asset-meta button.secondary { border: 1px solid rgba(148, 163, 184, .35); background: rgba(15, 23, 42, .88); color: #dcecff; }
|
||||
@media (max-width: 900px) { .hero, .workspace { grid-template-columns: 1fr; } h1 { font-size: clamp(36px, 13vw, 64px); } }
|
||||
@media (max-width: 560px) { .form-grid { grid-template-columns: 1fr; } .app-shell { width: min(100% - 20px, 1180px); padding-top: 16px; } .receipt-header, .result-header, .asset-meta { align-items: flex-start; flex-direction: column; } }
|
||||
@media (max-width: 560px) { .form-grid { grid-template-columns: 1fr; } .app-shell { width: min(100% - 20px, 1180px); padding-top: 16px; } .receipt-header, .result-header, .asset-meta { align-items: flex-start; flex-direction: column; } .asset-actions { justify-content: flex-start; } }
|
||||
|
||||
Reference in New Issue
Block a user