From e82e7f40cc6fa4fa22224162f0751b30ff4a8cab Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Sun, 8 Nov 2026 17:21:44 +0200 Subject: [PATCH] Tour: Generate row, Sampler, + Add and Render steps for the moved buttons; viewport script walks the tour; how-to doc matches the new header Co-Authored-By: Claude Sonnet 5.5 --- app/e2e/viewports.mjs | 19 +++++++++++++++++++ app/ui/features/tour/index.js | 7 +++++-- docs/how-to-start.md | 25 +++++++++++++------------ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/app/e2e/viewports.mjs b/app/e2e/viewports.mjs index c36ae3ff..d19e3517 100644 --- a/app/e2e/viewports.mjs +++ b/app/e2e/viewports.mjs @@ -34,6 +34,24 @@ async function fakeRunning(page) { }); } +// Help > Start tour, then Next to the end: every callout must find its target (a step whose target is missing is skipped, so the numbers would jump). +async function walkTour(page, note) { + await page.getByRole("button", { name: "Help", exact: true }).click(); + await page.getByText("Start tour").click(); + const seen = []; + for (let i = 0; i < 30; i++) { + await page.waitForTimeout(150); + const head = await page.evaluate(() => (document.querySelector(".cx-popover .cx-label, .cx-popover") || {}).textContent || ""); + const m = head.match(/(\d+) \/ (\d+)/); + if (!m) break; + seen.push(Number(m[1])); + const done = Number(m[1]) === Number(m[2]); + await page.getByRole("button", { name: done ? "Done" : "Next", exact: true }).click(); + if (done) break; + } + if (!seen.length || seen.some((n, i) => n !== i + 1) || seen.length < 5) note(`the tour skipped a step or did not run (saw ${seen.join(",") || "nothing"})`); +} + const { server, url } = await start(0); const problems = []; let ran = 0; @@ -53,6 +71,7 @@ for (const name of wanted) { if (!(await page.getByText(/Step 4\/5/).count())) note("the running render's progress is not shown"); if (process.env.FUNUI_SHOTS) await page.screenshot({ path: `${process.env.FUNUI_SHOTS}/running-${name}-${w}x${h}.png` }); } + if (!running) await walkTour(page, note); const main = await page.evaluate(inspect); if (main.over[0] > 0 || main.over[1] > 0) note(`page overflows by ${main.over}`); main.lanes.forEach((m) => note(m)); diff --git a/app/ui/features/tour/index.js b/app/ui/features/tour/index.js index 04a19538..b44846d4 100644 --- a/app/ui/features/tour/index.js +++ b/app/ui/features/tour/index.js @@ -4,13 +4,16 @@ import { composer as c } from "../../composer/composer.js"; // Each step points at a part of the screen by name: the menu bar, a zone, the page body, or a button by its label. const STEPS = [ - { at: "menubar", side: "bottom", title: "Everything starts here", text: "The menu bar above has File, Edit, View and Help. Settings (top right) holds the models, the engine and the updates." }, + { at: "menubar", side: "bottom", title: "Everything starts here", text: "The menu bar above has File, Edit, View and Help. Settings, next to Help, holds the models, the engine and the updates." }, { at: "zone:0", side: "right", title: "Assets", text: "Your projects and the media bin. Drop images, clips and audio here; right-click a tile to use it as a reference, rename or delete it." }, { at: "zone:1", side: "left", title: "Preview", text: "The monitor plays the cut wherever the playhead is. Save frame puts the current picture in the media bin." }, { at: "zone:2", side: "left", title: "Properties", text: "Project settings (size, length, postfix) and the picked scene's prompt, source, references and length." }, { at: "zone:3", side: "top", title: "Timeline", text: "One clip per scene. Drag the edges to trim, press S to split, Space to play. Lanes below carry separated sound." }, + { at: "button:▶ Generate", side: "top", title: "Generate", text: "Makes every scene on the timeline, except left-out scenes and video clips; an earlier render of a scene stays as a take. Beside it: Selected makes only the picked scenes, Takes ×N makes the picked scene N times with only the seed changing, and Rate scene… lets FunUI learn your taste (Upscale and Interpolate appear there too once you switch them on). “Generate this scene” in Properties makes just the picked one." }, + { at: "button:⏱ Sampler", side: "top", title: "Sampler", text: "Steps, sampler, scheduler, seed and the common switches, one click from the timeline. While a run goes, the step count shows to its left." }, { at: "button:◆ Composer", side: "top", title: "Composer", text: "Write the whole story in one box, cut at the cut word; keep templates, $variables and shortcuts; chat with the prompt enhancer." }, - { at: "button:▶ Generate", side: "top", title: "Generate", text: "Makes every scene on the timeline, except left-out scenes and video clips; an earlier render of a scene stays as a take. “Generate this scene” in Properties makes just the picked one; rate a result so FunUI learns your taste." }, + { at: "button:+ Add", side: "top", title: "Add and edit", text: "+ Add opens one menu: a scene, a video clip or audio track from the bin, an effect or transition, a text or picture overlay. Next to it: Split, Remove, Export, Save to media bin and Separate audio." }, + { at: "button:⧉ Render", side: "top", title: "Render", text: "Joins the whole timeline into one file, with the separated sound mixed in. Export downloads just the picked clip." }, { at: "main", side: "bottom", title: "FAQ", text: "Nothing happens? Check the ComfyUI chip at the top right and the Log window. Wrong look? Settings ▸ Appearance. Lost a layout? View ▸ Reset Layout. Lost a project? File ▸ Open recent. That is the tour: Help ▸ Start tour runs it again." }, ]; diff --git a/docs/how-to-start.md b/docs/how-to-start.md index 000f4a2d..3209a487 100644 --- a/docs/how-to-start.md +++ b/docs/how-to-start.md @@ -18,20 +18,20 @@ Start ComfyUI as usual and open `/fun/` on the same address, for example `http:/ ## 3. Make a project -**File ▸ Project Setup Wizard.** Give the project a name and pick **Start from**: the pipeline of the model you will use. Say yes to the tour if you want a walk through the screen (Help ▸ Start tour runs it again). +**File ▸ Project Setup Wizard** has three steps (Back and Continue sit in its footer): choose your look, name the project and pick **Start from** (the pipeline of the model you will use), then say yes to the tour if you want a walk through the screen (Help ▸ Start tour runs it again). -| Model | State | +| Start from | State | |---|---| -| MiniMax H3 | The model FunUI is built and tested around. | -| Stable Diffusion 1.5 | Experimental. | -| LTX 2.3 | Tested on a real model: Video to Video (direct), Image to Video (start from References), LoRAs, Noise merging. Other enhancements are not tested on LTX yet; please report problems in [Issues](https://github.com/digital-garbage/FunUI/issues). | +| MiniMax H3 · Reference to Video, MiniMax H3 · Fast & Simple R2V | The model FunUI is built and tested around. | +| Stable Diffusion 1.5 · Text to Image | Experimental. | +| LTX 2.3 · Image to Video (from References), LTX 2.3 · Video to Video (direct) | Tested on a real model, with LoRAs and Noise merging. Other enhancements are not tested on LTX yet; please report problems in [Issues](https://github.com/digital-garbage/FunUI/issues). | ## 4. Pick your files The model's pipeline starts empty: it needs your files. -1. Open **Settings ▸ Ready to generate?**. It checks the machine: ffmpeg, GPU, model folders, node packs. -2. Open **Settings ▸ Models & Pipeline** and choose a file in each card marked with an orange dot (diffusion model, text encoder, VAE, and so on). Generate names the first thing still missing. +1. Open **Settings** (in the menu bar, next to Help) and then **Ready to generate?**. It checks the machine: ffmpeg, GPU, model folders, node packs. +2. Open **Settings ▸ Models & Pipeline** and choose a file in each card marked with an orange dot (diffusion model, text encoder, VAE, and so on). The page says how many cards still need something and says "Every slot is filled" when you are ready. Put model files where ComfyUI expects them (`models/diffusion_models`, `models/text_encoders`, `models/vae`, `models/loras`). @@ -39,23 +39,24 @@ Put model files where ComfyUI expects them (`models/diffusion_models`, `models/t ## 5. Write the story -Click **Composer** and write all scenes in one box, separated by the cut word (see the Cuts tab). Each piece becomes one clip on the timeline. Composer also keeps `$variables`, templates and shortcuts, and has an optional **Enhance** tab: a language model rewrites each finished prompt. On H3, pick a chat encoder (for example Gemma 4) under Enhance ▸ Encoder, because H3's own encoder cannot write prose. Leave Encoder family at its default unless your encoder belongs to another family (Gemma 4 worked with the default). +Click **◆ Composer** (right end of the timeline header) and write all scenes in one box, separated by the cut word (see the Cuts tab). Each piece becomes one clip on the timeline. Composer also keeps `$variables`, templates and shortcuts, and has an optional **Enhance** tab: a language model rewrites each finished prompt. On H3, pick a chat encoder (for example Gemma 4) under Enhance ▸ Encoder, because H3's own encoder cannot write prose. Leave Encoder family at its default unless your encoder belongs to another family (Gemma 4 worked with the default). ## 6. Generate -- **▶ Generate** makes every scene on the timeline (not left-out scenes or video clips). An earlier render of a scene stays as a take. -- **Selected** makes only the picked scene. **Takes ×N** makes the same scene several times, differing only by seed. +- **▶ Generate** (timeline header) makes every scene on the timeline (not left-out scenes or video clips). An earlier render of a scene stays as a take. +- **Selected** makes only the picked scene. **Takes ×N…** makes the same scene several times, differing only by seed. +- **⏱ Sampler** (right end of the same header) holds steps, sampler, scheduler, seed and the common switches. While a run goes, the step count shows to its left. - No picture needed: on H3, a scene with no source image is generated from text alone. Watch the Log window if nothing happens: any module that fails says why there, and the rest of the run goes on without it. ## 7. Cut, render, export -Trim and split clips on the timeline. **⧉ Render** joins the timeline into one file; **⤓ Export** downloads the picked clip (picture only: a clip whose sound was separated is silent there, Render mixes it). +Trim and split clips on the timeline. The **+ Add** menu in the timeline toolbar adds a scene, a video clip or audio track from the bin, an effect or transition, or a text or picture overlay. **⧉ Render** (timeline header) joins the timeline into one file; **⤓ Export** (toolbar) downloads the picked clip (picture only: a clip whose sound was separated is silent there, Render mixes it). ## 8. Teach it your taste (optional) -Rate a result with **Rate scene…** (liked, disliked, bad image, bad composition). Set a **Taste key** (the ⚠ chip on the timeline points to it: **Settings ▸ Engine ▸ System**) so ratings are remembered. **Settings ▸ Refinement & Taste** lists, exports and deletes keys. Modules that learn from ratings start acting once they have enough ratings (a few liked clips for some, ten or more rated clips for others; some also need disliked ones) and say so when they need more. +Rate a result with **Rate scene…** in the timeline header, next to **Takes ×N…** (liked, disliked, bad image, bad composition). **Upscale** and **Interpolate** appear beside it once you set them to "When I press" in their settings. Set a **Taste key** (the ⚠ chip on the timeline points to it: **Settings ▸ Engine ▸ System**) so ratings are remembered. **Settings ▸ Refinement & Taste** lists, exports and deletes keys. Modules that learn from ratings start acting once they have enough ratings (a few liked clips for some, ten or more rated clips for others; some also need disliked ones) and say so when they need more. ## 9. Features marked experimental