Skip to content

feat: flutter gui#119

Merged
newfla merged 65 commits into
mainfrom
feat_flutter_gui
Jun 24, 2026
Merged

feat: flutter gui#119
newfla merged 65 commits into
mainfrom
feat_flutter_gui

Conversation

@newfla

@newfla newfla commented Jun 23, 2026

Copy link
Copy Markdown
Owner

No description provided.

newfla and others added 30 commits June 18, 2026 14:16
…placeholders

- Create gui/ Flutter desktop project (macOS, Linux, Windows)
- Add dependencies: yaru, flutter_riverpod, multi_split_view, file_picker, path_provider, uuid
- Create feature-based directory structure per D-07
- Add gui/rust/.gitkeep placeholder for Phase 2 bridge crate (SETUP-02)
- Add gui/assets/placeholder.png for mock generation output (MOCK-03)
- Replace generated counter app with ProviderScope + DiffusionRsApp entry point
- Override root .gitignore *.png for gui/assets/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… progress bar

- Create DiffusionRsApp with YaruTheme builder pattern (yaru.theme/darkTheme)
- Add MultiSplitView two-panel layout (40/60 split, min 320/280px) with DragHandle
- Add SegmentedButton theme toggle (Light/System/Dark) in AppBar
- Create ThemeModeNotifier with default ThemeMode.system (UI-03, UI-04, UI-05)
- Create ProgressEvent data class mirroring Rust Progress struct shape
- Create GenerationService abstract interface (Phase 1/2 seam per D-08)
- Create MockGenerationService with async* generator: 20 steps, 250ms each (MOCK-01, MOCK-02)
- Create GenerationNotifier with idle/generating/complete/error state machine
- Create ParamsPanel with Generate button (disabled during generation, text: Generating...)
- Create OutputPanel with 4 states: idle, spinner, progress bar + step counter, complete + save

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Preset catalog with all 41 presets mirroring src/preset.rs with weight mappings
- ParamsNotifier managing all 14 active form fields via Riverpod
- Model section with preset/weights dropdowns (weights disabled with N/A for no-weight presets)
- Generation section with prompt, negative prompt, steps, width/height, seed+dice
- Post-processing section with preview, upscaler, conditional scale factor
- Advanced section with cache, FORM-15 warning, token with visibility toggle, low VRAM switch
- SeedField widget with dice button resetting to -1
…yout and keyboard shortcut

- ParamsPanel now renders 4 collapsible YaruExpansionPanel sections (Model+Generation expanded, Post-processing+Advanced collapsed per D-03)
- Generate button pinned at bottom, disabled when prompt empty or generating
- Button text toggles between "Generate" and "Generating..." based on state
- All form fields disable during generation and re-enable on completion (GEN-02, GEN-05)
- Added CallbackShortcuts with Cmd+Enter (macOS) and Ctrl+Enter (Linux/Windows) for GEN-06
- Focus(autofocus: true) wraps layout to maintain focus after divider interaction
…fecycle cleanup

- TempDirectoryManager singleton creates session-specific temp dir on startup (TMP-01)
- Stale session directories from previous crashes cleaned on startup (TMP-03)
- Current session directory cleaned on normal app exit via AppLifecycleListener (TMP-02)
- Riverpod provider exposes TempDirectoryManager for cross-feature access (D-09)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nackBar

- OutputNotifier.saveImage() opens OS-native file picker, copies image, shows SnackBar (OUT-04, OUT-05, D-14)
- Default save filename: {preset}_{seed}_{timestamp}.png (OUT-05)
- Initial directory targets system Pictures folder (OUT-06)
- file_picker call wrapped in try/catch for Linux compatibility (Pitfall 4)
- Output panel complete state wires Save button to outputProvider.saveImage()
- Save button remains visible after saving for re-save to different location
- GenerationNotifier writes placeholder to TempDirectoryManager session path on completion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tional hints

- Add com.apple.security.files.user-selected.read-write to macOS entitlements
  (fixes PlatformException entitlement_required_write on file_picker save)
- Move Preview dropdown to Generation section; Upscaler+scale to Advanced
- Remove now-empty Post-processing section (3 sections: Model, Generation, Advanced)
- Weights dropdown: null = "Default" label, auto-selected on preset change;
  explicit weights available below
- Steps, Width, Height, Negative prompt: hintText "Default" (optional, backend uses model defaults)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The dice IconButton was calling setSeed(-1), which is the default value,
so no visible change occurred when seed was already -1. Now generates a
random positive integer (nextInt(0x7FFFFFFF)) so the field always updates.

UAT gap diagnosed and closed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two plans covering the full FRB integration: Plan 02-01 scaffolds
gui/rust/ crate with all Rust-side bridge functions, Plan 02-02
handles Dart-side codegen integration, RustGenerationService, and
UI updates for live preview and error handling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Create gui/rust/ as isolated Cargo crate with path dep on diffusion-rs
- Add flutter_rust_bridge 2.12.0, anyhow, strum dependencies
- Set panic=abort in release profile (D-13/FRB-07)
- Create GuiParams DTO with 17 FRB-compatible primitive fields (D-11/FRB-04)
- Create frb_generated.rs stub with placeholder StreamSink for pre-codegen compilation
- Change Progress struct fields step, steps, time to pub (D-10/FRB-05)
- Remove #[allow(unused)] from Progress struct
- Implement get_presets() returning all PresetDiscriminants as Vec<String> (FRB-01)
- Implement get_weights_for_preset() with match arms for all weight-bearing presets (FRB-02)
- Implement generate_image_stream() with two-thread relay pattern (FRB-03):
  - Worker thread runs gen_img_with_progress (blocking)
  - Relay thread bridges mpsc::Receiver<Progress> to StreamSink<GuiProgressEvent>
  - Reads preview PNG bytes from disk after each progress event (D-03)
  - Emits final image bytes on completion
