Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions plans/adopt-node-banana-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,28 @@ Analysis of [shrimbly/node-banana](https://github.com/shrimbly/node-banana) repo
### 1. Image Annotation System (High Priority)

**What node-banana has:**

- AnnotationNode that opens a full-screen modal
- Drawing tools: Rectangle, Circle, Arrow, Freehand, Text
- Konva.js-based canvas with zoom (0.1x-5x)
- Stroke color, size, fill options
- Select/transform existing annotations

**Why adopt:**

- Essential for image editing workflows (inpainting masks, guidance)
- Common in AI image tools (ComfyUI has similar)
- Differentiates from basic prompt-to-image pipelines

**Implementation approach:**

```
src/components/AnnotationModal.tsx (new - Konva canvas modal)
src/nodes/processing/AnnotationNode.ts (new - node definition)
```

**Dependencies to add:**

```bash
bun add konva react-konva
```
Expand All @@ -77,18 +81,21 @@ bun add konva react-konva
### 2. Global Image History Panel (High Priority)

**What node-banana has:**

- Fan-layout UI showing recent 10 images
- Expandable sidebar for full history
- Drag images to canvas to create nodes
- Shows prompt, model, timestamp metadata
- Clear all functionality

**Why adopt:**

- Users often want to reuse previous generations
- Improves workflow iteration speed
- Common expectation in AI image tools

**Implementation approach:**

```
src/components/ImageHistory.tsx (new - history panel)
src/context/ImageHistoryContext.tsx (new - or add to existing context)
Expand All @@ -101,16 +108,19 @@ src/context/ImageHistoryContext.tsx (new - or add to existing context)
### 3. Multi-Select Toolbar (Medium Priority)

**What node-banana has:**

- Floating toolbar when 2+ nodes selected
- Layout actions: Stack horizontally, Stack vertically, Arrange as grid
- Group/Ungroup operations

**Why adopt:**

- Improves workflow organization
- Common UX pattern in node editors
- LiteGraph supports groups natively

**Implementation approach:**

```
src/components/MultiSelectToolbar.tsx (new)
```
Expand All @@ -124,21 +134,25 @@ src/components/MultiSelectToolbar.tsx (new)
### 4. Floating Action Bar (Medium Priority)

**What node-banana has:**

- Bottom-center floating toolbar
- Quick node creation buttons
- Run workflow options (full, from selected, selected only)
- Edge style toggle (angular/curved)

**Why adopt:**

- More discoverable than right-click menus
- Faster workflow building
- Run options are powerful for debugging

**What we already have:**

- Toolbar.tsx exists but is simpler
- Side panel for node creation

**Implementation approach:**

- Enhance existing `Toolbar.tsx` with:
- "Run from selected node" option
- "Run selected node only" option
Expand All @@ -151,15 +165,18 @@ src/components/MultiSelectToolbar.tsx (new)
### 5. Split Grid Node (Low Priority)

**What node-banana has:**

- Divides input image into grid cells
- Configurable rows × columns
- Creates multiple output handles for each cell

**Why adopt:**

- Useful for batch processing sections of image
- Enables parallel processing of image regions

**Implementation approach:**

```
src/nodes/processing/SplitGridNode.ts (new)
```
Expand All @@ -171,23 +188,28 @@ src/nodes/processing/SplitGridNode.ts (new)
### 6. State Management Upgrade to Zustand (Optional)

**What node-banana has:**

- Clean Zustand store with actions
- Selective subscriptions prevent unnecessary re-renders
- Copy/paste with internal edge preservation

**Why consider:**

- 40-70% fewer re-renders vs Context API (per research)
- Cleaner action organization
- Better for larger applications

**Current state:**

- We use React Context (`GraphContext`, `ExecutionContext`)
- Works but may have performance issues at scale

**Implementation approach:**

```bash
bun add zustand
```

```
src/store/workflowStore.ts (new - migrate from contexts)
```
Expand All @@ -212,22 +234,26 @@ src/store/workflowStore.ts (new - migrate from contexts)
## Recommended Implementation Order

### Phase 1: Quick Wins (1-2 days)

1. **Multi-Select Toolbar** - Expose LiteGraph's existing group functionality
2. **Enhanced Toolbar** - Add run options and edge style toggle

### Phase 2: Core Features (3-5 days)

3. **Global Image History** - Track and reuse generated images
4. **Annotation System** - Add Konva-based image annotation
2. **Annotation System** - Add Konva-based image annotation

### Phase 3: Nice to Have (2-3 days)

5. **Split Grid Node** - Image segmentation for batch processing
6. **Zustand Migration** - Performance optimization (optional)
2. **Zustand Migration** - Performance optimization (optional)

---

## Acceptance Criteria

### Multi-Select Toolbar

- [ ] Toolbar appears when 2+ nodes selected
- [ ] Stack horizontally arranges nodes in a row
- [ ] Stack vertically arranges nodes in a column
Expand All @@ -236,18 +262,21 @@ src/store/workflowStore.ts (new - migrate from contexts)
- [ ] Ungroup removes nodes from group

### Enhanced Toolbar

- [ ] "Run from selected" executes graph starting at selected node
- [ ] "Run selected only" executes just the selected node
- [ ] Edge style toggle switches between curved and angular connections

### Image History

- [ ] Generated images automatically added to history
- [ ] History panel shows recent 10 images with expand option
- [ ] Drag image from history creates ImageSourceNode on canvas
- [ ] Each entry shows prompt, model, timestamp
- [ ] Clear all removes history

### Annotation System

- [ ] AnnotationNode accepts image input
- [ ] Click image opens full-screen modal
- [ ] Drawing tools: Select, Rectangle, Circle, Arrow, Freehand, Text
Expand All @@ -261,7 +290,9 @@ src/store/workflowStore.ts (new - migrate from contexts)
## Technical Notes

### LiteGraph Group Support

LiteGraph already supports groups natively:

```javascript
const group = new LiteGraph.LGraphGroup("My Group")
group.pos = [100, 100]
Expand All @@ -273,27 +304,32 @@ graph.add(group)
We just need UI to expose this functionality.

### Konva.js Integration

For annotation, we'll use Konva.js (same as node-banana):

- Renders to HTML5 Canvas
- Shape primitives (Rect, Circle, Arrow, Line, Text)
- Transformer for resize/rotate
- Stage → Layer → Shapes hierarchy

### PNG Metadata (Future Enhancement)

Research shows ComfyUI embeds workflow in PNG metadata - consider adding this for workflow sharing.

---

## References

### Research Sources

- [node-banana GitHub](https://github.com/shrimbly/node-banana)
- [LiteGraph.js Groups Documentation](https://github.com/jagenjo/litegraph.js/blob/master/guides/README.md)
- [Konva.js Documentation](https://konvajs.org/docs/)
- [React Flow (xyflow) Docs](https://reactflow.dev/)
- [Zustand Documentation](https://zustand-demo.pmnd.rs/)

### Internal References

- `src/components/Toolbar.tsx` - Current toolbar implementation
- `src/context/GraphContext.tsx` - Current state management
- `src/nodes/index.ts` - Node registration
Expand Down Expand Up @@ -333,11 +369,13 @@ Original estimate: 8-12 days
## Summary

**High-value adoptions:**

1. Image History Panel - Improves iteration workflow (start here - lowest risk)
2. Annotation System - Enables image editing capabilities (highest value, highest risk)
3. Multi-Select Toolbar - Better organization UX (quick win)

**Our advantages to keep:**

- Fal.ai FLUX model integration
- Comprehensive image processing nodes
- SQLite-backed persistence
Expand Down
29 changes: 29 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { OutputPreview } from './components/OutputPreview'
import { SaveLoadDialog } from './components/SaveLoadDialog'
import { SettingsDialog } from './components/SettingsDialog'
import { PromptTemplates } from './components/PromptTemplates'
import { TemplateDialog } from './components/TemplateDialog'
import type { WorkflowTemplate } from './lib/workflow-templates'
import { WorkflowDetectedDialog } from './components/WorkflowDetectedDialog'
import { ImageModal } from './components/ImageModal'
import { ImageHistory } from './components/ImageHistory'
Expand All @@ -37,6 +39,7 @@ function AppContent() {
const [saveLoadMode, setSaveLoadMode] = useState<'save' | 'load'>('save')
const [settingsOpen, setSettingsOpen] = useState(false)
const [templatesOpen, setTemplatesOpen] = useState(false)
const [workflowTemplatesOpen, setWorkflowTemplatesOpen] = useState(false)
const [curvedConnections, setCurvedConnections] = useState(true)

// Keyboard shortcuts
Expand Down Expand Up @@ -110,6 +113,25 @@ function AppContent() {
setTemplatesOpen(true)
}, [])

// Handle open workflow templates
const handleOpenWorkflowTemplates = useCallback(() => {
setWorkflowTemplatesOpen(true)
}, [])

// Handle select workflow template
const handleSelectWorkflowTemplate = useCallback((template: WorkflowTemplate) => {
if (!graph) return

if (graph._nodes.length > 0) {
if (!confirm('Load workflow template? Any unsaved changes will be lost.')) {
return
}
}

graph.configure(template.graph)
canvas?.setDirty(true, true)
}, [graph, canvas])

// Handle toggle curved connections
const handleToggleCurvedConnections = useCallback(() => {
if (!canvas) return
Expand Down Expand Up @@ -156,6 +178,7 @@ function AppContent() {
onLoad={handleOpenLoad}
onSettings={handleOpenSettings}
onTemplates={handleOpenTemplates}
onWorkflowTemplates={handleOpenWorkflowTemplates}
onRun={execute}
onRunFromSelected={handleRunFromSelected}
onRunSelectedOnly={handleRunSelectedOnly}
Expand Down Expand Up @@ -216,6 +239,12 @@ function AppContent() {
onClose={() => setTemplatesOpen(false)}
/>

<TemplateDialog
isOpen={workflowTemplatesOpen}
onClose={() => setWorkflowTemplatesOpen(false)}
onSelect={handleSelectWorkflowTemplate}
/>

{/* Workflow detected from PNG */}
<WorkflowDetectedDialog onLoad={handleLoadWorkflowFromPng} />

Expand Down
12 changes: 11 additions & 1 deletion src/components/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface ToolbarProps {
onLoad: () => void
onSettings: () => void
onTemplates: () => void
onWorkflowTemplates: () => void
onRun: () => void
onRunFromSelected?: () => void
onRunSelectedOnly?: () => void
Expand All @@ -30,6 +31,7 @@ export function Toolbar({
onLoad,
onSettings,
onTemplates,
onWorkflowTemplates,
onRun,
onRunFromSelected,
onRunSelectedOnly,
Expand Down Expand Up @@ -97,7 +99,15 @@ export function Toolbar({
title="Prompt Templates (T)"
>
<span>📝</span>
Templates
Prompts
</button>
<button
onClick={onWorkflowTemplates}
className="flex items-center gap-1 rounded-md px-3 py-1.5 text-sm font-medium text-zinc-300 hover:bg-zinc-700 hover:text-zinc-50"
title="Workflow Templates (W)"
>
<span>🔧</span>
Workflows
</button>

<div className="mx-2 h-6 w-px bg-zinc-600" />
Expand Down