fix(rsplat): use queue API for Hunyuan3D + fix controls z-index

Also fix canvas.html null reference crash when share-badge is stripped
by extractCanvasContent() header removal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-16 16:37:36 -07:00
parent 077bcf260a
commit 2eb9ca2d8f
2 changed files with 11 additions and 11 deletions

View File

@ -571,10 +571,14 @@ export class FolkSplatViewer extends HTMLElement {
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ image_url: imageUrl, title }),
});
clearInterval(ticker);
document.removeEventListener("visibilitychange", onVisChange);
const stopTicker = () => {
clearInterval(ticker);
document.removeEventListener("visibilitychange", onVisChange);
};
if (res.status === 524 || res.status === 504) {
stopTicker();
status.textContent = "Generation timed out — try a simpler image.";
progress.style.display = "none";
actions.style.display = "flex";
@ -583,6 +587,7 @@ export class FolkSplatViewer extends HTMLElement {
}
if (res.status === 503) {
stopTicker();
status.textContent = "AI generation not available — FAL_KEY not configured";
progress.style.display = "none";
actions.style.display = "flex";
@ -591,6 +596,7 @@ export class FolkSplatViewer extends HTMLElement {
}
if (!res.ok) {
stopTicker();
const err = await res.json().catch(() => ({ error: "Generation failed" }));
status.textContent = (err as any).error || "Generation failed";
progress.style.display = "none";
@ -600,7 +606,7 @@ export class FolkSplatViewer extends HTMLElement {
}
const { job_id } = await res.json() as { job_id: string };
status.textContent = "Generating 3D model — you'll get an email when it's ready...";
// Ticker keeps running — progress bar continues advancing during polling
// Poll for completion
const pollInterval = setInterval(async () => {
@ -610,6 +616,7 @@ export class FolkSplatViewer extends HTMLElement {
const job = await pollRes.json() as any;
if (job.status === "complete") {
stopTicker();
clearInterval(pollInterval);
progress.style.display = "none";
@ -683,6 +690,7 @@ export class FolkSplatViewer extends HTMLElement {
});
} else if (job.status === "failed") {
stopTicker();
clearInterval(pollInterval);
progress.style.display = "none";
status.textContent = job.error || "Generation failed";

View File

@ -2931,24 +2931,18 @@
}
layers = sync.getLayers?.() || [];
tabBar.setLayers(layers);
const activeId = sync.doc?.activeLayerId;
if (activeId) tabBar.setAttribute('active', activeId);
if (sync.getFlows) tabBar.setFlows(sync.getFlows());
} else {
// First connection: push all localStorage tabs into Automerge
for (const l of layers) {
sync.addLayer?.(l);
}
sync.setActiveLayer?.('layer-' + currentModuleId);
}
// Keep localStorage in sync
saveTabs();
// Sync layer changes back to Automerge
tabBar.addEventListener('layer-switch', (e) => {
sync.setActiveLayer?.(e.detail.layerId);
});
tabBar.addEventListener('layer-add', (e) => {
const { moduleId } = e.detail;
const newLayer = makeLayer(moduleId, sync.getLayers?.().length || 0);
@ -2975,8 +2969,6 @@
layers = sync.getLayers?.() || [];
tabBar.setLayers(layers);
if (sync.getFlows) tabBar.setFlows(sync.getFlows());
const activeId = sync.doc?.activeLayerId;
if (activeId) tabBar.setAttribute('active', activeId);
const viewMode = sync.doc?.layerViewMode;
if (viewMode) tabBar.setAttribute('view-mode', viewMode);
saveTabs(); // keep localStorage in sync