Initial release: Workflow Snapshot Manager v1.0.0
Some checks failed
Publish to ComfyUI Registry / Publish Custom Node to Registry (push) Has been cancelled
Some checks failed
Publish to ComfyUI Registry / Publish Custom Node to Registry (push) Has been cancelled
Auto-capture workflow snapshots with per-workflow hash map, promise-based restore lock, custom naming, search/filter, theme-aware CSS, toast notifications, and native confirm/prompt dialogs. Includes README with SVG/PNG assets, MIT license, and ComfyUI registry publish action. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
BIN
assets/architecture.png
Normal file
BIN
assets/architecture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
93
assets/architecture.svg
Normal file
93
assets/architecture.svg
Normal file
@@ -0,0 +1,93 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 420">
|
||||
<defs>
|
||||
<linearGradient id="abg" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#0f172a"/>
|
||||
<stop offset="100%" style="stop-color:#1e293b"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="800" height="420" rx="12" fill="url(#abg)"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="400" y="35" text-anchor="middle" font-family="system-ui, sans-serif" font-size="16" font-weight="600" fill="#94a3b8">How It Works</text>
|
||||
|
||||
<!-- Graph Edit box -->
|
||||
<rect x="40" y="60" width="160" height="70" rx="8" fill="#1e293b" stroke="#3b82f6" stroke-width="2"/>
|
||||
<text x="120" y="92" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#e2e8f0">Graph Edit</text>
|
||||
<text x="120" y="112" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#64748b">graphChanged event</text>
|
||||
|
||||
<!-- Arrow 1 -->
|
||||
<line x1="200" y1="95" x2="250" y2="95" stroke="#475569" stroke-width="2" marker-end="url(#arrowhead)"/>
|
||||
|
||||
<!-- Debounce box -->
|
||||
<rect x="250" y="60" width="160" height="70" rx="8" fill="#1e293b" stroke="#f59e0b" stroke-width="2"/>
|
||||
<text x="330" y="92" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#e2e8f0">Debounce Timer</text>
|
||||
<text x="330" y="112" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#64748b">configurable delay</text>
|
||||
|
||||
<!-- Arrow 2 -->
|
||||
<line x1="410" y1="95" x2="460" y2="95" stroke="#475569" stroke-width="2" marker-end="url(#arrowhead)"/>
|
||||
|
||||
<!-- Hash Check box -->
|
||||
<rect x="460" y="60" width="160" height="70" rx="8" fill="#1e293b" stroke="#8b5cf6" stroke-width="2"/>
|
||||
<text x="540" y="92" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#e2e8f0">Hash Check</text>
|
||||
<text x="540" y="112" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#64748b">per-workflow map</text>
|
||||
|
||||
<!-- Arrow 3 -->
|
||||
<line x1="620" y1="95" x2="640" y2="95" stroke="#475569" stroke-width="2"/>
|
||||
<line x1="640" y1="95" x2="640" y2="180" stroke="#475569" stroke-width="2"/>
|
||||
<line x1="640" y1="180" x2="620" y2="180" stroke="#475569" stroke-width="2" marker-end="url(#arrowhead-left)"/>
|
||||
|
||||
<!-- IndexedDB box -->
|
||||
<rect x="460" y="150" width="160" height="70" rx="8" fill="#1e293b" stroke="#22c55e" stroke-width="2"/>
|
||||
<text x="540" y="182" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#e2e8f0">IndexedDB</text>
|
||||
<text x="540" y="202" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#64748b">persistent storage</text>
|
||||
|
||||
<!-- Arrow 4 down to sidebar -->
|
||||
<line x1="540" y1="220" x2="540" y2="265" stroke="#475569" stroke-width="2" marker-end="url(#arrowhead)"/>
|
||||
|
||||
<!-- Sidebar Panel box (wide) -->
|
||||
<rect x="250" y="265" width="370" height="130" rx="8" fill="#1e293b" stroke="#3b82f6" stroke-width="2"/>
|
||||
<text x="435" y="295" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#e2e8f0">Sidebar Panel</text>
|
||||
|
||||
<!-- Sidebar sub-items -->
|
||||
<rect x="270" y="310" width="100" height="32" rx="5" fill="#3b82f6" opacity="0.15" stroke="#3b82f6" stroke-width="1"/>
|
||||
<text x="320" y="330" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#93c5fd">Take Snapshot</text>
|
||||
|
||||
<rect x="380" y="310" width="70" height="32" rx="5" fill="#22c55e" opacity="0.15" stroke="#22c55e" stroke-width="1"/>
|
||||
<text x="415" y="330" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#86efac">Restore</text>
|
||||
|
||||
<rect x="460" y="310" width="55" height="32" rx="5" fill="#f59e0b" opacity="0.15" stroke="#f59e0b" stroke-width="1"/>
|
||||
<text x="488" y="330" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#fcd34d">Swap</text>
|
||||
|
||||
<rect x="525" y="310" width="70" height="32" rx="5" fill="#8b5cf6" opacity="0.15" stroke="#8b5cf6" stroke-width="1"/>
|
||||
<text x="560" y="330" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#c4b5fd">Search</text>
|
||||
|
||||
<text x="435" y="375" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#64748b">toast notifications · confirm dialogs · loading states</text>
|
||||
|
||||
<!-- Restore arrow back up -->
|
||||
<rect x="40" y="180" width="160" height="70" rx="8" fill="#1e293b" stroke="#22c55e" stroke-width="2"/>
|
||||
<text x="120" y="207" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#e2e8f0">Restore / Swap</text>
|
||||
<text x="120" y="227" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#64748b">with lock guard</text>
|
||||
|
||||
<line x1="250" y1="330" x2="200" y2="265" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="6,3" marker-end="url(#arrowhead-green)"/>
|
||||
<line x1="120" y1="180" x2="120" y2="130" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="6,3" marker-end="url(#arrowhead-green)"/>
|
||||
<text x="120" y="155" text-anchor="middle" font-family="system-ui, sans-serif" font-size="10" fill="#22c55e">loadGraphData</text>
|
||||
|
||||
<!-- Manual capture arrow -->
|
||||
<line x1="320" y1="310" x2="460" y2="185" stroke="#3b82f6" stroke-width="1.5" stroke-dasharray="6,3" marker-end="url(#arrowhead-blue)"/>
|
||||
|
||||
<!-- Arrowhead markers -->
|
||||
<defs>
|
||||
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
|
||||
<polygon points="0 0, 10 3.5, 0 7" fill="#475569"/>
|
||||
</marker>
|
||||
<marker id="arrowhead-left" markerWidth="10" markerHeight="7" refX="0" refY="3.5" orient="auto-start-reverse">
|
||||
<polygon points="10 0, 0 3.5, 10 7" fill="#475569"/>
|
||||
</marker>
|
||||
<marker id="arrowhead-green" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
|
||||
<polygon points="0 0, 10 3.5, 0 7" fill="#22c55e"/>
|
||||
</marker>
|
||||
<marker id="arrowhead-blue" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
|
||||
<polygon points="0 0, 10 3.5, 0 7" fill="#3b82f6"/>
|
||||
</marker>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
BIN
assets/banner.png
Normal file
BIN
assets/banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
32
assets/banner.svg
Normal file
32
assets/banner.svg
Normal file
@@ -0,0 +1,32 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 200">
|
||||
<defs>
|
||||
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#1a1a2e"/>
|
||||
<stop offset="100%" style="stop-color:#16213e"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="accent" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style="stop-color:#3b82f6"/>
|
||||
<stop offset="100%" style="stop-color:#8b5cf6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="840" height="200" rx="12" fill="url(#bg)"/>
|
||||
<rect x="0" y="192" width="840" height="8" rx="0 0 12 12" fill="url(#accent)"/>
|
||||
|
||||
<!-- Clock/History icon -->
|
||||
<circle cx="100" cy="100" r="40" fill="none" stroke="#3b82f6" stroke-width="3"/>
|
||||
<line x1="100" y1="70" x2="100" y2="100" stroke="#3b82f6" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="100" y1="100" x2="120" y2="110" stroke="#3b82f6" stroke-width="3" stroke-linecap="round"/>
|
||||
<path d="M 65 72 A 40 40 0 0 0 60 100" fill="none" stroke="#8b5cf6" stroke-width="3" stroke-linecap="round"/>
|
||||
<polygon points="58,68 68,76 64,64" fill="#8b5cf6"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="170" y="85" font-family="system-ui, -apple-system, sans-serif" font-size="32" font-weight="700" fill="#e2e8f0">Workflow Snapshot Manager</text>
|
||||
<text x="170" y="120" font-family="system-ui, -apple-system, sans-serif" font-size="16" fill="#94a3b8">Auto-capture, browse, name, and restore workflow snapshots</text>
|
||||
<text x="170" y="150" font-family="system-ui, -apple-system, sans-serif" font-size="13" fill="#64748b">ComfyUI Extension</text>
|
||||
|
||||
<!-- Decorative dots -->
|
||||
<circle cx="750" cy="50" r="3" fill="#3b82f6" opacity="0.4"/>
|
||||
<circle cx="770" cy="70" r="2" fill="#8b5cf6" opacity="0.3"/>
|
||||
<circle cx="790" cy="45" r="2.5" fill="#22c55e" opacity="0.3"/>
|
||||
<circle cx="760" cy="90" r="2" fill="#f59e0b" opacity="0.3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/sidebar-preview.png
Normal file
BIN
assets/sidebar-preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
94
assets/sidebar-preview.svg
Normal file
94
assets/sidebar-preview.svg
Normal file
@@ -0,0 +1,94 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 520">
|
||||
<defs>
|
||||
<linearGradient id="sbg" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#1e1e1e"/>
|
||||
<stop offset="100%" style="stop-color:#252525"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Panel background -->
|
||||
<rect width="300" height="520" rx="10" fill="url(#sbg)" stroke="#333" stroke-width="1"/>
|
||||
|
||||
<!-- Header -->
|
||||
<rect x="0" y="0" width="300" height="50" rx="10 10 0 0" fill="#1a1a1a"/>
|
||||
<rect x="12" y="12" width="120" height="28" rx="5" fill="#3b82f6"/>
|
||||
<text x="72" y="31" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#fff">Take Snapshot</text>
|
||||
<text x="265" y="31" text-anchor="end" font-family="system-ui, sans-serif" font-size="11" fill="#888">5 / 50</text>
|
||||
|
||||
<!-- Separator -->
|
||||
<line x1="0" y1="50" x2="300" y2="50" stroke="#444"/>
|
||||
|
||||
<!-- Search bar -->
|
||||
<rect x="12" y="58" width="252" height="30" rx="5" fill="#2a2a2a" stroke="#444" stroke-width="1"/>
|
||||
<text x="24" y="78" font-family="system-ui, sans-serif" font-size="12" fill="#666">Filter snapshots...</text>
|
||||
<text x="252" y="78" font-family="system-ui, sans-serif" font-size="13" fill="#666"></text>
|
||||
|
||||
<!-- Separator -->
|
||||
<line x1="0" y1="96" x2="300" y2="96" stroke="#444"/>
|
||||
|
||||
<!-- Snapshot item 1 -->
|
||||
<rect x="0" y="97" width="300" height="80" fill="#1e1e1e"/>
|
||||
<text x="12" y="118" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#ddd">Checkpoint before merge</text>
|
||||
<text x="12" y="136" font-family="system-ui, sans-serif" font-size="12" fill="#ddd">2:34:15 PM</text>
|
||||
<text x="12" y="150" font-family="system-ui, sans-serif" font-size="10" fill="#777">Jan 5, 2026</text>
|
||||
<text x="12" y="164" font-family="system-ui, sans-serif" font-size="10" fill="#666">42 nodes</text>
|
||||
|
||||
<!-- Action buttons row 1 -->
|
||||
<rect x="180" y="112" width="42" height="22" rx="3" fill="#f59e0b"/>
|
||||
<text x="201" y="127" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" font-weight="500" fill="#fff">Swap</text>
|
||||
<rect x="226" y="112" width="52" height="22" rx="3" fill="#22c55e"/>
|
||||
<text x="252" y="127" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" font-weight="500" fill="#fff">Restore</text>
|
||||
<rect x="282" y="112" width="5" height="22" rx="2" fill="#444"/>
|
||||
|
||||
<line x1="0" y1="177" x2="300" y2="177" stroke="#333"/>
|
||||
|
||||
<!-- Snapshot item 2 -->
|
||||
<rect x="0" y="178" width="300" height="80" fill="#1e1e1e"/>
|
||||
<text x="12" y="199" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#ddd">Auto</text>
|
||||
<text x="12" y="217" font-family="system-ui, sans-serif" font-size="12" fill="#ddd">2:31:02 PM</text>
|
||||
<text x="12" y="231" font-family="system-ui, sans-serif" font-size="10" fill="#777">Jan 5, 2026</text>
|
||||
<text x="12" y="245" font-family="system-ui, sans-serif" font-size="10" fill="#666">40 nodes</text>
|
||||
|
||||
<rect x="180" y="193" width="42" height="22" rx="3" fill="#f59e0b"/>
|
||||
<text x="201" y="208" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" font-weight="500" fill="#fff">Swap</text>
|
||||
<rect x="226" y="193" width="52" height="22" rx="3" fill="#22c55e"/>
|
||||
<text x="252" y="208" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" font-weight="500" fill="#fff">Restore</text>
|
||||
|
||||
<line x1="0" y1="258" x2="300" y2="258" stroke="#333"/>
|
||||
|
||||
<!-- Snapshot item 3 -->
|
||||
<rect x="0" y="259" width="300" height="80" fill="#1e1e1e"/>
|
||||
<text x="12" y="280" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#ddd">Before KSampler change</text>
|
||||
<text x="12" y="298" font-family="system-ui, sans-serif" font-size="12" fill="#ddd">2:28:44 PM</text>
|
||||
<text x="12" y="312" font-family="system-ui, sans-serif" font-size="10" fill="#777">Jan 5, 2026</text>
|
||||
<text x="12" y="326" font-family="system-ui, sans-serif" font-size="10" fill="#666">38 nodes</text>
|
||||
|
||||
<rect x="180" y="274" width="42" height="22" rx="3" fill="#f59e0b"/>
|
||||
<text x="201" y="289" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" font-weight="500" fill="#fff">Swap</text>
|
||||
<rect x="226" y="274" width="52" height="22" rx="3" fill="#22c55e"/>
|
||||
<text x="252" y="289" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" font-weight="500" fill="#fff">Restore</text>
|
||||
|
||||
<line x1="0" y1="339" x2="300" y2="339" stroke="#333"/>
|
||||
|
||||
<!-- Snapshot item 4 -->
|
||||
<rect x="0" y="340" width="300" height="80" fill="#1e1e1e"/>
|
||||
<text x="12" y="361" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#ddd">Initial</text>
|
||||
<text x="12" y="379" font-family="system-ui, sans-serif" font-size="12" fill="#ddd">2:15:30 PM</text>
|
||||
<text x="12" y="393" font-family="system-ui, sans-serif" font-size="10" fill="#777">Jan 5, 2026</text>
|
||||
<text x="12" y="407" font-family="system-ui, sans-serif" font-size="10" fill="#666">35 nodes</text>
|
||||
|
||||
<rect x="180" y="355" width="42" height="22" rx="3" fill="#f59e0b"/>
|
||||
<text x="201" y="370" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" font-weight="500" fill="#fff">Swap</text>
|
||||
<rect x="226" y="355" width="52" height="22" rx="3" fill="#22c55e"/>
|
||||
<text x="252" y="370" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" font-weight="500" fill="#fff">Restore</text>
|
||||
|
||||
<line x1="0" y1="420" x2="300" y2="420" stroke="#333"/>
|
||||
|
||||
<!-- Empty space -->
|
||||
<rect x="0" y="421" width="300" height="57" fill="transparent"/>
|
||||
|
||||
<!-- Footer -->
|
||||
<line x1="0" y1="478" x2="300" y2="478" stroke="#444"/>
|
||||
<rect x="12" y="486" width="276" height="26" rx="5" fill="#555"/>
|
||||
<text x="150" y="504" text-anchor="middle" font-family="system-ui, sans-serif" font-size="12" font-weight="600" fill="#ccc">Clear All Snapshots</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
Reference in New Issue
Block a user