Commit Graph

18 Commits

Author SHA1 Message Date
b042fe4368 Fix 25+ bugs across rounds 4-8 of comprehensive code review
history_tree.py:
- Cycle protection in generate_graph() parent walk
- KeyError → .get() for malformed node data in commit() and generate_graph()
- UUID collision check with for/else raise in commit() and _migrate_legacy()
- RuntimeError → ValueError for consistent exception handling

tab_timeline_ng.py:
- Re-parent children walks to surviving ancestor for batch deletes
- Branch tip deletion re-points to parent instead of removing branch
- Cycle protection in _walk_branch_nodes and _find_branch_for_node
- Full data.clear() restore instead of merge in _restore_node
- Safe .get('data', {}) in restore and preview
- Reset stale branch selection after node deletion
- json.dumps for safe JS string escaping in graphviz renderer

tab_batch_ng.py:
- NaN/inf rejection in dict_number with math.isfinite()
- _safe_int used in recalc_vace, update_mode_label, frame_to_skip
- Uncaught ValueError from htree.commit() caught with user notification

tab_comfy_ng.py:
- asyncio.get_event_loop() → get_running_loop()

utils.py:
- Atomic writes for save_config and save_snippets
- save_config extra_data can't override explicit last_dir/favorites

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:23:14 +01:00
04b9ed0e27 Fix 4 bugs: SQL conflict handling, HTML escaping, backup cap, safe int cast
- sync_to_db: use ON CONFLICT for duplicate sequence numbers
- history_tree: html.escape() for Graphviz DOT labels
- tab_timeline_ng: cap history_tree_backup to 10 entries
- tab_batch_ng: add _safe_int() helper for VACE settings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:03:13 +01:00
c15bec98ce Add SQLite project database + ComfyUI connector nodes
- db.py: ProjectDB class with SQLite schema (projects, data_files,
  sequences, history_trees), WAL mode, CRUD, import, and query helpers
- api_routes.py: REST API endpoints on NiceGUI/FastAPI for ComfyUI
  to query project data over the network
- project_loader.py: ComfyUI nodes (ProjectLoaderDynamic, Standard,
  VACE, LoRA) that fetch data from NiceGUI REST API via HTTP
- web/project_dynamic.js: Frontend JS for dynamic project loader node
- tab_projects_ng.py: Projects management tab in NiceGUI UI
- state.py: Added db, current_project, db_enabled fields
- main.py: DB init, API route registration, projects tab
- utils.py: sync_to_db() dual-write helper
- tab_batch_ng.py, tab_raw_ng.py, tab_timeline_ng.py: dual-write
  sync calls after save_json when project DB is enabled
- __init__.py: Merged project node class mappings
- tests/test_db.py: 30 tests for database layer
- tests/test_project_loader.py: 17 tests for ComfyUI connector nodes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:12:05 +01:00
24f9b7d955 Fix graph interactivity: use querySelector instead of NiceGUI DOM ID
The c{id} DOM ID pattern was wrong. Use document.querySelector with
the timeline-graph class instead, with retries until g.node elements
are present in the DOM.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:27:00 +01:00
f2980a9f94 Fix graph: NiceGUI blocks script tags in ui.html()
Move JS back to ui.run_javascript() with retry-based DOM lookup
using NiceGUI's element ID (c{id}). CSS stays inline via style tag.
Retries up to 10 times at 50ms intervals to handle Vue async render.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:20:32 +01:00
4e3ff63f6a Fix graph interactivity: embed JS/CSS inline in HTML
Previous approach used ui.run_javascript with getElement() which
failed due to Vue rendering timing. Now embeds the script and style
directly inside the HTML content so there are no DOM lookup or
timing issues — the script runs inline when parsed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:19:26 +01:00
6e01cab5cd Fix graph interactivity: use NiceGUI element ref and requestAnimationFrame
The click handlers weren't attaching because getElementById couldn't
find the container — Python's id() generated IDs that didn't survive
NiceGUI's DOM rendering. Now uses getElement() with the NiceGUI
element ID and defers JS via requestAnimationFrame to ensure the
DOM is ready.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:15:56 +01:00
16ed81f0db Fix tiny graph: keep SVG natural size, scroll on overflow
Stop replacing the SVG's width/height attributes — this was shrinking
the graph to fit the container. Instead keep graphviz's native pt
dimensions and let the scroll container handle overflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:14:25 +01:00
d98cee8015 Fix timeline graph height: remove invalid SVG height="auto"
Drop the fixed height attribute entirely instead of setting it to
"auto", which SVGs don't support. The viewBox attribute handles
proportional scaling when only width="100%" is set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:11:03 +01:00
2ebf3a4fcd Interactive timeline graph: click nodes to select in node manager
Add click-to-select functionality to the graphviz SVG timeline graph.
Clicking a node highlights it with an amber border, auto-switches the
branch selector, and updates the node manager panel. The SVG is now
responsive (100% width, scroll container) instead of fixed-size.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:06:13 +01:00
8911323832 Branch-grouped navigation for timeline node manager
Replace flat dropdown with branch selector showing node counts,
scrollable node list with HEAD/tip badges, and inline actions panel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:15:56 +01:00
39a1b98924 Fix history snapshot corruption, missing dir crash, stale batch delete
- Deep-copy node data on restore to prevent edits from mutating
  stored history snapshots
