Files
Claude 3adebb731f Rename FunPack to FunUI (5.0.3 Classy Chopper): /fun endpoint, wink logo, load-time migration of old names
Old project/workflow names and browser settings migrate on load; /funpack redirects to /fun.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016acRss69eH1235eRdFTZHY
2026-10-25 13:11:03 +00:00

52 lines
2.9 KiB
JavaScript

// The welcome screen: shown the first time this browser opens the app, and from Help ▸ Welcome window.
import { composer as c } from "../../composer/composer.js";
import { list } from "../../shell/project.js";
const SEEN = "funui_welcomed";
const card = (title, sub, onClick) => c.tile.action({ title, sub, onClick });
export default {
id: "welcome",
mount: "menubar.right",
needs: ["project", "maintenance"],
setup({ app }) {
let win = null;
const seen = () => { try { return localStorage.getItem(SEEN) === "1"; } catch { return true; } };
const markSeen = () => { try { localStorage.setItem(SEEN, "1"); } catch { /* private window */ } };
// Saved projects, or a project file from disk: the same two ways File ▸ Load and Open recent offer.
const load = async () => {
let all = []; try { all = await list(); } catch (err) { return c.toast.warn({ text: err.message }); }
const items = [{ id: "__import__", label: "Import a project file…" }, ...all.map((r) => ({ id: r.id, label: r.name }))];
const id = await c.modal.choice({ title: "Load a project", items }).result;
if (!id) return;
if (id === "__import__") {
markSeen(); if (win) win.close("done");
return app.say("project.load");
}
try { await app.project.open(id); markSeen(); if (win) win.close("done"); } catch (err) { c.toast.warn({ text: err.message }); }
};
const open = () => {
if (win) return;
const recent = app.project.project;
const done = () => { markSeen(); if (win) win.close("done"); };
const tiles = c.grid.pair({ children: [
card("Update", "Pull the newest version from origin, install missing requirements and restart ComfyUI (after a running generation finishes)", () => app.maintenance.update()), card("Switch branch", "Pick another branch", () => app.maintenance.switchBranch()),
card("Restart ComfyUI", "Reload the server without updating", () => app.maintenance.restart()), card("Rollback update", "Undo the last update", () => app.maintenance.rollback())] });
win = c.modal.generic({
title: "Welcome to FunUI", size: "lg",
body: c.region.stack({ gap: "md", children: [
c.hint.default({ text: "Multi-scene video on a real timeline." }),
c.button.lg({ label: "Begin", tone: "primary", onClick: done }),
...(recent ? [c.button.md({ label: `Continue with “${recent.name}”`, onClick: done })] : []),
c.button.md({ label: "Load an existing project", tone: "ghost", onClick: load }),
tiles,
] }),
onClose: () => { markSeen(); win = null; },
});
};
const timer = seen() ? 0 : setTimeout(open, 600); // after the first paint, so the screen it sits over is already there
const off = app.on((what) => { if (what === "welcome.open") open(); });
return () => { clearTimeout(timer); off(); };
},
};