- Wrap all FFI work in catch_unwind for defense-in-depth (D-07/FRB-06)
- Implement bridge::map_preset with from_str validation and descriptive errors (T-02-01)
- Implement bridge::build_configs mapping GuiParams to PresetBuilder/ConfigBuilder/ModelConfigBuilder
- Support cache modes, upscaler variants, low_vram, preview config (D-02)
- Summary: gui/rust/ crate with FRB functions, GuiParams DTO, Progress pub fields
- 2 tasks, 7 files, 8min duration
- Requirements completed: FRB-01 through FRB-07
newfla and others added 28 commits June 21, 2026 20:14
gaps_found: SC-1 (preset UI wiring), SC-4 (FRB codegen stubs), FRB-06 (catch_unwind partial), cargokit analyze

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…reset UI wiring

Gap 1 (SC-1): model_section.dart and params_provider.dart now call
getPresets() and getWeightsForPreset() from FRB bindings instead of
PresetCatalog hardcoded lists. Deleted obsolete api/api.dart stub that
conflicted with real codegen output.

Gap 2: Replaced stub FRB bindings with output from actual
flutter_rust_bridge_codegen generate run (api.dart, gui_params.dart,
frb_generated.dart/.io.dart/.web.dart, frb_generated.rs).

Gap 3 (FRB-06): get_presets() and get_weights_for_preset() now wrapped
in catch_unwind; private _get_weights_for_preset() helper avoids
AssertUnwindSafe capture of non-UnwindSafe closure.

Also adds PresetDefaults/getDefaults() to PresetCatalog (steps/width/
height UI hints) and preset-change controller sync in GenerationSection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Re-verified VERIFICATION.md: status gaps_found → passed (9/9).
Updated STATE.md: status executing → complete, 2/2 phases done.

Gap closure summary:
- Gap 1 (SC-1): model_section + params_provider now call getPresets()/getWeightsForPreset()
- Gap 2 (codegen): real FRB 2.12.0 output replaces manual stubs
- Gap 3 (FRB-06): catch_unwind on all 3 FFI entry points
- Gap 4 (Cargokit): override — third-party vendored tool, flutter analyze lib/ passes clean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename Cargo package from 'diffusion-rs-gui' to 'rust_lib_diffusion_rs_gui'
  so cargokit produces librust_lib_diffusion_rs_gui.a matching the pod target name
- Add -lc++ and -framework Accelerate to podspec OTHER_LDFLAGS
  to resolve C++ stdlib and BLAS/vDSP symbols from stable-diffusion.cpp

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…_rs_gui

After renaming the Cargo package, the FRB codegen stem must match.
Re-ran flutter_rust_bridge_codegen to update frb_generated.dart and api.dart.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Safety checkpoint: archive ROADMAP, REQUIREMENTS, MILESTONES, STATE, PROJECT,
RETROSPECTIVE before removing REQUIREMENTS.md for next milestone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fresh start for next milestone. v1.0 requirements archived to
.planning/milestones/v1.0-REQUIREMENTS.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Prerequisites section with Flutter SDK, Rust, Xcode, CocoaPods, CMake versions
- Add macOS build and run steps (clone, pub get, pod install, flutter run/build)
- Document FRB codegen caveat (pre-generated bindings, when to regenerate)
- Add Project Structure table mapping paths to purpose
- Add Key Dependencies table with versions and descriptions
- Remove all Flutter boilerplate content
… project overview

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Updates MaterialApp title, AppBar text, and macOS PRODUCT_NAME from
'diffusion-rs' / 'diffusion_rs_gui' to 'DiffusionRS GUI'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add monotonic generationId to GenerationState and thread it through all
state transitions. Use ValueKey(generationId) on Image.memory to force
Flutter to dispose the old image element when a new generation starts,
preventing the previous generation's final frame from persisting via
gaplessPlayback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ayback

Previous attempt placed `key:` before the positional bytes argument (invalid
Dart syntax), causing silent hot-reload rejection. Fix: move ValueKey to the
Flexible wrapper so Flutter's canUpdate() sees a key change when generationId
increments, forcing full subtree disposal. Drop gaplessPlayback: true so no
old frame can be retained on element reuse.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Rust API emits multiple isComplete events (one per phase). Intermediate
complete events arrive with previewImage=null → imagePath=null in state.
Previously the Save button was always enabled in complete state, making it
appear active with no image behind it. Now onPressed is null when imagePath
is null, which disables the button visually until the final image is available.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…phases

The Rust API emits isComplete=true for each generation phase. Intermediate
complete events arrive with imagePath=null, briefly re-enabling the Generate
button before the final image is ready. Fix: treat complete+imagePath=null
as still-generating in both the button's onPressed guard (params_panel.dart)
and the keyboard shortcut handler (app.dart).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… gui flutter. l'icona deve avere una fiamma rossa su background bianco
- Generate stylized red/orange/yellow flame icon at 1024x1024
- Add macOS icons at 7 sizes (16-1024px) in AppIcon.appiconset
- Replace Windows app_icon.ico with flame icon (6 embedded sizes)
- Add high-res source icon at gui/assets/app_icon.png
- Update gui/macos/.gitignore to allow AppIcon PNG tracking
- Remove placeholder.png from gui/assets
…icona deve avere una fiamma rossa su background bianco
@newfla newfla merged commit cec9539 into main Jun 24, 2026
16 checks passed
@newfla newfla mentioned this pull request Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant