feat: flutter gui#119
Merged
Merged
Conversation
…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>
…p, preset/weight enumeration
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
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
…holder to app_icon
…icona deve avere una fiamma rossa su background bianco
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.