- Guard glob calls against non-existent current_dir
- Read current selection at delete time instead of using stale
  render-time capture

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 18:11:11 +01:00
710a8407d2 Overhaul UI: new color palette, spacing, and visual hierarchy
Replace red accent with amber, add Inter font, introduce 4-level depth
palette via CSS variables, expand padding/gaps, wrap sidebar and content
sections in cards, add section/subsection header typography classes, and
style scrollbars for dark theme. Pure visual changes — no functional or
data-flow modifications.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 17:27:02 +01:00
b0125133f1 Refactor for readability: declare state attrs, extract helpers, deduplicate
- Declare dynamic attributes (_render_main, _load_file, etc.) in AppState
  dataclass instead of monkey-patching at runtime
- Extract max_main_seq_number() and FRAME_TO_SKIP_DEFAULT in batch tab
- Add commit() closure in _render_sequence_card to deduplicate save/notify/refresh
- Add default param to dict_number(), replace hand-rolled CFG/VACE/custom bindings
- Extract _delete_nodes() helper in timeline to deduplicate single/batch delete
- Split 230-line render_timeline refreshable into 4 focused section helpers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 16:56:40 +01:00
b6f31786c6 Style NiceGUI to closely match Streamlit dark theme
Exact Streamlit colors: #0E1117 background, #262730 secondary,
#FF4B4B primary accent, #FAFAFA text, rgba borders. Match input
styling, border-radius, sidebar width, tab indicators, and
separator colors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 14:09:00 +01:00
79a47e034e Switch to dark theme to match original Streamlit look
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:33:25 +01:00
d5fbfe765e Fix UI readability and clipping issues
Add page/sidebar background contrast, wrap action button rows,
ensure dark text in inputs, and improve timeline card highlight colors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:30:44 +01:00
f6d5ebfe34 Migrate web UI from Streamlit to NiceGUI
Replace the Streamlit-based UI (app.py + tab_*.py) with an event-driven
NiceGUI implementation. This eliminates 135 session_state accesses,
35 st.rerun() calls, and the ui_reset_token hack. Key changes:

- Add main.py as NiceGUI entry point with sidebar, tabs, and file navigation
- Add state.py with AppState dataclass replacing st.session_state
- Add tab_batch_ng.py (batch processor with blur-binding, VACE calc)
- Add tab_timeline_ng.py (history tree with graphviz, batch delete)
- Add tab_raw_ng.py (raw JSON editor)
- Add tab_comfy_ng.py (ComfyUI monitor with polling timer)
- Remove Streamlit dependency from utils.py (st.error → logger.error)
- Remove Streamlit mock from tests/test_utils.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 10:53:47 +01:00