Compare commits

...

774 Commits

Author SHA1 Message Date
github-actions
69366e5e91 Update locales [skip ci] 2025-02-28 22:11:52 +00:00
bymyself
5facc77529 move to expandable advanced tools 2025-02-28 15:08:07 -07:00
bymyself
289cbe428e move validation to form 2025-02-28 15:08:07 -07:00
github-actions
96e39b4c85 Update locales [skip ci] 2025-02-28 00:53:08 +00:00
bymyself
590280dd92 node model metadata edit popover 2025-02-27 17:41:36 -07:00
Chenlei Hu
cb4a5b88fc Remove magic 10% scale on numeric widget step (#2759) 2025-02-27 16:56:22 -05:00
Chenlei Hu
b685eba689 Update litegraph 0.8.99 (#2761) 2025-02-27 16:30:17 -05:00
bymyself
8775c1d930 Add video_upload to combo input schema (#2760) 2025-02-27 16:22:14 -05:00
Chenlei Hu
1dab413473 [Schema] Expose input options types (#2757) 2025-02-27 14:22:42 -05:00
Chenlei Hu
1d95d639e9 [Refactor] Extract nodeDefSchema from apiSchema (#2756) 2025-02-27 13:39:23 -05:00
bymyself
e380d792c7 Support models metadata in node properties (#2754) 2025-02-27 13:25:16 -05:00
bymyself
0910d485fd [Test] Fix flaky optional combo test (#2755) 2025-02-27 11:13:38 -07:00
Chenlei Hu
cdf42d5ad7 [Refactor] Move zod schemas to schemas/ folder (#2753) 2025-02-27 13:05:01 -05:00
Chenlei Hu
96f02dbf80 [Refactor] Use util.clone in mergeIfValid (#2752) 2025-02-27 11:47:56 -05:00
bymyself
f9157ee05f Update workflow schema to include node pack ID and version (#2751) 2025-02-27 11:15:31 -05:00
Terry Jia
cb6f2e4398 [3d] fix preview camera not sync up issue (#2747) 2025-02-27 08:42:07 -05:00
bymyself
71f3f720bf Lower floor on max history items setting (#2748) 2025-02-27 08:41:50 -05:00
Chenlei Hu
d1fead298f [Revert] Restrict applyToGraph to PrimitiveNode (#2746) 2025-02-26 22:29:13 -05:00
Chenlei Hu
0bc66965f0 [Cleanup] Remove LiteGraph global type declarations (#2745) 2025-02-26 21:50:41 -05:00
Terry Jia
e843f53799 [3d] temp fix preview camera not sync up (#2743) 2025-02-26 21:39:19 -05:00
Chenlei Hu
0259befcdd 1.11.4 (#2744) 2025-02-26 20:20:53 -05:00
Chenlei Hu
3662938080 Update litegraph 0.8.98 (#2742) 2025-02-26 20:10:10 -05:00
Chenlei Hu
ab9c65f28b Type widgetInputs (#2741) 2025-02-26 18:01:56 -05:00
Chenlei Hu
bdfa2efa50 [BugFix] Remove outputs.animated in queueStore (#2740) 2025-02-26 16:04:01 -05:00
Silver
1c408d2f6a replace colorSelect.png cursor (#2738) 2025-02-26 14:13:50 -05:00
bymyself
76818b54e6 Fix widget label extraction (#2737) 2025-02-26 13:44:05 -05:00
Chenlei Hu
2d41aed051 [BugFix] Properly update color button color on first selection (#2736) 2025-02-26 13:43:09 -05:00
bymyself
237b895e8b Add thumbnails for workflow templates (#2729)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-26 10:39:27 -05:00
bymyself
e2087d2a7b Add node to default/tutorial workflow with link to getting started page of docs (#2734) 2025-02-26 10:35:40 -05:00
bymyself
74e8852958 Fix combo values from optional inputs not changed when refreshing (#2733) 2025-02-26 10:35:22 -05:00
Chenlei Hu
3c196f8f97 1.11.3 (#2731) 2025-02-25 21:40:17 -05:00
Chenlei Hu
6dbdde6491 Update litegraph 0.8.97 (#2730) 2025-02-25 21:40:07 -05:00
Chenlei Hu
a784abef0d Type INodeOutputSlot widget hack on PrimitiveNode (#2728) 2025-02-25 19:34:23 -05:00
filtered
c20ea0c523 [TS] Add null check in graph to prompt (#2727) 2025-02-25 13:39:46 -05:00
filtered
101e8dea11 [TS] Update type to match strict Litegraph (#2726) 2025-02-26 04:00:55 +11:00
Chenlei Hu
156013aa24 [Reland] Restrict applyToGraph to PrimitiveNode (#2724) 2025-02-25 10:54:21 -05:00
Comfy Org PR Bot
1a7145fbc9 Update locales for node definitions (#2723)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-02-25 10:24:09 -05:00
Terry Jia
956b9609fd [3d] disable depth mode (#2720) 2025-02-25 10:05:10 -05:00
filtered
51c16a4f56 [TS] Add null check in paste handler (#2722) 2025-02-25 22:45:37 +11:00
filtered
417a089186 [Refactor] Use more explicit types in usePaste (#2721) 2025-02-25 21:52:47 +11:00
Chenlei Hu
f5cec41130 [i18n] Translate button widget labels (#2719)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-24 20:31:14 -05:00
Chenlei Hu
d3dda14267 Update litegraph 0.8.95 (#2718) 2025-02-24 19:48:44 -05:00
Chenlei Hu
3a63b9eb56 1.11.2 (#2717) 2025-02-24 18:41:10 -05:00
bymyself
aabd409bf7 Add copy paste audio files onto LoadAudio nodes or canvas (#2716) 2025-02-24 16:37:03 -05:00
Terry Jia
7f98342492 [3d] some general improvement (#2714) 2025-02-24 14:57:36 -05:00
Chenlei Hu
1a9d6aca7d [nit] Fix import path (#2715) 2025-02-24 14:57:20 -05:00
bymyself
15785fea68 Add drag and drop audio files onto LoadAudio nodes (#2710)
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-02-24 14:05:44 -05:00
bymyself
d340e634a8 [Refactor] Move node composables to subfolder (#2712) 2025-02-24 14:04:16 -05:00
bymyself
9cb993cd3d [CodeHealth] Remove unused var (#2713) 2025-02-24 14:03:52 -05:00
Chenlei Hu
2ac67f2dd0 Add tooltip show-delay in action bar (#2709) 2025-02-24 11:22:26 -05:00
Chenlei Hu
96ba2b4564 Allow quitting instant queue mode with the stop button (#2708) 2025-02-24 11:20:34 -05:00
bymyself
05bd64820d Fix node videos when preview format setting is set (#2706) 2025-02-24 10:49:45 -05:00
bymyself
a35071fcb2 Add previewMediaType flag for simpler node preview rendering (#2694)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-02-24 10:48:55 -05:00
bymyself
37d4cc974b Cleanup node's file input elements on node removal (#2703)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-02-24 10:45:27 -05:00
bymyself
81102604f5 Type addDOMWidget (#2705) 2025-02-24 10:32:43 -05:00
filtered
97f9d654b6 [TS] Fix nullability (#2702)
`LGraphCanvas.graph` may explicity set to null by litegraph.
2025-02-24 22:00:19 +11:00
Terry Jia
822a8e02f8 [3d] add missing i18n (#2700)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-23 23:50:13 -05:00
Chenlei Hu
eb951c9cf9 Show image size (W x H) on image nodes (#2699) 2025-02-23 19:52:58 -05:00
Chenlei Hu
e98fda31ba 1.11.1 (#2698) 2025-02-23 18:48:47 -05:00
Chenlei Hu
78e4537fc2 Update litegraph 0.8.94 (#2697) 2025-02-23 18:47:45 -05:00
filtered
436b952c59 [Refactor] Simplify & document graphToPrompt (#2696) 2025-02-23 16:18:06 -05:00
bymyself
2ed3e59135 Type widget.options.serialize (#2692)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-02-23 13:14:20 -05:00
bymyself
c7ac0b8325 [Tests] Update test expectations (#2693)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-23 12:57:25 -05:00
bymyself
e7420fe2e3 Translate runtime-generated widget labels (#2688) 2025-02-23 10:16:25 -05:00
Terry Jia
d033640927 [3d] redesign UI (#2686)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-02-23 10:14:52 -05:00
bymyself
6f3b99209e Don't serialize file upload and video preview widgets (#2689) 2025-02-23 10:12:45 -05:00
bymyself
f7ee6861f1 Translate control before/after generate labels (#2690)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-23 10:09:06 -05:00
Chenlei Hu
8dcf7eca74 1.11.0 (#2685) 2025-02-22 19:22:19 -05:00
bymyself
f94831d054 Add node video previews (#2635) 2025-02-22 18:37:42 -05:00
Terry Jia
c502b86c31 [3d] refactor load3d nodes (#2683)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-22 18:36:47 -05:00
Chenlei Hu
86b65d481a 1.10.10 (#2679) 2025-02-21 23:30:06 -05:00
Chenlei Hu
064e982f01 Revert "[Refactor] Extract RerouteNode as a separate file" (#2678) 2025-02-21 22:57:19 -05:00
Chenlei Hu
f43eac7c71 Revert "Restrict applyToGraph to PrimitiveNode" (#2677) 2025-02-21 22:56:51 -05:00
bymyself
d7c9a43aba [Docs] Add id to details tag in README.md (#2676) 2025-02-21 22:36:55 -05:00
Chenlei Hu
dee3f5824a 1.10.9 (#2673) 2025-02-21 20:19:29 -05:00
Chenlei Hu
9b88909caa [Extension] Selection toolbox API (#2672) 2025-02-21 19:25:30 -05:00
Chenlei Hu
3fa512957c [CI] Enable release on LTS branches (#2671) 2025-02-21 16:36:17 -05:00
Chenlei Hu
b012f243b3 Only show delete in selection toolbox for reroute (#2670) 2025-02-21 16:03:36 -05:00
Chenlei Hu
6cb33d9431 Restrict applyToGraph to PrimitiveNode (#2669) 2025-02-21 15:53:33 -05:00
Chenlei Hu
85d04f6814 [Refactor] Extract RerouteNode as a separate file (#2668) 2025-02-21 15:04:47 -05:00
Chenlei Hu
40da43861e [Refactor] Move Widget.beforeQueued invocation from graphToPrompt to queuePrompt (#2667) 2025-02-21 14:18:11 -05:00
Chenlei Hu
40deb19634 [Cleanup] Remove upstreamed litegraph types (#2666) 2025-02-21 13:39:13 -05:00
Chenlei Hu
abfc7481d3 Remove 'clean' param from graphToPrompt (#2665) 2025-02-21 12:01:26 -05:00
Chenlei Hu
ec94811637 [Refactor] Move app.graphToPrompt to executionUtil (#2664) 2025-02-21 11:41:25 -05:00
Chenlei Hu
cea5a4a3dd Update litegraph 0.8.92 (#2662) 2025-02-21 09:28:43 -05:00
Chenlei Hu
0937c1f2cd 1.10.8 (#2659) 2025-02-20 20:14:32 -05:00
Chenlei Hu
8074d797b0 [BugFix] Fix incorrect selection overlay after drag (#2658) 2025-02-20 20:12:42 -05:00
Terry Jia
c3c6ec627b [3d] support using image as background (#2657)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-20 20:05:54 -05:00
Chenlei Hu
02d77002c9 Update litegraph to 0.8.91 (#2654)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-20 14:43:51 -05:00
Chenlei Hu
3e31045fbb [BugFix] Properly trigger onClose hook in dialogService (#2655) 2025-02-20 14:42:52 -05:00
Chenlei Hu
78146c86f4 [BugFix] Copy LGraphCanvas.ds on serialization (#2653) 2025-02-20 10:25:17 -05:00
bymyself
365fd1e047 Fix error translating legacy setting options (#2648) 2025-02-20 10:12:46 -05:00
filtered
fbb6c2f825 Update issue report image (#2647) 2025-02-20 16:29:21 +11:00
bymyself
9c7d86ee49 Update issue report template (#2645) 2025-02-19 22:46:22 -05:00
filtered
bc43cf0290 [CI] Always test LTS branches (#2641)
- Adds core/* and desktop/* to CI testing worfklows
2025-02-20 13:51:17 +11:00
Chenlei Hu
45c59f9e84 1.10.7 (#2639) 2025-02-19 17:45:05 -05:00
Terry Jia
014a65411e [3d] flash preview screen border if reach out limitation (#2638) 2025-02-19 15:49:36 -05:00
Chenlei Hu
6c6d86a30b Selection toolbox color picker button (#2637)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-19 15:25:46 -05:00
filtered
08a6867c00 [Desktop] Offer Troubleshoot page instead of Reinstall on start error (#2623)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-19 10:30:23 -05:00
filtered
dbbe67dfcd [Desktop] Fix missing git logo in troubleshooting (#2633) 2025-02-19 10:29:48 -05:00
bymyself
40fa1d37bc Fix pasting image that was copied from browser (#2630) 2025-02-19 10:27:58 -05:00
filtered
0d6bc669f5 [Desktop] Fix invalid type assertion in API (#2631) 2025-02-19 21:59:17 +11:00
Chenlei Hu
e4444d4074 1.10.6 (#2628) 2025-02-18 20:33:58 -05:00
Chenlei Hu
cbf5dff633 Update litegraph 0.8.87 (#2625)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-18 20:25:17 -05:00
Chenlei Hu
9de8450deb Update test expectations (#2627)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-18 20:25:06 -05:00
Chenlei Hu
3b0e3d635b [BugFix] Fix node color for custom light themes (#2621)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-18 19:08:34 -05:00
Chenlei Hu
d1a682bc01 [Refactor] Extract color selector as component (#2620) 2025-02-18 15:28:17 -05:00
Terry Jia
01ffc9e4eb [3d] allow using mouse wheel to adjust preview screen size (#2619) 2025-02-18 14:59:43 -05:00
Chenlei Hu
54e42178f7 1.10.5 (#2617) 2025-02-18 12:26:27 -05:00
Chenlei Hu
25e5ab3a36 Add bypass action to selection toolbox (#2616) 2025-02-18 12:25:49 -05:00
Chenlei Hu
28dd6a2702 Update litegraph 0.8.85 (#2615) 2025-02-18 11:51:36 -05:00
bymyself
3b3df250cd Add refresh button to selecton toolbox (#2612) 2025-02-18 11:39:43 -05:00
bymyself
6441a86619 [Style] Update toolbox style (#2614) 2025-02-18 11:34:06 -05:00
Chenlei Hu
79db202925 [New Feature] Selection Toolbox (#2608)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-17 19:07:49 -05:00
Chenlei Hu
f7556e0015 Add DeleteSelectedItems command (#2606) 2025-02-17 17:16:12 -05:00
bymyself
141e64354c Support batch image upload (#2597) 2025-02-17 13:56:21 -05:00
bymyself
79452ce267 Fix extraneous values in template workflows (#2605) 2025-02-17 13:55:29 -05:00
Chenlei Hu
4d8a5eacba 1.10.4 (#2604) 2025-02-17 10:13:43 -05:00
bymyself
8f5a9a50aa Remove duplicate outpaint template (#2602)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-02-17 10:12:09 -05:00
Margen67
7bc48c5074 Formatting/cleanup (#2594) 2025-02-17 10:10:00 -05:00
Dr.Lt.Data
e04ea07774 refine locales/ko (#2600) 2025-02-17 10:09:09 -05:00
bymyself
75af956279 Fix gallery navigator icons (#2601) 2025-02-17 10:08:46 -05:00
bymyself
434a2307a2 Remove lora dependency from flux canny template (#2603) 2025-02-17 10:08:16 -05:00
filtered
336b3caf9a [Desktop] Update uv cache clear task to show terminal (#2598) 2025-02-17 23:33:34 +11:00
filtered
c757fbaeb4 [Test] Fix unnecessary circular reference (#2596) 2025-02-17 20:18:26 +11:00
Chenlei Hu
fd27b3d580 Fix title editor font size (#2593) 2025-02-16 21:48:02 -05:00
Chenlei Hu
0658698a13 Selection Overlay (#2592) 2025-02-16 21:23:07 -05:00
Terry Jia
b2375a150c [3d] fully convert load 3d nodes into vue (#2590) 2025-02-16 20:15:49 -05:00
Chenlei Hu
9ebb5b2a0c 1.10.3 (#2591) 2025-02-16 20:14:50 -05:00
Chenlei Hu
d6a5deccd8 [Refactor] useAbsolutePosition composable (#2589) 2025-02-16 15:39:58 -05:00
Chenlei Hu
3f4d11c63a Inplace widget to input conversion (#2588)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-16 13:41:32 -05:00
Margen67
44498739fc Update setup-node to v4 (#2587) 2025-02-16 13:14:01 -05:00
dependabot[bot]
764ec9f7d0 Bump vite from 5.4.6 to 5.4.14 (#2585)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-16 11:23:17 -05:00
bymyself
e3234aa0aa Normalize translation keys in template card component (#2574)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-02-16 10:17:49 -05:00
bymyself
df11c99393 Refactor node image upload and preview (#2580)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-02-16 10:09:02 -05:00
Chenlei Hu
317ea8b932 1.10.2 (#2583) 2025-02-16 09:49:25 -05:00
bymyself
108884a304 Replace "clip" with "text_encoders" in template workflows (#2572) 2025-02-16 09:39:10 -05:00
bymyself
9f1992ca59 Change title of pose ControlNet template workflow (#2573) 2025-02-16 09:38:18 -05:00
bymyself
39f245fd97 Remove interchangeable models from template workflows (#2575) 2025-02-16 09:36:34 -05:00
bymyself
2d2fa5bfe9 Fix incorrect link in template workflow (#2579) 2025-02-16 09:35:54 -05:00
Terry Jia
bfb1b80cd7 [3d] bug fix for unable click vue button (#2581) 2025-02-16 09:35:20 -05:00
bymyself
0c8bfb4650 Add stable zero model url to whitelist (#2577) 2025-02-16 08:42:50 -05:00
bymyself
f69180cd84 Move node field to tags in error report (#2570)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-15 21:50:54 -05:00
Chenlei Hu
2ac177caeb 1.10.1 (#2569) 2025-02-15 19:34:13 -05:00
bymyself
77d3e0c45e Add ComfyUI Examples workflows to in-app templates (#2541)
Co-authored-by: jojodecayz <121620462+jojodecayz@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-02-15 16:15:56 -05:00
Chenlei Hu
00dceb880a Update litegraph 0.8.81 (#2568) 2025-02-15 15:06:21 -05:00
Chenlei Hu
acea173ba0 [BugFix] Set height to 0 for hidden widgets on GroupNode (#2566) 2025-02-15 12:24:38 -05:00
Chenlei Hu
bcedd5f4ed [Style] Show right arrow on nested submenu item (#2564) 2025-02-15 11:18:46 -05:00
Chenlei Hu
168ea05f81 [Style] Highlight active workflow item in the workflow sidebar (#2563) 2025-02-15 11:01:47 -05:00
Chenlei Hu
370ad7a4f9 1.10.0 (#2562) 2025-02-15 09:59:56 -05:00
Hiroaki Ogasawara
b9cfa70dcd chore: Add type augmentations for litegraph and enable copying of DTS (#2560) 2025-02-15 09:57:27 -05:00
Chenlei Hu
c15201bfe2 [Cleanup] Remove unused imports in domWidget (#2559) 2025-02-14 22:09:27 -05:00
Chenlei Hu
0e2ce5e1ca Upstream widgets layout to litegraph (#2557) 2025-02-14 19:40:31 -05:00
Chenlei Hu
5dc4a1b9cd Update litegraph 0.8.79 (#2556)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-14 14:42:53 -05:00
Chenlei Hu
acfb95f8d4 Use LGraphNode.setSize (#2555) 2025-02-14 11:02:56 -05:00
Chenlei Hu
f2065777b5 1.9.17 (#2553) 2025-02-14 09:58:19 -05:00
Yuki Shindo
b8b1e58172 [keybinding-panel] Include label in filter fields for multilingual search (#2549) 2025-02-14 09:48:44 -05:00
bymyself
2e86393378 Add null checks to widget constructor options (#2552) 2025-02-14 09:48:07 -05:00
bymyself
530ca75dd0 Fix remote widget undefined arg (#2551) 2025-02-14 09:47:18 -05:00
Chenlei Hu
f9c2db5908 Type LGraphNode.addDOMWidget (#2548) 2025-02-13 15:15:21 -05:00
Chenlei Hu
166ad432f3 [Refactor] Generalize dom widget layout as Widget.computeLayoutSize hook (#2547) 2025-02-13 14:30:46 -05:00
Chenlei Hu
174754e646 [Refactor] Extract widget layout logic (#2545) 2025-02-13 11:43:40 -05:00
Chenlei Hu
43dd457bf5 1.9.16 (#2546) 2025-02-13 11:03:16 -05:00
Yuki Shindo
625aa9bd11 Improve Japanese Text for Enhanced Readability (#2542) 2025-02-12 20:58:05 -05:00
Chenlei Hu
f791322ddb Revert "[Cleanup] Remove unused hooks on DOMWidget" (#2543) 2025-02-12 20:57:38 -05:00
Chenlei Hu
89812ce7d0 [Cleanup] Remove unused hooks on DOMWidget (#2540) 2025-02-12 19:41:06 -05:00
Chenlei Hu
c7aaa2a45d Type Widget.computedHeight (#2539) 2025-02-12 16:50:30 -05:00
Chenlei Hu
8bb785c5e4 Show convert to widget option slot context menu (#2538) 2025-02-12 16:07:19 -05:00
Chenlei Hu
a861a070d0 Remove horizontal layout of reroute node (#2532) 2025-02-12 14:43:34 -05:00
Chenlei Hu
108e37deca 1.9.15 (#2535) 2025-02-12 14:19:15 -05:00
Chenlei Hu
9082903956 [Style] Fix pointer events on graph canvas panel content (#2534) 2025-02-12 14:11:54 -05:00
Chenlei Hu
2cb9d4dd1c 1.9.14 (#2531) 2025-02-12 11:16:05 -05:00
bymyself
46f0733ae7 Ignore reserved keybindings when typing in text input (#2514)
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2025-02-12 11:15:19 -05:00
Chenlei Hu
150b4341b2 Update litegraph 0.8.77 (#2530) 2025-02-12 11:11:05 -05:00
bymyself
054f8f6838 Move install directory selection tooltip to not block buttons (#2527) 2025-02-12 10:02:56 -05:00
bymyself
9fd73873b6 [Desktop] Re-run path validation when re-focusing installation location input (#2528) 2025-02-12 10:02:42 -05:00
bymyself
bfec9b692b Add keybind hint to confirm close dialog (#2529)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-12 10:02:27 -05:00
Terry Jia
29cd693335 [3d] add tooltip (#2524)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-11 22:28:24 -05:00
Chenlei Hu
4f6891a5ad [Cleanup] Remove legacy settings dialog CSS (#2525) 2025-02-11 21:55:21 -05:00
Chenlei Hu
ca2aee296a [Cleanup] Remove unnecessary pointer-event-auto (#2523) 2025-02-11 21:41:47 -05:00
Chenlei Hu
9017513979 [Refactor] Manage comfyui-body elements with Vue (#2522)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-11 18:37:08 -05:00
Terry Jia
8cfe814daa [3d] refactor load3d (#2521) 2025-02-11 17:43:36 -05:00
Chenlei Hu
c901d5f659 1.9.13 (#2520) 2025-02-11 13:40:17 -05:00
Chenlei Hu
1263fbb4ad Enable ts-strict for scripts/widgets.ts (#2519) 2025-02-11 12:38:24 -05:00
Chenlei Hu
8db101c1cb [Type] Mark app as required arg for ComfyWidgetConstructor (#2518) 2025-02-11 11:39:23 -05:00
Chenlei Hu
efe7843469 [Refactor] useComboWidget composable (#2517) 2025-02-11 11:17:09 -05:00
Chenlei Hu
cfa46ebacb [Refactor] useBooleanWidget composable (#2516) 2025-02-11 11:05:58 -05:00
Chenlei Hu
ab305059bc [Refactor] useImageUploadWidget composable (#2515) 2025-02-11 10:50:55 -05:00
bymyself
cd8c0d2865 Add refresh button to remote (lazy) widgets (#2494) 2025-02-11 10:31:32 -05:00
bymyself
6a9d309818 Increase width of actionbar drag handle (#2511) 2025-02-11 10:29:26 -05:00
bymyself
e3f226e483 Fix actionbar has drag preview (#2512) 2025-02-11 10:28:56 -05:00
bymyself
8822edaf24 Improve settings dialog accessibility (#2513) 2025-02-11 10:28:41 -05:00
Chenlei Hu
44b9a477b1 [Refactor] useMarkdownWidget composable (#2510) 2025-02-11 00:12:29 -05:00
bymyself
e4f8d4b8d0 Add support for image_folder field in node image input spec (#2509) 2025-02-11 00:12:03 -05:00
Chenlei Hu
a93f57eeb2 [Refactor] useSeedWidget composable (#2508) 2025-02-10 23:55:59 -05:00
Chenlei Hu
0c2879b6f4 [Refactor] useIntWidget composable (#2507) 2025-02-10 23:07:57 -05:00
Chenlei Hu
d8d46f8cf6 1.9.12 (#2506) 2025-02-10 22:17:12 -05:00
Chenlei Hu
1a06c91ed1 [BugFix] Workaround custom nodes expectation on DOMWidget.value (#2505) 2025-02-10 22:06:20 -05:00
Chenlei Hu
d4122a7510 [Refactor] useFloatWidget composable (#2504) 2025-02-10 22:06:11 -05:00
Chenlei Hu
b4c59ffae1 [Refactor] useStringWidget composable (#2503) 2025-02-10 19:49:00 -05:00
Chenlei Hu
46428cbf7d [Cleanup] Rename remoteWidgetHook (#2500) 2025-02-10 18:12:15 -05:00
filtered
2d759aa9e3 Fix element style override CSS in #2499 (#2501) 2025-02-10 18:11:32 -05:00
Chenlei Hu
08e613e468 Enable ts-strict for scripts/domWidgets (#2499) 2025-02-10 17:20:30 -05:00
Chenlei Hu
8052b2a02a Type LGraphNode.getInnerNodes (#2498) 2025-02-10 16:35:26 -05:00
Chenlei Hu
0479b112c1 1.9.11 (#2497) 2025-02-10 15:31:17 -05:00
Chenlei Hu
d7a0ee8703 Update litegraph 0.8.76 (#2496)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-10 15:30:46 -05:00
Chenlei Hu
9051ab8d7a Type domWidget computeSize (#2495) 2025-02-10 12:58:40 -05:00
Terry Jia
aaca5191ab Light fov UI change (#2492) 2025-02-10 11:23:33 -05:00
Chenlei Hu
9707a30d0e 1.9.10 (#2491) 2025-02-09 23:39:57 -05:00
Chenlei Hu
e100041db4 Update litegraph 0.8.75 (#2490) 2025-02-09 23:39:27 -05:00
Chenlei Hu
21718d9da2 1.9.9 (#2486) 2025-02-09 20:50:47 -05:00
Chenlei Hu
2b4c594b21 Update litegraph 0.8.74 (#2485) 2025-02-09 20:26:58 -05:00
Chenlei Hu
00abd885c9 [Refactor] ES6 DOMWidget class (#2482) 2025-02-09 20:20:51 -05:00
bymyself
550a9d04c5 Fix color and slider settings types to inherit attrs (#2483) 2025-02-09 20:18:09 -05:00
bymyself
eeb1c34ada Update public API syntax of remote (lazy) widgets (#2477)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-02-09 12:41:14 -05:00
Terry Jia
83cc49a42b [3d] use vue to rewrite the UI for load3d (#2467) 2025-02-09 12:05:42 -05:00
Chenlei Hu
91a3d1228e Reference specific ComfyUI_devtools in CI (#2479) 2025-02-09 12:00:26 -05:00
Chenlei Hu
3d59d478b6 [Desktop] Fix torch mirror setting (#2475) 2025-02-08 21:08:23 -05:00
Chenlei Hu
4dd292252e 1.9.8 (#2474) 2025-02-08 18:31:16 -05:00
Chenlei Hu
0d307ff587 Update litegraph 0.8.73 (#2472) 2025-02-08 17:58:39 -05:00
Chenlei Hu
88a969df07 Update litegraph 0.8.72 (#2470) 2025-02-08 17:51:37 -05:00
Dr.Lt.Data
9e37738dc8 refine locales/ko (#2469) 2025-02-08 17:31:26 -05:00
Chenlei Hu
9b97abad57 1.9.7 (#2466) 2025-02-08 12:11:24 -05:00
Chenlei Hu
67fcb4fed4 Update litegraph 0.8.71 (#2465) 2025-02-08 12:10:44 -05:00
bymyself
a914456827 Add support for new COMBO input spec and lazy/remote COMBO widgets (#2422) 2025-02-07 15:35:42 -05:00
Chenlei Hu
340513e27f Type INodeSlot.widget (#2463) 2025-02-07 14:33:21 -05:00
bymyself
117c8be3a0 Use fp16 safetensors model in default/fallback workflow (#2433)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-06 19:47:14 -05:00
Chenlei Hu
68f6d51ad2 [i18n] Translate clipboard toast messages (#2462)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-06 15:34:15 -05:00
Chenlei Hu
2da23fd373 [Refactor] Extract litegraph settings sync to a composable (#2461) 2025-02-06 15:21:11 -05:00
Chenlei Hu
7ddcac88d7 [Refactor] Upstream drag zoom feature to litegraph (#2459) 2025-02-06 14:54:36 -05:00
Chenlei Hu
40a817bb0f 1.9.6 (#2460) 2025-02-06 14:48:57 -05:00
filtered
774ed4178f [Cleanup] Fix file and variable names to match usage (#2458) 2025-02-06 14:48:24 -05:00
filtered
78e4161c51 [Refactor] Terminal output drawer shared component (#2457) 2025-02-06 14:33:12 -05:00
filtered
dda9a72966 [Desktop] Add desktop updating page (#2454)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-06 14:23:51 -05:00
Chenlei Hu
d7673af8f5 [Refactor] Move resetView to litegraphService (#2456) 2025-02-06 14:22:40 -05:00
Chenlei Hu
2b18949615 [Cleanup] Remove duplicated group header drawing logic (#2453) 2025-02-06 13:52:05 -05:00
Chenlei Hu
629ac63f06 Type LGraphNode.pasteFile (#2455) 2025-02-06 13:50:48 -05:00
Chenlei Hu
1061620783 [Refactor] Move paste handling to usePaste composable (#2452) 2025-02-06 13:37:37 -05:00
Chenlei Hu
af7a6601e0 [Refactor] Move copy handling to useCopy composable (#2451) 2025-02-06 13:22:48 -05:00
Chenlei Hu
0e0c4b1302 [Refactor] Move isImageNode to litegraphUtil (#2450) 2025-02-06 13:15:17 -05:00
Chenlei Hu
fb170c9ee9 1.9.5 (#2448) 2025-02-06 10:49:37 -05:00
Chenlei Hu
7ef304b381 Fix litegraph copy in Chrome 133 (#2446) 2025-02-06 10:18:28 -05:00
Chenlei Hu
50833341bb 1.9.4 (#2444) 2025-02-05 22:25:19 -05:00
kvick-games
f5c5a95bdc Refresh Preview3D node with node.onMouseEnter (#2439) 2025-02-05 21:26:45 -05:00
Chenlei Hu
b700cc1824 [Documentation] Add src/scripts/README.md (#2442) 2025-02-05 18:32:44 -05:00
Chenlei Hu
a6031ec2be [Cleanup] Rename usePragmaticDroppable to usePragmaticDragAndDrop (#2441) 2025-02-05 17:46:28 -05:00
Chenlei Hu
a4d99d9d28 Support insert workflow by dragging from workflow sidebar to canvas (#2440) 2025-02-05 17:09:01 -05:00
Chenlei Hu
5a7465a907 Add node drag preview for bookmarked nodes (#2438) 2025-02-05 16:25:56 -05:00
Chenlei Hu
6525ae7cf4 [Refactor] Rename hooks/ to composables/ (#2437) 2025-02-05 15:05:56 -05:00
Chenlei Hu
c6ef107111 [Style] Fix shrinking of extension added topmenu items (#2436) 2025-02-05 13:40:14 -05:00
bymyself
3fbccd20ff Use fp16 model in default img2img template workflow (#2430) 2025-02-05 13:27:16 -05:00
Chenlei Hu
fa0682d66e 1.9.3 (#2434) 2025-02-05 13:26:56 -05:00
Chenlei Hu
f7b613c6cb 1.9.2 (#2429)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-05 12:20:20 -05:00
Chenlei Hu
292af3fe3f [Refactor] Replace explicit 'node' param with 'this' for TreeExplorer (#2427) 2025-02-05 12:20:08 -05:00
KarryCharon
2c12df12ab [i18n] Impl i18n context menu translation (#2425)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-02-05 12:07:40 -05:00
Chenlei Hu
d0e99beaa7 Swap eslint/prettier trigger order in pre-commit (#2428) 2025-02-05 12:04:20 -05:00
Chenlei Hu
6b64b74f6c [Desktop] Use fallback mirrors for China users (#2424) 2025-02-05 10:51:32 -05:00
Chenlei Hu
0af4768dd2 Update litegraph 0.8.67 (#2423) 2025-02-04 19:31:09 -05:00
Chenlei Hu
5f850ddaa4 [BrowserTest] Add test on boolean widget (#2421)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-04 17:28:32 -05:00
dependabot[bot]
9fb3235df4 Bump vitest from 2.0.5 to 2.1.9 (#2420)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-04 17:11:56 -05:00
Chenlei Hu
628facaa75 1.9.1 (#2416) 2025-02-03 20:55:06 -05:00
Chenlei Hu
eb5a4b65ab Update litegraph 0.8.66 (#2415) 2025-02-03 20:30:01 -05:00
Chenlei Hu
98c197e8b1 Add LiteGraph.Canvas.LowQualityRenderingZoomThreshold setting (#2412)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-03 20:28:07 -05:00
Chenlei Hu
90914a40ba Use canvas.low_quality flag for DOMWidget show/hide (#2413) 2025-02-03 20:23:07 -05:00
Chenlei Hu
821816955f Update litegraph 0.8.65 (#2411) 2025-02-03 17:38:29 -05:00
Chenlei Hu
b4121008cd Fix NoteNode constructor fields (#2410) 2025-02-03 14:20:39 -05:00
Chenlei Hu
3730c2b36f [Refactor] Use litegraph.strokeShape (#2406) 2025-02-02 23:15:09 -05:00
bymyself
77be5ac514 [BrowserTest] Add test on groupnode with duplicate hidden inputs (#2403) 2025-02-02 21:03:08 -05:00
bymyself
83759b9a4a Use command label as header text in change keybinding dialog (#2404) 2025-02-02 21:02:48 -05:00
Chenlei Hu
b8f187713e 1.9.0 (#2401) 2025-02-02 17:35:04 -05:00
filtered
b8088ad782 Revert "Correct node/output titles when grouping nodes (#2359) (#2370)" (#2399)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-02 17:23:55 -05:00
bymyself
a37671b154 Add bottom panel to extension manager (#2393) 2025-02-02 15:01:42 -05:00
filtered
57bc7ad312 Add node tooltip delay setting (#2396)
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-02-02 14:31:34 -05:00
filtered
5f59fbdead [Desktop] Persist troubleshooting terminal when hidden (#2398)
Co-authored-by: github-actions <github-actions@github.com>
2025-02-02 14:29:47 -05:00
filtered
4eed9c7e53 [Accessibility] Use keybindings to add keybindings (#2384) 2025-01-31 09:46:23 -08:00
bymyself
ee6197785a Fix typo in coreSettings.ts (#2391)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-31 07:50:16 -08:00
Chenlei Hu
f5d6ad07e8 1.8.12 (#2390) 2025-01-30 15:51:53 -08:00
Chenlei Hu
45207dabbc Type LGraphNode.onDragOver/onDragDrop (#2389) 2025-01-30 15:50:04 -08:00
bymyself
4699360147 Show bookmark buttons when item is focused (#2386) 2025-01-30 14:45:04 -08:00
Chenlei Hu
8ef3b87e59 Generate drag preview for node library nodes (#2387) 2025-01-30 11:11:22 -08:00
Dr.Lt.Data
d3a6baf8cd refine locales/ko (#2385) 2025-01-30 09:55:40 -08:00
jojodecayz
b4d679d31f Update Python fallback mirror in uvMirrors.ts (#2382) 2025-01-29 20:06:45 -08:00
Chenlei Hu
7afc1baf7d [Refactor] Extract litegraph canvas drop target logic as composable (#2381) 2025-01-29 17:15:01 -08:00
Chenlei Hu
7bdad335ca [Refactor] Extract global window litegraph as a composable (#2380) 2025-01-29 16:53:26 -08:00
Chenlei Hu
94065b6c21 [Style] Show sidebar tool buttons when sidebar is focused (#2379) 2025-01-29 16:29:59 -08:00
Chenlei Hu
a205a5cca5 [Style] Only show sidebar tool buttons when sidebar hovered (#2378) 2025-01-29 16:16:10 -08:00
Chenlei Hu
788d6cf514 1.8.11 (#2377) 2025-01-29 15:00:32 -08:00
Chenlei Hu
766710cf37 [Desktop] Fix mirror validation in settings dialog (#2375) 2025-01-29 14:57:36 -08:00
Chenlei Hu
e019277ba0 [Style] Use consistent color for workflow sidebar tab tool buttons (#2376) 2025-01-29 14:57:19 -08:00
Chenlei Hu
97e5c9c6d2 1.8.10 (#2374) 2025-01-29 14:09:55 -08:00
Chenlei Hu
52e42b5339 Fix 404 PythonInstallMirror url suffix (#2373) 2025-01-29 13:01:54 -08:00
Chenlei Hu
c42cdf5cd9 1.8.9 (#2372) 2025-01-29 11:15:00 -08:00
Chenlei Hu
c07ec659a7 Fix mirror item key not being unique (#2371) 2025-01-29 11:13:04 -08:00
Chenlei Hu
cbcbeab9d9 Correct node/output titles when grouping nodes (#2359) (#2370)
Co-authored-by: Anastasiy Safari <anastasiuspernat@gmail.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-01-29 11:05:48 -08:00
Dr.Lt.Data
bf9d2affb4 refine locales/ko (#2368) 2025-01-29 10:46:57 -08:00
Chenlei Hu
2c8c8718e9 [Desktop] Apply default pypi mirror when installing CPU torch (#2367) 2025-01-28 18:00:08 -08:00
Chenlei Hu
475e38ddb4 [CI] Skip draft in github release action (#2366) 2025-01-28 15:28:41 -08:00
Chenlei Hu
430f051c64 Add UV mirrors settings (#2333)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-28 14:39:51 -08:00
filtered
29b5f606b0 [CI] Auto-generate release notes in GH action (#2364) 2025-01-27 17:10:34 -08:00
Terry Jia
55d63a8aef [3d] move change background color button (#2365) 2025-01-27 17:06:01 -08:00
filtered
99009a18f7 1.8.8 (#2363) 2025-01-27 22:58:11 +11:00
filtered
e3ab0e4d68 Add option to disable combo box zoom-in scaling (#2362)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-27 22:56:40 +11:00
filtered
0e1ae41c0c Update litegraph 0.8.62 (#2360) 2025-01-27 22:32:24 +11:00
filtered
f12d4a2d6f [Test] Update test expectations for 2357 (#2361) 2025-01-27 22:09:25 +11:00
bymyself
7bd8527bca Add cursor drop effect when dragging nodes/models onto graph (#2354) 2025-01-26 07:08:10 -05:00
bymyself
cb356d50b8 Set Node ID badges to hidden by default (#2356) 2025-01-26 07:07:05 -05:00
filtered
d2e9943e79 Add convert to input for the clicked widget (#2357)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-26 07:06:41 -05:00
Chenlei Hu
27e4bd2592 [Refactor] Use computed states for maintenance/StatusTag (#2352) 2025-01-25 20:56:05 -05:00
Chenlei Hu
82e0c3a8b6 1.8.7 (#2351) 2025-01-25 20:12:21 -05:00
Chenlei Hu
2852720b2c [Refactor] Extract workflow/workflow tabs restore into a composable (#2350) 2025-01-25 16:58:50 -05:00
Chenlei Hu
38b8a68e50 [Refactor] Move workflow restore from app to GraphCanvas (#2349) 2025-01-25 15:36:50 -05:00
Chenlei Hu
44321e4692 [DevExperience] Add default VSCode launch.json (#2348) 2025-01-25 12:53:36 -05:00
bymyself
e992bd6571 Add tutorial workflow function for new desktop users (#2315)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-01-25 12:23:27 -05:00
bymyself
e971ba31e0 Add "Don't show this again" checkbox to missing models dialog (#2344)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-25 11:42:01 -05:00
Terry Jia
28b163cdd5 [3d] animation node UI change (#2347) 2025-01-25 11:41:05 -05:00
bymyself
652125de1f Use v1-5-pruned-emaonly-fp16 model in default template workflow (#2346) 2025-01-25 11:40:39 -05:00
bymyself
c5d153cf16 Enable missing models dialog by default (#2345) 2025-01-25 11:40:18 -05:00
Chenlei Hu
9459f599b6 1.8.6 (#2343) 2025-01-24 22:41:38 -05:00
Terry Jia
326839db88 [3d] add preview 3d animation node (#2341) 2025-01-24 22:35:28 -05:00
Chenlei Hu
30fdc70218 Click url input status icon to trigger validation (#2339) 2025-01-24 14:15:54 -05:00
bymyself
9c42c31968 Fix missing models dialog (#2336) 2025-01-24 10:37:19 -05:00
Chenlei Hu
44aa1bf8c3 1.8.5 (#2335) 2025-01-23 22:06:57 -05:00
Chenlei Hu
caad27e28d Validate on mount for UrlInput (#2332) 2025-01-23 15:09:00 -05:00
Chenlei Hu
e8136ff0ae UrlInput emits update:modelValue only on blur (#2331) 2025-01-23 14:55:12 -05:00
Chenlei Hu
157475cb2e Add validateUrlFn props on UrlInput component (#2330) 2025-01-23 14:44:06 -05:00
Chenlei Hu
93dc50a95a Allow passthrough attrs on UrlInput (#2329) 2025-01-23 14:29:38 -05:00
Terry Jia
3f787e2dbf [3d] improve storing Camera State logic (#2328) 2025-01-23 14:26:13 -05:00
Terry Jia
b54e270b10 [3d] refactor code (#2326) 2025-01-23 11:26:27 -05:00
Chenlei Hu
0ab1d974c0 Add url setting type (#2327) 2025-01-23 11:25:06 -05:00
bymyself
95ff01a67b Fix form validation message appearing unnecessarily (#2324) 2025-01-23 09:25:36 -05:00
filtered
6f05ce6cc2 [Desktop] Add restart app instruction to git fix task (#2322) 2025-01-23 09:25:04 -05:00
bymyself
b8bef57522 Clean tags in issue reports (#2323) 2025-01-23 09:23:07 -05:00
bymyself
46500bf3dd Fix translation id in folder customization dialog (#2320) 2025-01-22 20:44:02 -05:00
Chenlei Hu
1bcc00cd33 [i18n] Load custom nodes locales from ComfyUI server (#2314) 2025-01-22 17:37:02 -05:00
Chenlei Hu
08d2322817 1.8.4 (#2319) 2025-01-22 15:37:07 -05:00
filtered
8cfc1c4682 [Desktop] Remove beforeunload handler - unusable in electron (#2318) 2025-01-22 15:35:21 -05:00
filtered
c7bce87b8d [Desktop] Use Window Controls Overlay API (#2316)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-01-22 13:22:21 -05:00
Chenlei Hu
8f6b594a9f Fix console error on adding node via searchbox (#2317) 2025-01-22 13:13:26 -05:00
Chenlei Hu
1c9b300396 1.8.3 (#2312) 2025-01-21 20:36:54 -05:00
filtered
cd5283c4b7 [Refactor] Desktop maintenance task runner (#2311) 2025-01-21 20:18:01 -05:00
filtered
0b69d3cbfe [Desktop] Startup maintenance screen (#2253)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-21 16:10:15 -05:00
bymyself
8257e848c6 Update SearchBox vue features (#2310) 2025-01-21 10:32:46 -05:00
Chenlei Hu
a07b7693b6 [chore] Update vue to 3.5 (#2308)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-20 21:21:13 -05:00
Chenlei Hu
26ddf69451 Fix validation message locale (#2309) 2025-01-20 21:11:23 -05:00
bymyself
ed6ece2099 Add forms plugin to issue report component (#2302) 2025-01-20 20:20:59 -05:00
Chenlei Hu
b42516d39c 1.8.2 (#2307) 2025-01-20 17:24:58 -05:00
Chenlei Hu
ef24efe5a3 [Desktop] Report execution complete events (#2306) 2025-01-20 17:24:15 -05:00
Chenlei Hu
34c267c755 [chore] Update primevue to 4.2.5 (#2304) 2025-01-20 16:22:24 -05:00
bymyself
8b9f0ddd1d Add Comfy Forum (forum.comfy.org) to Help menu (#2305)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-20 16:06:31 -05:00
filtered
af658b7792 [Style] Use import/export icons for colour palette (#2300) 2025-01-20 14:33:02 -05:00
filtered
9c53bbd53d [Refactor] Move type extensions out of LG (SoC) (#2303)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-01-20 14:22:56 -05:00
filtered
f9be20fa78 [Desktop] Fix unnecessary setting update (#2301)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-20 14:00:35 -05:00
Chenlei Hu
87fc7a2c5d [Cleanup] Remove explicit prettier plugin call (#2299) 2025-01-20 11:15:16 -05:00
Chenlei Hu
1f266e826e Fix .cursorrules typo (#2298) 2025-01-20 11:12:59 -05:00
Dr.Lt.Data
911adfe9f8 refine locales/ko (#2296) 2025-01-20 11:11:16 -05:00
bymyself
654d72b4cc Add issue report dialog service (#2284)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-01-19 20:44:11 -05:00
bymyself
a1ed67fc74 Add User Feedback buttons (#2275)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-01-19 19:41:58 -05:00
Chenlei Hu
78bc635518 1.8.1 (#2295) 2025-01-19 19:07:18 -05:00
Chenlei Hu
f49ec175e9 1.8.0 (#2293)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-19 18:57:07 -05:00
Yuki Shindo
e4c60e7e18 Prevent Enter Key from Triggering Selection During IME Composition in AutoCompletePlus (#2285) 2025-01-19 18:34:26 -05:00
filtered
37cb2cb0a5 [Desktop] Add quit command (#2286)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-01-19 14:31:52 -05:00
Hikari-Fox
141825e988 Update Russian localization: refine terminology for "node", "hook", "… (#2289)
Co-authored-by: Vladimir Pozdnyakov <pozdnyakov044@gmail.com>
2025-01-19 14:29:40 -05:00
filtered
78f43b1e06 [Desktop] Add electron types update script (#2290) 2025-01-19 14:16:27 -05:00
filtered
a6105eb8c7 [DevExperience] Tailwind rules (#2292) 2025-01-19 14:16:03 -05:00
filtered
79ed598d5d [chore] Update electron-types to 0.4.11 (#2291) 2025-01-19 14:12:17 -05:00
bymyself
816574e0ab [Refactor] improve type safety in dialog service (#2283) 2025-01-18 15:46:57 -05:00
Chenlei Hu
1a4e77a3ab [Desktop] Ctrl+w to close workflow tab (#2282) 2025-01-17 20:02:54 -05:00
Chenlei Hu
de570712df 1.7.14 (#2281) 2025-01-17 18:04:43 -05:00
Chenlei Hu
44612e8f97 [Desktop] Add privacy policy link to install view about dialog (#2280)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-17 18:04:08 -05:00
bymyself
3df911c1bf Add consent prompt view (#2268)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-17 17:39:50 -05:00
Chenlei Hu
af26b9ad6d [Desktop] Report completed generation status (#2279) 2025-01-17 17:36:46 -05:00
Chenlei Hu
d503873980 Move queueStore update from QueueSidebarTab to GraphView (#2278) 2025-01-17 17:14:22 -05:00
bymyself
842a9f74fc [BrowserTest] Fix flaky gallery test (#2150) 2025-01-17 17:11:49 -05:00
Chenlei Hu
29551a36b3 Add .cursorrules (#2277) 2025-01-17 16:35:25 -05:00
filtered
d6e5c8950c [Desktop] Loading screen (#2274)
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-01-17 11:12:03 -05:00
Chenlei Hu
ad1c1ce9c2 [chore] Update electron-types to 0.4.9 (#2276) 2025-01-17 10:59:41 -05:00
Benjamin Lu
cb9d2c6bae Caching brush settings in mask editor (#2271)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-01-17 10:38:23 -05:00
Chenlei Hu
7fd41eeaba 1.7.13 (#2270) 2025-01-16 11:51:58 -05:00
filtered
79fee6ac72 Fix collapsed node textarea causes UI inconsistency (#2267) 2025-01-16 11:50:53 -05:00
Benjamin Lu
edd58cd153 Hotfix scoped --sidebar-width uasges in maskeditor.ts (#2269)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-01-16 11:36:11 -05:00
Chenlei Hu
e153508955 1.7.12 (#2265) 2025-01-15 20:19:24 -05:00
Chenlei Hu
237fca0bf1 [CodeHealth] Use scoped CSS for SideToolbar (#2264) 2025-01-15 20:16:39 -05:00
Chenlei Hu
65542b885a [Style] Fix root CSS selector (#2263) 2025-01-15 19:44:46 -05:00
Chenlei Hu
f739f704af [CodeHealth] Use scoped CSS in views (#2262) 2025-01-15 19:35:01 -05:00
Chenlei Hu
37abdbe35d [Desktop] Add install screen stepper change metrics (#2261) 2025-01-15 19:27:05 -05:00
Chenlei Hu
ff445f5c95 Apply min col on logs terminal for colab (#2260) 2025-01-15 17:16:33 -05:00
Chenlei Hu
84b652a281 [CodeHealth] Convert useAutoSize to kwargs (#2259) 2025-01-15 17:06:45 -05:00
Chenlei Hu
184291d21b [Settings] Enable Comfy.Window.UnloadConfirmation by default (#2258) 2025-01-15 16:37:11 -05:00
Chenlei Hu
d7fb25a36a Don't prompt unsaved when there is no unsaved workflow on window close (#2257) 2025-01-15 16:34:05 -05:00
Comfy Org PR Bot
c039a60fcc Update locales for node definitions (#2256)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
Co-authored-by: huchenlei <huchenlei@proton.me>
2025-01-15 16:23:45 -05:00
Chenlei Hu
3b6108c26e Add work dir to i18n-node-defs.yaml (#2255) 2025-01-15 16:19:13 -05:00
Chenlei Hu
49bb247526 1.7.11 (#2250) 2025-01-14 23:34:58 -05:00
bymyself
dd005f5fa5 Allow parent component to pass tags to issue report panel (#2247) 2025-01-14 23:34:11 -05:00
Chenlei Hu
bf90b458d3 [Desktop] Add clarification of migration from existing install (#2249)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-14 23:33:53 -05:00
bymyself
7e78c5b1dc Fix type error in BaseViewTemplate (#2245) 2025-01-14 20:19:35 -05:00
Gremlation
c13190cd07 Fix execution_interrupted (#2244) 2025-01-14 11:46:42 -05:00
filtered
00f031e382 [Refactor] Remove old workarounds (#2242) 2025-01-14 10:52:34 -05:00
filtered
04153caaf5 Fix prettier output in CI does not match IDE (#2243) 2025-01-14 10:51:32 -05:00
Chenlei Hu
210bfdeb7d 1.7.10 (#2241) 2025-01-13 20:25:36 -05:00
bymyself
ce0726d85e Restore all open workflows on load (#2238) 2025-01-13 20:24:40 -05:00
bymyself
dd69f9dc30 [Style] Update workflow template cards style (#2239) 2025-01-13 20:21:03 -05:00
Chenlei Hu
3f261f0e53 [Desktop] Add user journey events to the metrics collection list (UI) (#2237)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-12 17:16:16 -05:00
Chenlei Hu
3b2cc23f65 [Desktop] Mark window style setting as experimental (#2236) 2025-01-12 16:14:51 -05:00
bymyself
c50a86b258 [CI] Fix vite config condition (#2235) 2025-01-12 16:09:46 -05:00
Chenlei Hu
1a8c2bba42 1.7.9 (#2234) 2025-01-12 13:43:05 -05:00
Benjamin Lu
fc09951b3e [Style] Visual improvements to WorkflowTabs (#2232)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-01-12 13:41:55 -05:00
Terry Jia
76d5f39607 [3d] use threejs native viewHelper (#2230) 2025-01-12 13:23:23 -05:00
bymyself
9d3bc0f173 Add optional report feature to error dialog (#2229)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-12 13:23:02 -05:00
bymyself
d9b350e159 Add bookmark option in workflow tab context menu (#2231)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-12 13:22:22 -05:00
Chenlei Hu
44610674ee [Desktop] Fix server start view layout (#2226) 2025-01-10 22:14:01 -05:00
Chenlei Hu
9bfce5b8d0 Disable i18n on PRs from forked repo (#2225) 2025-01-10 19:23:20 -05:00
Chenlei Hu
8986fa356a 1.7.8 (#2223) 2025-01-10 19:06:03 -05:00
Chenlei Hu
0c4fd4af1c [Style] Set topbar height to 2.5rem (40px) (#2224) 2025-01-10 19:05:44 -05:00
Chenlei Hu
30cd46ce1f [Desktop] Allow dragging window on empty titlebar (#2222) 2025-01-10 13:41:26 -05:00
filtered
3122c33310 Allow Ctrl + C to send interrupt in terminal (#2221) 2025-01-10 13:30:11 -05:00
Chenlei Hu
91d8d04dc6 [Style] Reduce opacity on workflow tabs scrollbar (#2220) 2025-01-10 10:59:58 -05:00
Chenlei Hu
8f5aa1ff08 [Desktop] Native window in graph view (#2216) 2025-01-09 23:00:28 -05:00
Chenlei Hu
e076783b89 [Desktop] Native window virtual menu bar (#2215) 2025-01-09 20:21:03 -05:00
Chenlei Hu
04c23001fc [Desktop] Set window action buttons style (#2214) 2025-01-09 19:35:22 -05:00
Chenlei Hu
cb265fb0bf 1.7.7 (#2213) 2025-01-09 19:03:43 -05:00
Chenlei Hu
e9211fe377 [Desktop] Add window style setting (#2212)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-09 17:33:57 -05:00
Chenlei Hu
ffc7febeac [BrowserTest] Disable flaky test (#2211) 2025-01-09 14:46:09 -05:00
Chenlei Hu
b15e626607 [Style] Replace px with rem in sidebar width (#2210) 2025-01-09 14:25:34 -05:00
Chenlei Hu
906b5e35a3 [Style] Set fixed top menu bar height (#2209) 2025-01-09 14:14:14 -05:00
Chenlei Hu
e8cd9c7642 [BrowserTest] Replace ComfyPage.reload with ComfyPage.setup (#2208) 2025-01-09 12:54:05 -05:00
Chenlei Hu
93e184e379 Explicitly add zod-to-json-schema as dev dependency (#2207) 2025-01-09 11:41:40 -05:00
Chenlei Hu
1d02cd3c47 [Docs] Extract comfy workflow zod schema as json schema (#2206) 2025-01-09 11:30:47 -05:00
Chenlei Hu
b86e3f71cb 1.7.6 (#2202) 2025-01-08 11:24:59 -05:00
bymyself
1ece2462bd Use more conventional import/export icons in color palette settings (#2199)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-08 10:58:21 -05:00
bymyself
73ecacfa2d Fix searchbox dismissed when closing filter panel (#2196) 2025-01-08 10:57:55 -05:00
bymyself
67e6df7c72 Fix search result category text on light theme (#2198) 2025-01-08 10:57:10 -05:00
Jarvis
7e8510028d fix: Make sure use the correct graph parameter (#2200) 2025-01-08 10:56:27 -05:00
bymyself
dd4dd8b68a [Doc] Add anchors to sections in README (#2197) 2025-01-08 10:55:59 -05:00
bymyself
7111022617 Fix node text highlight color on light theme (#2195) 2025-01-08 09:16:57 -05:00
Chenlei Hu
daee073045 [Style] Fix second row workflow tabs overflow (#2194) 2025-01-07 16:28:49 -05:00
Chenlei Hu
a1a834a76d Support 2nd row location for workflow tabs (#2193)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-07 16:05:37 -05:00
Chenlei Hu
c437d32691 Truncate sidebar title first to avoid tool buttons wrap (#2192) 2025-01-07 15:14:09 -05:00
Chenlei Hu
0130d41be5 Try fix workflow tabs vertical scrollbar (#2191) 2025-01-07 13:39:14 -05:00
Chenlei Hu
527561d148 1.7.5 (#2189) 2025-01-07 10:47:34 -05:00
Chenlei Hu
1c4481c342 Horizontal scroll workflow tabs on overflow (#2188) 2025-01-07 10:45:58 -05:00
Chenlei Hu
07000a23d4 Wrap each init task with error handling (#2187) 2025-01-07 10:40:32 -05:00
Chenlei Hu
ea6c9e7ca5 Replace unset unknown keybinding error with warn (#2186) 2025-01-07 10:33:23 -05:00
Chenlei Hu
90698fced6 [BugFix] Migrate deprecated Comfy.Keybinding.UnsetBindings values (#2185) 2025-01-07 10:23:25 -05:00
iola1999
9716aea10d fix: Fix infinite recursion in mask upload retry logic (#2181) 2025-01-07 16:19:13 +01:00
Chenlei Hu
077ded2cce [Refactor] Simplify keybindingStore with _.groupBy (#2180) 2025-01-06 19:46:20 -05:00
Chenlei Hu
ffb20b8789 1.7.4 (#2179) 2025-01-06 19:24:40 -05:00
Chenlei Hu
549a2fdc92 Remove main_repo_release.py (#2147) 2025-01-06 17:01:41 -05:00
bymyself
e123295423 Fix saved keybinding persistence (#2176) 2025-01-06 15:54:35 -05:00
Chenlei Hu
613b44610a 1.7.3 (#2175) 2025-01-06 11:04:54 -05:00
Chenlei Hu
e82d795ff9 Trigger node def locale update manually (#2170) 2025-01-06 10:54:59 -05:00
bymyself
ba31f8fa68 Add Close Workflow to commands (#2171)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-01-06 10:50:44 -05:00
Alexander Piskun
f2eb4e1519 (fix): added missing slash to "loadWorkflow" templates endpoint (#2174) 2025-01-06 10:49:07 -05:00
Chenlei Hu
975c2248c5 Rename Keybinding.targetSelector to targetElementId (#2169)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-05 16:03:38 -05:00
bymyself
477f4b275d Fix node bookmark color customization (#2168) 2025-01-05 13:05:09 -05:00
bymyself
179b8c22a9 [BrowserTest] Refactor test fixtures (#2165) 2025-01-05 13:03:07 -05:00
bymyself
6525389273 Update Settings schema (#2167) 2025-01-05 12:56:29 -05:00
Chenlei Hu
59fc5ac77e Update litegraph 0.8.60 (#2164) 2025-01-04 20:46:38 -05:00
bymyself
ed844e04b8 Fix text wrapping in dropdown menu (#2162) 2025-01-04 20:30:58 -05:00
bymyself
972af1977d Improve menu accessibility (#2163) 2025-01-04 20:30:27 -05:00
Chenlei Hu
5ac0b7b181 1.7.2 (#2161) 2025-01-04 19:42:15 -05:00
Chenlei Hu
31ea39e44c Prevent reference sharing on settingStore content (#2160) 2025-01-04 19:31:32 -05:00
Chenlei Hu
e65653c107 Add support for custom light color palette (#2156)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-04 18:53:47 -05:00
Chenlei Hu
e46706777c [BrowserTest] Disable flaky queue sidebar tests (#2158) 2025-01-04 16:33:36 -05:00
Chenlei Hu
1a817a48cb 1.7.1 (#2152) 2025-01-03 20:19:11 -05:00
Chenlei Hu
871967349f 1.7.0 (#2151)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-03 20:14:51 -05:00
filtered
11258f4a95 Revert markdown note node, reland as new node (#2148) 2025-01-03 16:05:23 -05:00
bymyself
c3e05c2a10 Add alt text to images in gallery and queue (#2136) 2025-01-03 13:49:06 -05:00
Chenlei Hu
ea1e776dcc Update litegraph 0.8.59 (#2140) 2025-01-03 11:15:16 -05:00
Dr.Lt.Data
f0c273f845 elaborate korean translation (#2137) 2025-01-03 11:14:56 -05:00
Chenlei Hu
ea489851ed [BugFix] Fix open workflow after insert (#2138) 2025-01-03 11:09:28 -05:00
Chenlei Hu
5717c33a0b [BrowserTest] Add test on paste with link (#2130)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-02 20:38:36 -05:00
Chenlei Hu
c31919c418 Remove invertMenuScrolling extension (#2131)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-02 20:19:00 -05:00
bymyself
2e7de4701e Reduce debounce delay in settings search (#2126) 2025-01-02 19:51:31 -05:00
Chenlei Hu
f53723da0f 1.6.15 (#2129) 2025-01-02 17:54:31 -05:00
bymyself
5c7cbe968e Fix gallery changing image every time a task finishes (#2125) 2025-01-02 17:51:28 -05:00
Chenlei Hu
cb607ee070 Update litegraph 0.8.58 (#2128) 2025-01-02 17:47:32 -05:00
Terry Jia
f4b5677901 [3d] support for fov and mask (#2116) 2025-01-02 15:45:37 -05:00
Chenlei Hu
9c1eacf0af Fix duplication of persisted workflow (#2124)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-02 12:16:39 -05:00
Chenlei Hu
bb988edf9f 1.6.14 (#2120) 2025-01-01 19:29:47 -05:00
Chenlei Hu
39e9f421f4 Fix double trigger of loadColorPalette effect (#2118)
Co-authored-by: github-actions <github-actions@github.com>
2025-01-01 19:27:22 -05:00
Chenlei Hu
3d2b9a8d9d Call api.storeSetting only when setting value changes (#2119) 2025-01-01 17:34:58 -05:00
pythongosssss
c77a5cab5b Add support for nested dynamic prompts (#2117) 2025-01-01 15:29:17 -05:00
Chenlei Hu
e525a3ad98 1.6.13 (#2115) 2024-12-31 19:05:26 -05:00
bymyself
f507142e6a Fix error when adding custom setting with no category (#2112)
Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-31 19:04:58 -05:00
Chenlei Hu
3189e310a8 Add default confirm dialog (#2114) 2024-12-31 18:18:48 -05:00
Chenlei Hu
174a9a114a Expose dialogService to extensionManager (#2113) 2024-12-31 17:01:37 -05:00
Chenlei Hu
0b3c0cc0c9 Fix i18n-custom-nodes action (#1991)
Co-authored-by: snomiao <snomiao@gmail.com>
2024-12-31 16:03:33 -05:00
bymyself
74b02237db Add virtual scroll to Queue Tab for improved performance (#2108) 2024-12-31 12:35:29 -05:00
bymyself
6dc5c6958f Compress test assets (#2109) 2024-12-31 12:33:29 -05:00
bymyself
70bece2d48 Update history task item schema (#2110) 2024-12-31 12:33:11 -05:00
bymyself
7eea2e5aa0 Increase width of settings dialog on mobile (#2111) 2024-12-31 12:30:40 -05:00
Chenlei Hu
eb94337c43 1.6.12 (#2107) 2024-12-30 21:30:07 -05:00
Chenlei Hu
98b96d2b1a Fix install view stepper layout shift (#2106) 2024-12-30 19:19:40 -05:00
Chenlei Hu
1b10e16b2d Adjust styles on various views (#2105) 2024-12-30 19:09:55 -05:00
Chenlei Hu
d8f074fea0 [Lint] Sort imports (#2104) 2024-12-30 17:26:37 -05:00
Chenlei Hu
e88817ea36 Lint/format vite.config.mts (#2103) 2024-12-30 16:48:57 -05:00
Chenlei Hu
4ae77e22d4 Add eslint to presubmit hook (#2102) 2024-12-30 16:47:12 -05:00
Chenlei Hu
9f23f81879 [Refactor] Move goToNode to litegraphService (#2101) 2024-12-30 16:38:10 -05:00
Chenlei Hu
3bf0dfd218 [Refactor] Move addNodeOnGraph to litegraphService (#2100) 2024-12-30 16:09:44 -05:00
Yuki Shindo
be7e2c6505 Add category-based filtering in settings search (#2086)
Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-30 11:23:02 -05:00
Chenlei Hu
6dce285210 Fix litegraph grab cursor style (#2097) 2024-12-30 10:50:53 -05:00
Zoltán Dócs
5218024395 Show workflow templates from custom nodes (#2032) 2024-12-29 22:26:03 -05:00
Chenlei Hu
92a5a8057f 1.6.11 (#2096) 2024-12-29 21:04:37 -05:00
Chenlei Hu
b19f7ca228 Add BaseViewTemplate (#2094) 2024-12-29 18:07:22 -05:00
Chenlei Hu
94f964cf17 [Cleanup] Remove legacy slow jest test utils (#2093) 2024-12-29 17:05:05 -05:00
Chenlei Hu
a7fd9bf0d9 Remove life on default error handler toast (#2091) 2024-12-29 16:42:09 -05:00
Chenlei Hu
642094ead1 Remove legacy slow jest tests (#2092) 2024-12-29 16:25:06 -05:00
Chenlei Hu
95a4623c37 Re-enable keybinding jest test (#2090) 2024-12-29 14:55:18 -05:00
Chenlei Hu
773059da93 1.6.10 (#2087) 2024-12-28 21:37:03 -05:00
Chenlei Hu
a48ad1cb41 Move setting impl from ComfySettingsDialog to settingStore (#2085) 2024-12-28 21:31:09 -05:00
Chenlei Hu
5152985656 [Refactor] Rename settingStore.settings to settingsById (#2081) 2024-12-28 17:39:40 -05:00
Chenlei Hu
ab33eb6262 Remove legacy menu setting Comfy.MenuPosition (#2080)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-27 23:15:43 -05:00
Chenlei Hu
af1a5d9dbc Fix Comfy.WidgetControlMode watcher (#2079) 2024-12-27 22:42:41 -05:00
Chenlei Hu
feabd3f11d [Refactor] Move Comfy.WidgetControlMode to coreSettings (#2078) 2024-12-27 21:06:23 -05:00
Chenlei Hu
74361eebe0 1.6.9 (#2077) 2024-12-27 18:56:46 -05:00
Yuki Shindo
20412f2c74 Enable category-based narrowing and reset to default on search clear (#2071)
Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-27 18:06:50 -05:00
Chenlei Hu
861d559f19 Update litegraph 0.8.50 (#2076) 2024-12-27 14:13:36 -05:00
Chenlei Hu
7cb0c230df [Refactor] Move app.registerNodeDef to litegraphService (#2075) 2024-12-27 13:08:42 -05:00
Chenlei Hu
9d94802e26 Activate French translation (#2074) 2024-12-27 10:35:21 -05:00
filtered
34492aed17 Fix context menu text blurred by CSS filter (#2069) 2024-12-27 10:31:17 -05:00
Gremlation
a3be889872 Add Markdown table support to the Note node (#2072) 2024-12-27 10:30:47 -05:00
Chenlei Hu
9acb5abf58 1.6.8 (#2070) 2024-12-26 20:33:03 -05:00
Chenlei Hu
b9edd05623 [i18n] Add French translation (#2064)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-26 20:31:31 -05:00
Chenlei Hu
56a243f958 [Refactor] Deprecate ComfyApp.progress (#2065) 2024-12-26 15:21:58 -05:00
Chenlei Hu
c311806249 [Refactor] Move keybinds extension to keybindingService (#2063) 2024-12-26 13:19:04 -05:00
gremlation
7990491c58 Add Markdown support to the Note node (#2044) 2024-12-26 13:16:00 -05:00
Chenlei Hu
66ada54587 [Refactor] Move vintageClipboard to utils/ (#2062) 2024-12-26 12:55:58 -05:00
DorotaL
a5f9fa006c [i18n] Update zh translations (#2061)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-26 10:55:40 -05:00
Chenlei Hu
f69e88bf41 [Refactor] Convert dialogService to composable (#2058) 2024-12-26 00:26:01 -05:00
Chenlei Hu
4e554503c0 [Refactor] Convert workflowService to composable (#2057) 2024-12-26 00:11:27 -05:00
Chenlei Hu
c00d665aa5 Update litegraph 0.8.49 (#2056) 2024-12-25 23:20:28 -05:00
Chenlei Hu
cce11bb639 Move extension related functions from app to extensionService (#2055) 2024-12-25 23:19:25 -05:00
Chenlei Hu
7771802038 1.6.7 (#2054) 2024-12-25 22:47:42 -05:00
Chenlei Hu
9d7a7dae62 [Theme] Loosen color palette schema (#2053) 2024-12-25 22:47:10 -05:00
Chenlei Hu
e7528f13a2 [Theme] Fallback secondary menu bg to menu bg if not set (#2052) 2024-12-25 21:59:37 -05:00
Chenlei Hu
f851e356f2 Fix flaky reroute insert playwright test (#2051)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-25 21:57:52 -05:00
Chenlei Hu
db572a4085 Implement color palette in Vue (#2047)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-25 21:41:48 -05:00
Chenlei Hu
f1eee96ebc Ignore hidden settings for translation (#2050)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-25 21:26:52 -05:00
Dr.Lt.Data
d11fad8a06 Fix Korean translation (#2049)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-25 19:44:00 -05:00
Chenlei Hu
e961e64497 1.6.6 (#2046) 2024-12-24 17:20:25 -05:00
filtered
006d544ac5 Improve install path validation and i18n (#2042)
Co-authored-by: huchenlei <huchenlei@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
2024-12-24 14:36:32 -05:00
filtered
467b35f98d Add i18n for next/back/install buttons (#2045)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-24 14:01:54 -05:00
Chenlei Hu
eb43234a3a Fix extension panel search/sort (#2041)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-24 10:51:41 -05:00
bymyself
5da26e917a Fix render issue when removing search filter chips (#2038) 2024-12-24 10:13:14 -05:00
bymyself
96b2987590 Fix batch count limit (#2039) 2024-12-24 10:12:38 -05:00
filtered
653ed6f096 Fix reroutes not included in Insert Workflow (#2037) 2024-12-23 23:24:54 -05:00
Chenlei Hu
3cb303ff05 1.6.5 (#2036) 2024-12-23 21:43:46 -05:00
Chenlei Hu
af6cb31214 Move color palettes to constants/coreColorPalettes.ts (#2035) 2024-12-23 21:43:30 -05:00
Chenlei Hu
54ca111c7c Fix FormItem structure (#2034) 2024-12-23 21:33:03 -05:00
Chenlei Hu
e2bbfe7d80 Fix NODE_DEFAULT_SHAPE in color palette (#2033)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-23 20:44:52 -05:00
Chenlei Hu
3b9a5a61b2 Add color picker and image upload form items (#2031)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-23 16:10:15 -05:00
Chenlei Hu
27ec6139a8 Translate keybinding panel table header (#2030)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-23 14:54:12 -05:00
Chenlei Hu
fa06d6ea99 [Refactor] Split color palettes into separate json files (#2029) 2024-12-23 14:42:03 -05:00
Chenlei Hu
47435cdfed Fix docked actionbar expanding menu height (#2027) 2024-12-23 10:15:05 -05:00
Fahd Arafat
cfb884b118 Rearrange workflow tabs (#2026) 2024-12-23 09:51:17 -05:00
pythongosssss
1af0b4f992 [Electron] Migrate custom nodes (#1892)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-23 09:33:48 -05:00
bymyself
c36e55f0b7 Auto-focus node filter search (#2024) 2024-12-23 09:27:32 -05:00
bymyself
9f6c828cfe Fix search input failing to focus after adding filter (#2023) 2024-12-23 09:27:17 -05:00
bymyself
cf51254d24 Remove defineProps import (#2025) 2024-12-23 09:25:47 -05:00
Chenlei Hu
b0cc5eac95 1.6.4 (#2021) 2024-12-22 19:52:40 -05:00
bymyself
feeb1d19c8 Fix workflow-insert with reroute nodes (#2008)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-22 19:51:32 -05:00
Chenlei Hu
920266e1ff [ExtensionPanel] Distinguish core and 3rd party extensions (#2020) 2024-12-22 19:41:28 -05:00
Chenlei Hu
b81ccc0507 [ExtensionPanel] Add disable all / enable all actions (#2017)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-22 18:57:58 -05:00
shinich39
f4c523f188 Bypass selected nodes (#2013)
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2024-12-22 16:51:28 -05:00
AustinMroz
cce5ade578 Fix memory leak in preview code (#2012)
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2024-12-22 16:18:31 -05:00
filtered
3767749398 Add About to Help menu (#2010)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-22 16:17:25 -05:00
bymyself
c3ceef0461 Update mobile settings visibility test (#2009) 2024-12-22 16:16:11 -05:00
Terry Jia
ac952fbee3 [3d] fix file path issue for preview 3d node (#2005) 2024-12-22 16:13:15 -05:00
Chenlei Hu
72f7c3101d Always show extension panel in settings dialog (#2002)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-20 16:30:11 -08:00
Chenlei Hu
ca9627cada Move widget link drop conversion to widgetInputs (#2001)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-20 16:10:18 -08:00
Chenlei Hu
c8f62cd963 1.6.3 (#1997) 2024-12-19 18:12:59 -08:00
Chenlei Hu
9900e46b95 Unify title edit handling (#1995) 2024-12-19 16:56:26 -08:00
Chenlei Hu
c433b38ba8 [CNR] Support module sytax of <node name>@<version> (#1994) 2024-12-19 14:48:33 -08:00
Chenlei Hu
0b501d7a1c Add DorotaLuna to translation codeowner (#1990) 2024-12-19 09:46:17 -08:00
Yuki Shindo
0e197261b0 Add Clear Functionality in the SearchBox (#1989)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-19 09:40:08 -08:00
Chenlei Hu
89bf5c182d Add AIGODLIKE team to translation codeowner (#1983) 2024-12-18 19:26:19 -08:00
Chenlei Hu
e80c75482e 1.6.2 (#1988) 2024-12-18 17:45:38 -08:00
Chenlei Hu
569a131624 [i18n] Add gihtub action to translate custom nodes (#1987) 2024-12-18 17:04:35 -08:00
Chenlei Hu
b1d02c6a7b [i18n] Split settings locale to separate json files (#1986)
Co-authored-by: github-actions <github-actions@github.com>
2024-12-18 14:57:05 -08:00
Zoltán Dócs
abeafd5625 Save sidebar width per tab (#1985) 2024-12-18 14:56:27 -08:00
Chenlei Hu
0906d7873a Update locales (Sync core node defs)(#1984) 2024-12-18 13:24:11 -08:00
Chenlei Hu
0ce3f1ecb0 Update README.md (#1982) 2024-12-18 12:23:00 -08:00
Chenlei Hu
ec6919c5ab 1.6.1 (#1979) 2024-12-17 17:20:50 -08:00
Laurent Erignoux
10de690ccf Updating workflow template to use relative url and ensure resources can be accessed behind a url rewriting proxy. (#1922)
Co-authored-by: Erignoux Laurent <laurent.erignoux@ubisoft.com>
2024-12-17 13:09:38 -08:00
filtered
cb3e4b5ed7 [Refactor] Clean up image nodes, add TS types (#1927)
* [Refactor] Clean up image nodes, add TS types

Should be no functional changes.

* Remove unused code
2024-12-17 13:09:24 -08:00
filtered
2b4ac582d4 Add manual configuration screen (#1926)
* Add manual configuration screen

* nit

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-17 09:52:30 -08:00
filtered
7f60811ebf Fix cannot open groupNodes menu from canvas (#1925)
* Fix cannot open groupNode menu from canvas

* Fix cannot open groupNode menu from canvas

Fixes root cause of issue

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-17 09:47:09 -08:00
Chenlei Hu
90e94df1e4 1.6.0 (#1921) 2024-12-16 18:52:35 -08:00
Hayden
5b72fc7fdc Optimize model library (#1739)
* Adapt experiment models api

* Add model preview
2024-12-16 15:27:30 -08:00
filtered
601b739f75 Add GPU selection to desktop installer (#1888)
* Remove redundant code

* Add GPU picker screen to installer

* Permit jumping installation steps when visited

* Prevent sad girl from covering buttons

* Update gpu options to match availability

* Ensure install screen renders inside bounds

* Pre-select GPU detected by desktop native

* Redesign GPU selection screen

* Prevent text highlight on installer stepper

* Add translations for GPU picker

* Rename for clarity

* Remove unused code

* Update electron types

* Update locales [skip ci]

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
2024-12-16 15:26:40 -08:00
Fahd Arafat
a441908db3 display cancelled worklflow images (#1920) 2024-12-16 14:45:49 -08:00
Terry Jia
a376503a7b [3d] improve Preview 3d node (#1918) 2024-12-16 11:56:20 -08:00
Chenlei Hu
69a4a17848 [Multi-User] Press enter in new username textbox trigger login (#1919)
* [Multi-User] Press enter in new username textbox trigger login

* nit
2024-12-16 10:34:33 -08:00
Chenlei Hu
22f9ad31dc 1.5.18 (#1916) 2024-12-15 16:39:43 -08:00
Fahd Arafat
2a02159355 fix settings not showing on small screens (#1914) 2024-12-15 15:40:40 -08:00
Chenlei Hu
9258098e0c [litegraph] Fix slider value display when custom widget label is present (#1915)
* Update litegraph

* Add playwright test

* Update locales [skip ci]

* Update test expectations [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-15 13:54:03 -08:00
Fahd Arafat
fa48fe587d forward mouse events from textareas to canvas (#1911)
* forward mouse events from textareas to canvas

* use arrow functions

* Apply suggestions from code review

Use pointer events instead of mouse to get extended properties
Remove workaround (only required due to missing extended properties)

* Apply code review - Adjust UX

- Do not prevent middle click from hitting DOM widgets
- Allow middle click and drag to continue functioning if another button is held down

---------

Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2024-12-15 12:50:32 -08:00
Terry Jia
7b64bfa173 [3d] Set view only when object exists (#1912)
* [3d] Set view only when object exists

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-15 10:57:34 -08:00
Chenlei Hu
59b62eadf1 [i18n] Translate save/export workflow dialog (#1906)
* [i18n] Translate save/export workflow dialog

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-13 16:56:37 -08:00
Chenlei Hu
98912efeb7 1.5.17 (#1907) 2024-12-13 16:55:52 -08:00
Fahd Arafat
c7303ea465 Add new workflow button in topbar for tab view (#1903) 2024-12-13 14:14:13 -08:00
Chenlei Hu
618b451f1e [test] Stricter locator matching on workflows sidebar elements (#1905)
* [test] Stricter locator matching on workflows sidebar elements

* nit
2024-12-13 14:13:56 -08:00
Chenlei Hu
a99f63784d Fix io slot label overwrite by i18n (#1904)
* Add test on export with different locales

* Fix node slot rename
2024-12-13 12:27:16 -08:00
Yoland Yan
6f7c7f3c61 Update default value for 'Opened workflows position' setting from 'Sidebar' to 'Topbar' in coreSettings.ts (#1902) 2024-12-13 09:45:52 -08:00
Chenlei Hu
4f049b66a2 1.5.16 (#1901) 2024-12-13 08:50:18 -08:00
Chenlei Hu
458ff350c8 1.5.15 (#1900)
* 1.5.15

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-13 08:24:01 -08:00
Chenlei Hu
fc8c10bca4 Add Comfy-Desktop.OpenUserGuide in help menu (#1896)
* Add Comfy-Desktop.OpenUserGuide in help menu

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-12 16:39:54 -08:00
filtered
28ab86cd4a Fix #1769 - Keep log on screen after installation error (#1891)
* Hide terminal on server start error

* nit - Doc

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-12 14:41:07 -08:00
Chenlei Hu
efb6f8afe3 Proper fix on locale message type (#1894) 2024-12-12 14:26:43 -08:00
Chenlei Hu
a2549f23c7 Fix circular dependency on updating missing locale (#1893) 2024-12-12 12:26:18 -08:00
oto-ciulis-tt
7877c96ffe feat: Add more server side arguments (#1846)
* feat: Add more server side arguments

* nit

* Update locales [skip ci]

---------

Co-authored-by: Oto Ciulis <oto.ciulis@gmail.com>
Co-authored-by: huchenlei <huchenlei@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
2024-12-12 11:18:21 -08:00
Chenlei Hu
4997d13219 [i18n] Add commands label translation (#1890)
* [i18n] Add commands label translation

* Use translation
2024-12-12 09:28:47 -08:00
Chenlei Hu
c5135afd29 [i18n] Fix some unintuitive Chinese translations (#1889) 2024-12-12 08:32:53 -08:00
Chenlei Hu
8663340067 1.5.14 (#1886) 2024-12-11 20:03:31 -08:00
Chenlei Hu
a1ffc521a4 [i18n] Update i18n on node defs (#1885)
* [i18n] Update i18n on node defs

* Update test expectations [skip ci]

* Downgrade i18n-cli

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-11 19:59:51 -08:00
Chenlei Hu
f7dce3116a 1.5.13 (#1884) 2024-12-11 18:05:11 -08:00
Chenlei Hu
f23530afcf [i18n] Translate widget label (#1883)
* [i18n] Translate widget label

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-11 18:03:56 -08:00
Chenlei Hu
c5f77de1bf [CSS] Use brighter secondary menu color in light mode (#1882) 2024-12-11 16:11:12 -08:00
Chenlei Hu
c60645d9f4 [i18n] Translate node input label (#1880) 2024-12-11 14:57:49 -08:00
Chenlei Hu
ebbff358a0 [i18n] Fix untranslated dataTypes in ru (#1879) 2024-12-11 12:13:39 -08:00
Chenlei Hu
a39c04d56e [i18n] Split nodeDefs translations to a separate json file (#1878)
* [i18n] Split nodeDefs translations to a separate json file

* build locale
2024-12-11 11:51:54 -08:00
Chenlei Hu
9e61d1509f [i18n] Fix ko translation schema (#1877) 2024-12-11 11:38:00 -08:00
Chenlei Hu
0c511d08e6 [i18n] Use folder mode for locale (#1876)
* [i18n] Use folder mode for locale

* try pipe
2024-12-11 11:29:52 -08:00
filtered
929e3a5733 Add native context menu when using desktop (#1875)
* Add system menu to elements

* Add desktop text context menu control

* Update electron types

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-11 11:29:14 -08:00
Chenlei Hu
75c98d00fc [i18n] Fix node output label translation (#1871) 2024-12-11 09:36:44 -08:00
Chenlei Hu
7bce5ac4d0 1.5.12 (#1868) 2024-12-11 08:33:16 -08:00
Chenlei Hu
e7733d94f9 [i18n] Supress expected translation/fallback warnings (#1867) 2024-12-11 08:32:50 -08:00
Chenlei Hu
20a3a95df2 Fix output label on untranslated output names (#1866)
* Fix output label on untranslated output names

* nit

* Update test expectations [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-11 08:09:37 -08:00
Yuki Shindo
d2bbf41fb5 Add translated setting names to the search index for improved localization support (#1865)
* feat: add translated setting names to the search index for improved localization support

* nit

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-11 08:07:41 -08:00
Chenlei Hu
97ccc6a854 1.5.11 (#1862) 2024-12-10 17:10:36 -08:00
Chenlei Hu
b48619878f Replace deprecated InputSwitch with ToggleSwitch (#1861) 2024-12-10 17:08:58 -08:00
Chenlei Hu
ac6130a556 [i18n] Translate node input/output label and tooltip (#1860)
* [i18n] Translate node input/output labels

* nit

* Impl actual translation

* Remove outputs where name is the type

* Pick outputs key

* Translate outputs

* Properly persist label

* Translate input tooltips

* Translate single node

* Translate first node

* Translate 10 nodes

* Exclude input name translation

* Update test expectations [skip ci]

* nit

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-10 17:08:45 -08:00
Chenlei Hu
86797d2492 [i18n] Collect node data types (#1859)
* [i18n] Collect node data types

* nit

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-10 11:29:54 -08:00
Chenlei Hu
112a693f3d [i18n] Translate setting options (#1858)
* Collect options

* Translate setting options

* Update locales [skip ci]

* Normalize key

* Revert change of logic

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-10 09:31:13 -08:00
oto-ciulis-tt
57701f6145 feat: Adding indicator for completed download (#1852)
* feat: Adding indicator for completed download

* Reverting changes

* Inline color style

---------

Co-authored-by: Oto Ciulis <oto.ciulis@gmail.com>
Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-09 15:09:33 -08:00
filtered
c2145b6f45 Adjust UI theme slightly (#1853)
* Format CSS - prettier

* Cast Minor Shadows

Adds faint shadows to the top and side bars

* Darken the sidebar slightly

* Add theme config for bar shadows

* Fix menu item alignment and spacing

* [Refactor] Prefer canvas setDirty over draw

- nits
- types
2024-12-09 15:03:14 -08:00
Chenlei Hu
0b91d53c9f 1.5.10 (#1850) 2024-12-08 20:42:27 -05:00
Chenlei Hu
b4ccaf4fec Rename EditAttention to EditTokenWeight (#1848)
* Rename EditAttention to EditTokenWeight

* Update locales [skip ci]

* Remove EditAttention

* nit

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-08 20:22:09 -05:00
Chenlei Hu
2d1b2cb1cc Fix group node playwright tests (#1849)
* Fix group node playwright tests

* nit

* nit
2024-12-08 20:21:59 -05:00
Chenlei Hu
aa04ab78c1 Replace window.prompt with custom prompt impl (#1847)
* Replace window.prompt with custom prompt impl

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-08 16:55:32 -05:00
Chenlei Hu
1671437fb3 Fix korea translation activation (#1845)
* Fix korea translation activation

* nit
2024-12-08 11:48:05 -05:00
Chenlei Hu
9d49cb0e4b Add support for korea translation (#1830)
* Add support for korea translation

* Update locales [skip ci]

* Update ko.json

* Update locales [skip ci]

* Update ko.json

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Dr.Lt.Data <128333288+ltdrdata@users.noreply.github.com>
2024-12-08 11:44:36 -05:00
Chenlei Hu
43548785b5 Fix Comfy-Desktop.Reinstall command label (#1844) 2024-12-07 22:13:03 -05:00
Chenlei Hu
b6038128cb [i18n] g global namespace (#1843)
* Batch move global scope i18n to g. namespace

* Minor fix

* Update locale

* Update locales [skip ci]

* More moves

* Regroup icon/color

* nit

* Fix component test

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-07 22:07:03 -05:00
Chenlei Hu
a76159e9a0 [i18n] Translate node categories (#1842)
* [i18n] Translate node categories

* nit

* Update locales [skip ci]

* Fix some translations

* Do translate

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-07 21:25:40 -05:00
Chenlei Hu
a0ff78dbdb 1.5.9 (#1840) 2024-12-07 18:54:26 -05:00
Yuki Shindo
059dfcbebb Use i18n keys for workflow tree type labels (#1839)
* fix: use i18n keys for workflow tree type labels

* Inline translations

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-07 18:52:52 -05:00
Chenlei Hu
c17d44638e [i18n] Safe fallback to original string (#1838)
* [i18n] Safe fallback to original string

* nit
2024-12-07 18:48:14 -05:00
filtered
0e385c4262 Require confirmation for desktop reinstall (#1835)
* Add generic default button for unknown dialogs

* Add reinstall confirmation dialog

* Prevent removal of newlines in i18n dialogs

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-07 10:24:00 -05:00
Chenlei Hu
da98b1c4cc Update CODEOWNER matching rule (#1836) 2024-12-07 10:23:43 -05:00
Chenlei Hu
26d2e5de31 Add code owners (#1832)
* Add code owners

* nit
2024-12-06 22:29:21 -05:00
filtered
b0e37036d5 Fix missing titles during desktop installation (#1831)
* Add missing desktop translation keys

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-06 22:18:19 -05:00
Chenlei Hu
b7ddb47d2a 1.5.8 (#1829) 2024-12-06 21:29:11 -05:00
Yuki Shindo
6eb5ee99d8 feat: use friendly language names for Comfy.Locale setting options (#1828) 2024-12-06 20:19:01 -05:00
Chenlei Hu
6409e17d4a Hint for empty canvas when invoking Comfy.Canvas.FitView (#1826) 2024-12-06 18:07:01 -05:00
Yuki Shindo
a6549fb41e docs: Localize menu paths in firstTimeUIMessage (#1825) 2024-12-06 18:06:43 -05:00
Yuki Shindo
06d5064b7c fix: updated About label translation to a more appropriate Japanese term (#1827) 2024-12-06 18:06:20 -05:00
Chenlei Hu
fd621f485e Reload current workflow when locale changes (#1824) 2024-12-06 17:37:25 -05:00
Chenlei Hu
517ae56763 Translate node title and description (#1822)
* Collect node def i18n

* Add collected en locale

* Sort by node id

* Add translations

* Show translated node def

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-06 16:56:54 -05:00
Chenlei Hu
ae26390776 Properly implement ComfyNodeDef interface (#1821)
* nit

* Properly implement ComfyNodeDef interface

* nit

* Mark readonly
2024-12-06 12:00:15 -05:00
Chenlei Hu
aa68422e0f 1.5.7 (#1818) 2024-12-05 20:00:18 -05:00
Chenlei Hu
dac2a2ec86 [Electron] Translate server config panel (#1817)
* Update i18 collection to include server config items

* Use translation

* Update locales [skip ci]

* nit

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-05 19:56:51 -05:00
Chenlei Hu
5cee4d828f [Electron] Use shortname for server config disable-smart-memory (#1816) 2024-12-05 17:17:24 -05:00
Chenlei Hu
d6247d69ce [Electron] Hide auto-launch in server config (#1815) 2024-12-05 17:02:17 -05:00
Chenlei Hu
e2fa1e65d1 Add Workspace.SearchBox.Toggle command (#1814)
* Add Workspace.SearchBox.Toggle command

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-05 15:30:02 -05:00
Chenlei Hu
55c04b5533 [Electron] Allow force install on not supported device page (#1812)
* [Electron] Allow force install on not supported device page

* Update locales [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-12-05 12:06:51 -05:00
Chenlei Hu
540e785424 Reland "Replace magic numbers with LGraphEventMode (#1809)" (#1811)
* Revert "Revert "Replace magic numbers with LGraphEventMode (#1809)" (#1810)"

This reverts commit 30a92d40eb.

* Update litegraph
2024-12-05 11:48:07 -05:00
Chenlei Hu
30a92d40eb Revert "Replace magic numbers with LGraphEventMode (#1809)" (#1810)
This reverts commit 679405e0a2.
2024-12-05 11:29:41 -05:00
Chenlei Hu
679405e0a2 Replace magic numbers with LGraphEventMode (#1809) 2024-12-05 11:27:43 -05:00
Chenlei Hu
6cdc524174 Align desktop version badge format with other badges (#1808) 2024-12-05 11:11:28 -05:00
Chenlei Hu
80a42ebf10 Fix fallback of unrecognized extension categories (#1807) 2024-12-05 11:06:06 -05:00
Chenlei Hu
c45f03f5e7 1.5.6 (#1805) 2024-12-04 22:35:06 -05:00
Chenlei Hu
36c2604639 [Electron] Use electronAPI to get ComfyUI core version (#1804) 2024-12-04 22:34:55 -05:00
Chenlei Hu
73f50e7e0b Replace locale presubmit hook with Github action (#1802)
* Replace locale presubmit hook with Github action

* nit

* Make sure electronAPI is defined on window object

* Set correct env var
2024-12-04 21:43:02 -05:00
Chenlei Hu
418fddd669 Revert "Fix setting list nav separator (#1799)" (#1803)
This reverts commit 30465f17e0.
2024-12-04 17:26:44 -08:00
Chenlei Hu
e3cda0e749 Translate queue buttom modes (#1800)
* Translate queue button

* Update label

* nit
2024-12-04 17:43:06 -05:00
Chenlei Hu
30465f17e0 Fix setting list nav separator (#1799) 2024-12-04 16:37:38 -05:00
Chenlei Hu
5206939c78 Translate setting categories (#1797)
* Add i18n for setting categories

* Update locales

* Translate about

* nit

* nit
2024-12-04 16:32:28 -05:00
Chenlei Hu
73396784a8 Keep shim of several legacy components (#1796) 2024-12-04 15:45:38 -05:00
Chenlei Hu
3745d8d791 Remove logging module (#1795)
* Remove logging module

* Remove translation
2024-12-04 14:16:43 -05:00
filtered
735153886f Confirm delete workflow (#1772)
* Add confirm delete workflow prompt

* Add confirm delete workflow setting

* Add delete workflow tests

* Change dialog to modal, set default cancel

* Fix setting version key

* Rename for clarity

* Fix tests

- Move into correct section
- Add confirm control

* Export type: ShowDialogOptions

* Replace workflow overwrite with new dialog

* Add delete workflow confirmation dialog

* Update i18n

* Add item list support to confirmation dialog

* Prevent multiple dialogs for same action

* Add confirm close file when dirty

* Add i18n for overwrite dialog

* Fix regression: confirm dialog setting ignored

* Fix delete last workflow does not open replacement

* Update tests
2024-12-04 14:11:49 -05:00
Chenlei Hu
d04cc4e272 Translate dynamically added settings (#1794)
* Collect settings i18n at runtime

* Translation

* Remove unused file
2024-12-04 13:51:37 -05:00
Chenlei Hu
473aa120eb Fix extra_model_paths_yaml i18n key (#1793) 2024-12-04 13:25:04 -05:00
Chenlei Hu
7986aebf27 Translate command label on top command dropdown menu (#1792)
* collect i18n with playwright

* Add command label translation

* Normalize i18n object key
2024-12-04 13:19:53 -05:00
filtered
2caa87d35d Prevent interface crash from dialog abuse (#1789)
- Adds hard-coded limit of 10 open dialogs
- Discards the oldest item on the dialog stack to maintain size
2024-12-04 10:09:06 -05:00
Chenlei Hu
dabcd4741b [Refactor] Extract command definitions to coreCommandHooks (#1785)
* [Refactor] Extract command definitions to coreCommandHooks

* Register core commands

* Fix rebase issue
2024-12-03 23:06:19 -05:00
Hayden
e893f3ed03 Add a unique key to each showDialog (#1786) 2024-12-03 23:04:27 -05:00
Chenlei Hu
1856479de9 Translate topbar command menu (#1784)
* Rename script

* Translate menu labels

* Update translations

* Display translated menu items
2024-12-03 22:51:15 -05:00
Chenlei Hu
fc69129a2f 1.5.5 (#1783) 2024-12-03 22:05:35 -05:00
Chenlei Hu
d953b8fa46 Merge core settings with existing translations (#1782) 2024-12-03 22:04:19 -05:00
Yuki Shindo
1847db7a47 chore: add locale keys for settings dialog (i18n) (#1779) 2024-12-03 17:27:13 -08:00
Chenlei Hu
9cbcda20a7 [Refactor] Extract top menu bar command definitions (#1778) 2024-12-03 17:17:15 -08:00
filtered
0fe0aea242 Fix keybinds invalidated by capslock state (#1776)
* [Refactor] Simplify keybinds code

* [Refactor] Type safety

* Fix capslock inverts undo/redo shortcuts

* [Refactor] Type safety

* Fix capslock state changes keybinds

* Deprecate keybind deserialize

* Remove keybind deserialize
2024-12-03 19:12:09 -05:00
Chenlei Hu
08ae36818a Fix litegraph types in NodeSearchBoxPopover (#1777) 2024-12-03 19:07:15 -05:00
Chenlei Hu
da6b4d2872 Disable install button when there is error (#1775) 2024-12-03 14:34:03 -05:00
Chenlei Hu
8e293b41f5 [Refactor] Remove abstract inheritance of node search filter (#1774) 2024-12-03 11:39:29 -05:00
Chenlei Hu
d2771a7a1d Always include node title metadata for API export (#1771) 2024-12-02 22:49:42 -05:00
Chenlei Hu
13869da300 1.5.4 (#1770) 2024-12-02 22:09:49 -05:00
filtered
6ba53f3af1 Keep log on screen after installation error (#1769) 2024-12-02 21:57:30 -05:00
Tristan Sommer
b23cebcba4 maskeditor: massive improvements to brush opacity in brush strokes and lines (#1768)
* massive improvements to brush opacity in brush strokes and lines, improved save button visibility

* prettier formatting fixed
2024-12-02 18:16:18 -08:00
pythongosssss
30dfe76577 Allow copy/paste in terminal (#1760) 2024-12-02 19:55:14 -05:00
Chenlei Hu
c1f0cfe366 Move Comfy.EnableWorkflowViewRestore to coreSettings (#1767) 2024-12-02 17:50:46 -05:00
Chenlei Hu
d1279fa474 Move Comfy.TreeExplorer.ItemPadding to Appearance category (#1766) 2024-12-02 17:38:46 -05:00
Chenlei Hu
a56462fc7c Translate core setting name & tooltip (#1765)
* lazy eval default value

* Add setting translation

* Adjust hooks

* Add all translations

* nit

* Normalized setting id

* Update locales

* Fallback

* Locale => Language

* Locale => Language

* Update translations
2024-12-02 17:34:21 -05:00
Chenlei Hu
646bcf595b Revert "Bump @intlify/core-base and vue-i18n (#1762)" (#1764)
This reverts commit 01ac9d9336.
2024-12-02 15:22:49 -05:00
Chenlei Hu
4796677a0a Create presubmit hooks for i18n (#1763)
* Add locale scripts to package.json

* Add i18n hooks
2024-12-02 15:10:53 -05:00
dependabot[bot]
01ac9d9336 Bump @intlify/core-base and vue-i18n (#1762)
Bumps [@intlify/core-base](https://github.com/intlify/vue-i18n/tree/HEAD/packages/core) to 9.14.2 and updates ancestor dependency [vue-i18n](https://github.com/intlify/vue-i18n/tree/HEAD/packages/vue-i18n). These dependencies need to be updated together.


Updates `@intlify/core-base` from 9.13.1 to 9.14.2
- [Release notes](https://github.com/intlify/vue-i18n/releases)
- [Changelog](https://github.com/intlify/vue-i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/intlify/vue-i18n/commits/v9.14.2/packages/core)

Updates `vue-i18n` from 9.13.1 to 9.14.2
- [Release notes](https://github.com/intlify/vue-i18n/releases)
- [Changelog](https://github.com/intlify/vue-i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/intlify/vue-i18n/commits/v9.14.2/packages/vue-i18n)

---
updated-dependencies:
- dependency-name: "@intlify/core-base"
  dependency-type: indirect
- dependency-name: vue-i18n
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-02 15:10:03 -05:00
pythongosssss
89a9288154 Support closing tab with middle click (#1761) 2024-12-02 15:09:46 -05:00
pythongosssss
17b7ef18d6 Add context menu to tabs (#1759)
* Add context menu to tabs

* Flatten menu
Translate

* Add translations

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-02 13:19:39 -05:00
Yuki Shindo
1afc584393 fix: remove unnecessary $t calls for column headers (#1758) 2024-12-02 09:47:08 -05:00
Chenlei Hu
9d71cdf8ef 1.5.3 (#1756) 2024-12-01 22:48:49 -05:00
pythongosssss
1c7f3e865a Add test for cloning pinned node (#1753)
* Add test for cloning pinned node

* Remove only

* Update litegraph

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
2024-12-01 22:38:09 -05:00
Yuki Shindo
9ef40189f9 Add lobe-i18n setup and translation scripts and update translation files for consistency (#1751)
* refactor: convert translation files from TS to JSON format

* feat: add lobe-i18n setup and translation scripts

* chore: update translation files for consistency

* chore: refine translations in ja_JP.json for natural phrasing

* refactor: revert locale file names to original simpler format (e.g., en_US → en)
2024-12-01 20:03:17 -05:00
pythongosssss
5c6eecd660 Fix group node manage opening to wrong node type (#1754)
Remove dialog from DOM when closed
Add test
2024-12-01 19:52:08 -05:00
filtered
9b07993e1a Clear console error - missed API type (#1749) 2024-11-30 09:47:15 -05:00
Chenlei Hu
c35d29f31c 1.5.2 (#1745) 2024-11-29 17:31:10 -05:00
Chenlei Hu
e50d7c5eef Update litegraph 0.8.41 (#1744)
* chore: update litegraph to 0.8.41

* Update test expectations [skip ci]

---------

Co-authored-by: github-actions <github-actions@github.com>
2024-11-29 17:30:04 -05:00
filtered
7c2cce40de Add default setting for node error colour (#1738) 2024-11-29 13:20:54 -05:00
filtered
2017b9016b Add TS types - API (#1736)
* nit

* Add TS types - API events

* Replace all API event emits with type-safe variants

* Add missing API type

* nit

* Remove test code, nit
2024-11-29 13:15:25 -05:00
filtered
0bf30e7621 Add git download page (#1742) 2024-11-29 13:12:09 -05:00
Chenlei Hu
7f5b685c9f Add current user message in settings dialog (#1740) 2024-11-29 11:24:21 -05:00
Yuki Shindo
ec824579d6 docs: add i18n section to README with instructions for adding new languages (#1735) 2024-11-29 10:57:37 -05:00
Chenlei Hu
9e565154a9 Rework user selection (#1728)
* Move to new route

* Convert to tailwind

* Basic style

* Add userStore

* nit

* nit

* nit

* Remove app.#setUser

* Route to user-select view

* Mock login

* Use primevue UI components

* handle create new user

* Remove legacy user selection

* Add logout button on side toolbar

* Add username to logout button tooltip

* Add playwright tests

* hide logout button in single user server

* nit
2024-11-28 23:36:41 -05:00
Chenlei Hu
541335bb31 1.5.1 (#1734) 2024-11-28 17:25:52 -05:00
Chenlei Hu
814c4b8ef0 Remove node bookmark migration (#1733)
* Remove node bookmarks setting migration

* nit

* nit
2024-11-28 14:28:53 -05:00
Chenlei Hu
df3fff5dbb Remove migration logic (settings & templates storage location) (#1732)
* Remove isNewUserSession handling

* Remove writing of setting and templates to localStorage
2024-11-28 14:24:06 -05:00
Chenlei Hu
b0085114d7 Remove app.storageLocation handling (#1731) 2024-11-28 13:35:08 -05:00
Chenlei Hu
7f9c70386f Update package.json (Fix repo name) (#1729) 2024-11-28 12:41:28 -05:00
filtered
578870d345 Add canvas maximum FPS setting (#1727)
* Add canvas maximum FPS setting

* Update litegraph

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
2024-11-28 11:46:54 -05:00
Chenlei Hu
05fab91bda Build comfyui-frontend-types library (#1725)
* Install vite-plugin-dts

* Explicitly type workflowStore

* Working rollup

* Hide diff type

* Inline primevue toast mesage types

* Add prepare-types script to generate package.json for type package

* Add global declaration

* Add publish types Github action

* Update litegraph

* Add @comfyorg to package name
2024-11-28 11:21:19 -05:00
Yuki Shindo
5191e11650 Add Japanese (ja) locale files and update type definition for supported locales (#1726)
* feat: add locale files for Japanese (ja)

* fix: update locale type definition to include all supported languages
2024-11-28 09:45:00 -05:00
filtered
92079a653e Update unsupproted card help link (#1724) 2024-11-27 22:43:03 -05:00
Chenlei Hu
a7d14eb815 1.5.0 (#1723) 2024-11-27 19:25:18 -05:00
Chenlei Hu
9aea6eae70 chore: update litegraph to 0.8.38 (#1722) 2024-11-27 19:23:40 -05:00
Chenlei Hu
88a42172c5 Typecheck vue components (#1721)
* Fix various type issues in vue components

* Add vue tsc

* Add to hooks

* nit
2024-11-27 19:18:16 -05:00
Chenlei Hu
e79013dcfe Remove deprecated type def on ComfyNodeDef (#1720) 2024-11-27 16:16:50 -05:00
Chenlei Hu
08f3370828 Use auto inferred type on electronAPI.Terminal (#1719) 2024-11-27 16:14:30 -05:00
Chenlei Hu
c4d3c672ad Enforce ComfyExtension types (#1718)
* Enforce extension types

* nit
2024-11-27 15:35:18 -05:00
Chenlei Hu
39eaa2e850 [Electron] Add not supported hardware page (#1717) 2024-11-27 10:46:24 -05:00
oto-ciulis-tt
2d022e4e49 feat: Remove successful model downloads (#1710)
* feat: Remove successful model downloads

* PR comments

---------

Co-authored-by: Oto Ciulis <oto.ciulis@gmail.com>
2024-11-27 10:40:43 -05:00
Chenlei Hu
1ac6d6529f Add empty workflows placeholder (#1712) 2024-11-26 17:22:05 -05:00
Chenlei Hu
86fec820ac Remove app.multiUserServer flag (#1711) 2024-11-26 16:06:58 -05:00
Chenlei Hu
030d5845db 1.4.13 (#1709) 2024-11-26 14:27:55 -05:00
Chenlei Hu
dd1c878fdf [Electron] Fix path validation on typing in input box (#1708) 2024-11-26 14:26:46 -05:00
Chenlei Hu
3942603a38 [Electron] Add version number to error state (#1707) 2024-11-26 14:21:37 -05:00
Chenlei Hu
244578db96 1.4.12 (#1706) 2024-11-26 14:02:43 -05:00
Chenlei Hu
6b6edfde9f chore: update litegraph to 0.8.37 (#1704) 2024-11-26 13:20:21 -05:00
Chenlei Hu
c54b675a48 Revert Filter cached/canceled results (#1586) (#1703)
* Revert "Filter cached/canceled results (#1586)"

This reverts commit 6fbf1248f4.

* nit
2024-11-26 13:17:26 -05:00
Chenlei Hu
b7008dfc5c Revert "nit: Fix import of OutputFilters in queue sidebar (#1680)" (#1702)
This reverts commit f97b673481.
2024-11-26 13:11:28 -05:00
Chenlei Hu
d0ad4af51c Revert "Move queueStore update to GraphView (#1679)" (#1701)
This reverts commit c8d5a6f154.
2024-11-26 13:08:42 -05:00
Chenlei Hu
4a182014e1 Revert "Fix queue sidebar tab task filter (#1682)" (#1700)
This reverts commit c1c5573e7f.
2024-11-26 13:08:19 -05:00
Chenlei Hu
46cd522384 Fix save temporary workflow loop on overwrite (#1699) 2024-11-26 10:44:25 -05:00
Hayden
c977667a15 Change dialog to multi-window mode (#1695)
Fixed Dropdown's z-index being below the dialog
2024-11-26 10:11:15 -05:00
Chenlei Hu
d531bc34c4 Make ChangeTracker detect changes in workflow.extra (Except ds) (#1692)
* Compare workflow.extra content

* Add tests
2024-11-25 21:59:27 -05:00
Chenlei Hu
adfbec2744 Add setting to adjust queue MaxHistoryItems (#1689)
* Add MaxHistoryItems

* nit
2024-11-25 18:49:40 -05:00
Chenlei Hu
23521559bf 1.4.11 (#1688) 2024-11-25 18:43:17 -05:00
Chenlei Hu
51f57aba17 Revert "Change dialog to multi-window mode (#1672)" (#1686)
This reverts commit 43c23e526c.
2024-11-25 13:29:47 -05:00
Chenlei Hu
97bab053df Split i18n locales to multiple files (#1683) 2024-11-25 13:18:14 -05:00
Chenlei Hu
c1c5573e7f Fix queue sidebar tab task filter (#1682)
* Fix queue sidebar tab task filter

* nit
2024-11-25 12:59:10 -05:00
Chenlei Hu
16d2a95760 chore: update litegraph to 0.8.36 (#1681) 2024-11-25 11:55:42 -05:00
Chenlei Hu
f97b673481 nit: Fix import of OutputFilters in queue sidebar (#1680) 2024-11-25 11:49:49 -05:00
Chenlei Hu
c8d5a6f154 Move queueStore update to GraphView (#1679) 2024-11-25 11:47:35 -05:00
Chenlei Hu
3708afaf21 [Electron] Add fp32 and fp64 to unet inference precision options (#1678) 2024-11-25 11:20:49 -05:00
Hayden
43c23e526c Change dialog to multi-window mode (#1672) 2024-11-24 21:36:30 -05:00
Chenlei Hu
a80eb84df1 1.4.10 (#1676) 2024-11-24 21:36:00 -05:00
Chenlei Hu
f89898b3d0 Add searchbox for extensions panel (#1675) 2024-11-24 21:33:43 -05:00
Chenlei Hu
af21142602 Use setting panel template (#1674)
* PanelTemplate

* Use panel template
2024-11-24 21:24:13 -05:00
Chenlei Hu
4b91860227 [Refactor] Extract SettingsPanel (#1673)
* [Refactor] Extract SettingsPanel

* nit
2024-11-24 20:48:35 -05:00
Chenlei Hu
e53bafbca6 [Electron] Add custom node migration placeholder (#1670) 2024-11-24 20:16:39 -05:00
Chenlei Hu
e01c8f06c7 [Electron] Show server launch args in server config panel (#1669)
* Move revertChanges

* Show launch args

* Explicit ServerConfigValue type

* nit

* nit

* Add tests
2024-11-24 18:14:05 -05:00
Chenlei Hu
c61ed4da37 Add server config modified message to prompt restart (#1668)
* Server config changed message

* Write to settings on unmount

* nit

* Highlight modified config

* Move modified logic to store

* Add jest test

* nit
2024-11-24 16:13:37 -05:00
Terry Jia
4a4d6d070a restore camera state (#1666) 2024-11-24 16:09:58 -05:00
Tristan Sommer
4bedd873a1 improved mouse brush adjustment, added zoom level indicator with reset, added invert button, bug fixes (#1664) 2024-11-24 11:32:13 -05:00
filtered
f8bd910e63 Fix terminal resizes incorrectly in flex parent (#1663)
Pushes siblings or self off-screen
2024-11-24 11:31:29 -05:00
825 changed files with 100850 additions and 15827 deletions

43
.cursorrules Normal file
View File

@@ -0,0 +1,43 @@
// Vue 3 Composition API .cursorrules
// Vue 3 Composition API best practices
const vue3CompositionApiBestPractices = [
"Use setup() function for component logic",
"Utilize ref and reactive for reactive state",
"Implement computed properties with computed()",
"Use watch and watchEffect for side effects",
"Implement lifecycle hooks with onMounted, onUpdated, etc.",
"Utilize provide/inject for dependency injection",
]
// Folder structure
const folderStructure = `
src/
components/
constants/
composables/
views/
stores/
services/
App.vue
main.ts
`;
// Tailwind CSS best practices
const tailwindCssBestPractices = [
"Use Tailwind CSS for styling",
"Implement responsive design with Tailwind CSS",
]
// Additional instructions
const additionalInstructions = `
1. Leverage VueUse functions for performance-enhancing styles
2. Use lodash for utility functions
3. Use TypeScript for type safety
4. Implement proper props and emits definitions
5. Utilize Vue 3's Teleport component when needed
6. Use Suspense for async components
7. Implement proper error handling
8. Follow Vue 3 style guide and naming conventions
9. Use Vite for fast development and building
`;

View File

@@ -16,7 +16,18 @@ body:
- type: textarea
attributes:
label: Frontend Version
description: 'What is the frontend version you are using? You can check this in the settings dialog'
description: |
What is the frontend version you are using? You can check this in the settings dialog.
<details>
<summary>Click to show where to find the version</summary>
Open the setting by clicking the cog icon in the bottom-left of the screen, then click `About`.
![Frontend version](https://github.com/user-attachments/assets/561fb7c3-3012-457c-a494-9bdc1ff035c0)
</details>
validations:
required: true
- type: textarea
@@ -72,7 +83,8 @@ body:
- Other
- type: textarea
attributes:
label: Other
description: 'Any other additional information you think might be helpful.'
label: Other Information
description: 'Any other context, details, or screenshots that might help solve the issue.'
placeholder: 'Add any other relevant information here...'
validations:
required: false

View File

@@ -2,10 +2,7 @@ name: ESLint
on:
pull_request:
branches:
- main
- master
- 'dev*'
branches: [ main, master, dev*, core/*, desktop/* ]
jobs:
eslint:
@@ -13,8 +10,8 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: lts/*
node-version: 'lts/*'
- run: npm ci
- run: npm run lint
- run: npm run lint

View File

@@ -2,7 +2,7 @@ name: Prettier Check
on:
pull_request:
branches: [ main, master, dev* ]
branches: [ main, master, dev*, core/*, desktop/* ]
jobs:
prettier:
@@ -12,12 +12,12 @@ jobs:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: lts/*
node-version: 'lts/*'
- name: Install dependencies
run: npm ci
- name: Run Prettier check
run: npx prettier --check './**/*.{js,ts,tsx,vue}'
run: npm run format:check

159
.github/workflows/i18n-custom-nodes.yaml vendored Normal file
View File

@@ -0,0 +1,159 @@
name: Update Locales for given custom node repository
on:
workflow_dispatch:
inputs:
owner:
description: 'Owner of the repository to update locales for'
required: true
type: string
repository:
description: 'Repository to update locales for'
required: true
type: string
fork_owner:
description: 'Owner of the forked repository'
required: false
type: string
default: 'Comfy-Org'
jobs:
update-locales:
runs-on: ubuntu-latest
steps:
- name: Checkout ComfyUI
uses: actions/checkout@v4
with:
repository: comfyanonymous/ComfyUI
path: ComfyUI
ref: master
- name: Checkout ComfyUI_frontend
uses: actions/checkout@v4
with:
repository: Comfy-Org/ComfyUI_frontend
path: ComfyUI_frontend
- name: Checkout ComfyUI_devtools
uses: actions/checkout@v4
with:
repository: Comfy-Org/ComfyUI_devtools
path: ComfyUI/custom_nodes/ComfyUI_devtools
- name: Checkout custom node repository
uses: actions/checkout@v4
with:
repository: ${{ inputs.owner }}/${{ inputs.repository }}
path: 'ComfyUI/custom_nodes/${{ inputs.repository }}'
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install ComfyUI requirements
run: |
python -m pip install --upgrade pip
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install -r requirements.txt
pip install wait-for-it
working-directory: ComfyUI
- name: Install custom node requirements
run: |
if [ -f "requirements.txt" ]; then
pip install -r requirements.txt
fi
working-directory: ComfyUI/custom_nodes/${{ inputs.repository }}
- name: Build & Install ComfyUI_frontend
run: |
npm ci
npm run build
rm -rf ../ComfyUI/web/*
mv dist/* ../ComfyUI/web/
working-directory: ComfyUI_frontend
- name: Start ComfyUI server
run: |
python main.py --cpu --multi-user &
wait-for-it --service 127.0.0.1:8188 -t 600
working-directory: ComfyUI
- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: ComfyUI_frontend
- name: Start dev server
# Run electron dev server as it is a superset of the web dev server
# We do want electron specific UIs to be translated.
run: npm run dev:electron &
working-directory: ComfyUI_frontend
- name: Capture base i18n
run: npx tsx scripts/diff-i18n capture
working-directory: ComfyUI_frontend
- name: Update en.json
run: npm run collect-i18n
env:
PLAYWRIGHT_TEST_URL: http://localhost:5173
working-directory: ComfyUI_frontend
- name: Update translations
run: npm run locale
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
working-directory: ComfyUI_frontend
- name: Diff base vs updated i18n
run: npx tsx scripts/diff-i18n diff
working-directory: ComfyUI_frontend
- name: Update i18n in custom node repository
run: |
LOCALE_DIR=ComfyUI/custom_nodes/${{ inputs.repository }}/locales/
install -d "$LOCALE_DIR"
cp -rf ComfyUI_frontend/temp/diff/* "$LOCALE_DIR"
- name: Check and create fork of custom node repository
run: |
# Try to fork the repository
gh repo fork ${{ inputs.owner }}/${{ inputs.repository }} --clone=false || {
echo "Fork failed - repository might already be forked"
# Exit 0 to prevent the workflow from failing
exit 0
}
# Enable workflows on the forked repository
gh api \
--method PUT \
-H "Accept: application/vnd.github+json" \
"/repos/${{ inputs.fork_owner }}/${{ inputs.repository }}/actions/permissions/workflow" \
-F can_approve_pull_request_reviews=true \
-F default_workflow_permissions="write" \
-F enabled=true
env:
GH_TOKEN: ${{ secrets.PR_GH_TOKEN }}
- name: Commit changes
working-directory: ComfyUI/custom_nodes/${{ inputs.repository }}
run: |
git config --global user.name 'github-actions'
git config --global user.email 'github-actions@github.com'
# Create and switch to new branch
git checkout -b update-locales
# Stage and commit changes
git add -A
git commit -m "Update locales"
- name: Install SSH key For PUSH
uses: shimataro/ssh-key-action@v2
with:
# PR private key from action server
key: ${{ secrets.PR_SSH_PRIVATE_KEY }}
# github public key to confirm it's github server
known_hosts: github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
- name: Push changes
working-directory: ComfyUI/custom_nodes/${{ inputs.repository }}
run: |
# Force push to create the branch
echo "Pushing changes to ${{ inputs.fork_owner }}/${{ inputs.repository }}"
git push -f git@github.com:${{ inputs.fork_owner }}/${{ inputs.repository }}.git update-locales
- name: Create PR
working-directory: ComfyUI/custom_nodes/${{ inputs.repository }}
run: |
# Create PR using gh cli
gh pr create --title "Update locales for ${{ inputs.repository }}" --repo ${{ inputs.owner }}/${{ inputs.repository }} --head ${{ inputs.fork_owner }}:update-locales --body "Update locales for ${{ inputs.repository }}"
env:
GH_TOKEN: ${{ secrets.PR_GH_TOKEN }}

48
.github/workflows/i18n-node-defs.yaml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: Update Node Definitions Locales
on:
workflow_dispatch:
inputs:
trigger_type:
description: 'Type of trigger (manual or automatic)'
required: false
type: string
default: 'manual'
jobs:
update-locales:
runs-on: ubuntu-latest
steps:
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.2
- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: ComfyUI_frontend
- name: Start dev server
# Run electron dev server as it is a superset of the web dev server
# We do want electron specific UIs to be translated.
run: npm run dev:electron &
working-directory: ComfyUI_frontend
- name: Update en.json
run: npm run collect-i18n -- scripts/collect-i18n-node-defs.ts
env:
PLAYWRIGHT_TEST_URL: http://localhost:5173
working-directory: ComfyUI_frontend
- name: Update translations
run: npm run locale
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
working-directory: ComfyUI_frontend
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.PR_GH_TOKEN }}
commit-message: "Update locales for node definitions"
title: "Update locales for node definitions"
body: |
Automated PR to update locales for node definitions
This PR was created automatically by the frontend update workflow.
branch: update-locales-node-defs-${{ github.event.inputs.trigger_type }}-${{ github.run_id }}
base: main
labels: dependencies
path: ComfyUI_frontend

41
.github/workflows/i18n.yaml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Update Locales
on:
pull_request:
branches: [ main, master, dev* ]
jobs:
update-locales:
# Don't run on fork PRs
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
steps:
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.2
- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: ComfyUI_frontend
- name: Start dev server
# Run electron dev server as it is a superset of the web dev server
# We do want electron specific UIs to be translated.
run: npm run dev:electron &
working-directory: ComfyUI_frontend
- name: Update en.json
run: npm run collect-i18n -- scripts/collect-i18n-general.ts
env:
PLAYWRIGHT_TEST_URL: http://localhost:5173
working-directory: ComfyUI_frontend
- name: Update translations
run: npm run locale
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
working-directory: ComfyUI_frontend
- name: Commit updated locales
run: |
git config --global user.name 'github-actions'
git config --global user.email 'github-actions@github.com'
git fetch origin ${{ github.head_ref }}
git checkout -B ${{ github.head_ref }} origin/${{ github.head_ref }}
git add src/locales/
git diff --staged --quiet || git commit -m "Update locales [skip ci]"
git push origin HEAD:${{ github.head_ref }}
working-directory: ComfyUI_frontend

View File

@@ -2,12 +2,10 @@ name: Create Release Draft
on:
pull_request:
types: [closed]
branches:
- main
- master
types: [ closed ]
branches: [ main, core/* ]
paths:
- "package.json"
- 'package.json'
jobs:
draft_release:
@@ -18,13 +16,15 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: lts/*
node-version: 'lts/*'
- name: Get current version
id: current_version
run: echo ::set-output name=version::$(node -p "require('./package.json').version")
- name: Build project
env:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
run: |
npm ci
npm run build
@@ -38,6 +38,26 @@ jobs:
files: |
dist.zip
tag_name: v${{ steps.current_version.outputs.version }}
target_commitish: ${{ github.event.pull_request.base.ref }}
make_latest: ${{ github.event.pull_request.base.ref == 'main' }}
draft: true
prerelease: false
make_latest: "true"
generate_release_notes: true
publish_types:
runs-on: ubuntu-latest
if: >
github.event.pull_request.merged == true &&
contains(github.event.pull_request.labels.*.name, 'Release')
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
registry-url: https://registry.npmjs.org
- run: npm ci
- run: npm run build:types
- name: Publish package
run: npm publish --access public
working-directory: dist
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -1,5 +1,4 @@
# Setting test expectation screenshots for Playwright
name: Update Playwright Expectations
on:
@@ -11,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
if: github.event.label.name == 'New Browser Test Expectations'
steps:
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.1
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.2
- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: ComfyUI_frontend

View File

@@ -2,31 +2,29 @@ name: Tests CI
on:
push:
branches:
- main
- master
branches: [ main, master, core/*, desktop/* ]
pull_request:
branches:
- main
- master
- 'dev*'
branches: [ main, master, dev*, core/*, desktop/* ]
jobs:
jest-tests:
runs-on: ubuntu-latest
steps:
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.1
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.2
with:
devtools_ref: 080e6d4af809a46852d1c4b7ed85f06e8a3a72be
- name: Run Jest tests
run: |
npm run test:generate
npm run test:generate:examples
npm run test:jest:fast -- --verbose
npm run test:jest -- --verbose
working-directory: ComfyUI_frontend
playwright-tests-chromium:
runs-on: ubuntu-latest
steps:
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.1
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.2
with:
devtools_ref: 080e6d4af809a46852d1c4b7ed85f06e8a3a72be
- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: ComfyUI_frontend
@@ -43,7 +41,9 @@ jobs:
playwright-tests-chromium-2x:
runs-on: ubuntu-latest
steps:
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.1
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.2
with:
devtools_ref: 080e6d4af809a46852d1c4b7ed85f06e8a3a72be
- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: ComfyUI_frontend
@@ -60,7 +60,9 @@ jobs:
playwright-tests-mobile-chrome:
runs-on: ubuntu-latest
steps:
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.1
- uses: Comfy-Org/ComfyUI_frontend_setup_action@v2.2
with:
devtools_ref: 080e6d4af809a46852d1c4b7ed85f06e8a3a72be
- name: Install Playwright Browsers
run: npx playwright install chromium --with-deps
working-directory: ComfyUI_frontend

View File

@@ -2,15 +2,9 @@ name: Vitest Tests
on:
push:
branches:
- main
- master
- 'dev*'
branches: [ main, master, dev*, core/*, desktop/* ]
pull_request:
branches:
- main
- master
- 'dev*'
branches: [ main, master, dev*, core/*, desktop/* ]
jobs:
test:
@@ -20,9 +14,9 @@ jobs:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: lts/*
node-version: 'lts/*'
- name: Install dependencies
run: npm ci

10
.gitignore vendored
View File

@@ -16,6 +16,9 @@ dist-ssr
.vscode/*
*.code-workspace
!.vscode/extensions.json
!.vscode/tailwind.json
!.vscode/settings.json.default
!.vscode/launch.json.default
.idea
.DS_Store
*.suo
@@ -39,4 +42,9 @@ browser_tests/*/*-win32.png
.env
dist.zip
dist.zip
/temp/
# Generated JSON Schemas
/schemas/

17
.i18nrc.cjs Normal file
View File

@@ -0,0 +1,17 @@
// This file is intentionally kept in CommonJS format (.cjs)
// to resolve compatibility issues with dependencies that require CommonJS.
// Do not convert this file to ESModule format unless all dependencies support it.
const { defineConfig } = require('@lobehub/i18n-cli');
module.exports = defineConfig({
modelName: 'gpt-4',
splitToken: 1024,
entry: 'src/locales/en',
entryLocale: 'en',
output: 'src/locales',
outputLocales: ['zh', 'ru', 'ja', 'ko', 'fr'],
reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade.
'latent' is the short form of 'latent space'.
'mask' is in the context of image processing.
`
});

View File

@@ -3,5 +3,16 @@
"tabWidth": 2,
"semi": false,
"trailingComma": "none",
"printWidth": 80
}
"printWidth": 80,
"importOrder": ["^@core/(.*)$", "<THIRD_PARTY_MODULES>", "^@/(.*)$", "^[./]"],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true,
"overrides": [
{
"files": "*.{js,cjs,mjs,ts,cts,mts,tsx,vue}",
"options": {
"plugins": ["@trivago/prettier-plugin-sort-imports"]
}
}
]
}

16
.vscode/launch.json.default vendored Normal file
View File

@@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome on frontend dev",
"url": "http://localhost:5173",
"webRoot": "${workspaceFolder}/src",
"sourceMaps": true,
}
]
}

5
.vscode/settings.json.default vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"css.customData": [
".vscode/tailwind.json"
]
}

55
.vscode/tailwind.json vendored Normal file
View File

@@ -0,0 +1,55 @@
{
"version": 1.1,
"atDirectives": [
{
"name": "@tailwind",
"description": "Use the `@tailwind` directive to insert Tailwind's `base`, `components`, `utilities` and `screens` styles into your CSS.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#tailwind"
}
]
},
{
"name": "@apply",
"description": "Use the `@apply` directive to inline any existing utility classes into your own custom CSS. This is useful when you find a common utility pattern in your HTML that youd like to extract to a new component.",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#apply"
}
]
},
{
"name": "@responsive",
"description": "You can generate responsive variants of your own classes by wrapping their definitions in the `@responsive` directive:\n```css\n@responsive {\n .alert {\n background-color: #E53E3E;\n }\n}\n```\n",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#responsive"
}
]
},
{
"name": "@screen",
"description": "The `@screen` directive allows you to create media queries that reference your breakpoints by **name** instead of duplicating their values in your own CSS:\n```css\n@screen sm {\n /* ... */\n}\n```\n…gets transformed into this:\n```css\n@media (min-width: 640px) {\n /* ... */\n}\n```\n",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#screen"
}
]
},
{
"name": "@variants",
"description": "Generate `hover`, `focus`, `active` and other **variants** of your own utilities by wrapping their definitions in the `@variants` directive:\n```css\n@variants hover, focus {\n .btn-brand {\n background-color: #3182CE;\n }\n}\n```\n",
"references": [
{
"name": "Tailwind Documentation",
"url": "https://tailwindcss.com/docs/functions-and-directives#variants"
}
]
}
]
}

17
CODEOWNERS Normal file
View File

@@ -0,0 +1,17 @@
# Admins
* @Comfy-Org/comfy_frontend_devs
# Maintainers
*.md @Comfy-Org/comfy_maintainer
/tests-ui/ @Comfy-Org/comfy_maintainer
/browser_tests/ @Comfy-Org/comfy_maintainer
/.env_example @Comfy-Org/comfy_maintainer
# Translations (AIGODLIKE team + shinshin86)
/src/locales/ @Yorha4D @KarryCharon @DorotaLuna @shinshin86 @Comfy-Org/comfy_maintainer
# Load 3D extension
/src/extensions/core/load3d.ts @jtydhr88 @Comfy-Org/comfy_frontend_devs
# Mask Editor extension
/src/extensions/core/maskeditor.ts @trsommer @Comfy-Org/comfy_frontend_devs

240
README.md
View File

@@ -52,17 +52,31 @@ pause
### Stable Release
Stable releases are published weekly in the ComfyUI main repository, aligned with ComfyUI backend's stable release schedule.
#### Feature Freeze
There will be a 2-day feature freeze before each stable release. During this period, no new major features will be merged.
Stable releases are published bi-weekly in the ComfyUI main repository.
## Release Summary
### Major features
<details>
<details id='feature-native-translation'>
<summary>v1.5: Native translation (i18n)</summary>
ComfyUI now includes built-in translation support, replacing the need for third-party translation extensions. Select your language
in `Comfy > Locale > Language` to translate the interface into English, Chinese (Simplified), Russian, Japanese, or Korean. This native
implementation offers better performance, reliability, and maintainability compared to previous solutions.<br>
More details available here: https://blog.comfy.org/p/native-localization-support-i18n
</details>
<details id='feature-mask-editor'>
<summary>v1.4: New mask editor</summary>
https://github.com/Comfy-Org/ComfyUI_frontend/pull/1284 implements a new mask editor.
![image](https://github.com/user-attachments/assets/f0ea6ee5-00ee-4e5d-a09c-6938e86a1f17)
</details>
<details id='feature-integrated-server-terminal'>
<summary>v1.3.22: Integrated server terminal</summary>
Press Ctrl + ` to toggle integrated terminal.
@@ -70,7 +84,7 @@ Press Ctrl + ` to toggle integrated terminal.
https://github.com/user-attachments/assets/eddedc6a-07a3-4a83-9475-63b3977f6d94
</details>
<details>
<details id='feature-keybinding-customization'>
<summary>v1.3.7: Keybinding customization</summary>
## Basic UI
@@ -87,7 +101,7 @@ https://github.com/user-attachments/assets/eddedc6a-07a3-4a83-9475-63b3977f6d94
</details>
<details>
<details id='feature-node-library-sidebar'>
<summary>v1.2.4: Node library sidebar tab</summary>
#### Drag & Drop
@@ -97,13 +111,13 @@ https://github.com/user-attachments/assets/853e20b7-bc0e-49c9-bbce-a2ba7566f92f
https://github.com/user-attachments/assets/4bbca3ee-318f-4cf0-be32-a5a5541066cf
</details>
<details>
<details id='feature-queue-sidebar'>
<summary>v1.2.0: Queue/History sidebar tab</summary>
https://github.com/user-attachments/assets/86e264fe-4d26-4f07-aa9a-83bdd2d02b8f
</details>
<details>
<details id='feature-node-search'>
<summary>v1.1.0: Node search box</summary>
#### Fuzzy search & Node preview
@@ -115,26 +129,26 @@ https://github.com/user-attachments/assets/4bbca3ee-318f-4cf0-be32-a5a5541066cf
### QoL changes
<details>
<details id='feature-nested-group'>
<summary>v1.3.32: **Litegraph** Nested group</summary>
https://github.com/user-attachments/assets/f51adeb1-028e-40af-81e4-0ac13075198a
</details>
<details>
<details id='feature-group-selection'>
<summary>v1.3.24: **Litegraph** Group selection</summary>
https://github.com/user-attachments/assets/e6230a94-411e-4fba-90cb-6c694200adaa
</details>
<details>
<details id='feature-toggle-link-visibility'>
<summary>v1.3.6: **Litegraph** Toggle link visibility</summary>
[rec.webm](https://github.com/user-attachments/assets/34e460ac-fbbc-44ef-bfbb-99a84c2ae2be)
</details>
<details>
<details id='feature-auto-widget-conversion'>
<summary>v1.3.4: **Litegraph** Auto widget to input conversion</summary>
Dropping a link of correct type on node widget will automatically convert the widget to input.
@@ -143,7 +157,7 @@ Dropping a link of correct type on node widget will automatically convert the wi
</details>
<details>
<details id='feature-pan-mode'>
<summary>v1.3.4: **Litegraph** Canvas pan mode</summary>
The canvas becomes readonly in pan mode. Pan mode is activated by clicking the pan mode button on the canvas menu
@@ -153,42 +167,42 @@ or by holding the space key.
</details>
<details>
<details id='feature-shift-drag-link-creation'>
<summary>v1.3.1: **Litegraph** Shift drag link to create a new link</summary>
[rec.webm](https://github.com/user-attachments/assets/7e73aaf9-79e2-4c3c-a26a-911cba3b85e4)
</details>
<details>
<details id='feature-optional-input-donuts'>
<summary>v1.2.62: **Litegraph** Show optional input slots as donuts</summary>
![GYEIRidb0AYGO-v](https://github.com/user-attachments/assets/e6cde0b6-654b-4afd-a117-133657a410b1)
</details>
<details>
<details id='feature-group-title-edit'>
<summary>v1.2.44: **Litegraph** Double click group title to edit</summary>
https://github.com/user-attachments/assets/5bf0e2b6-8b3a-40a7-b44f-f0879e9ad26f
</details>
<details>
<details id='feature-group-selection-shortcut'>
<summary>v1.2.39: **Litegraph** Group selected nodes with Ctrl + G</summary>
https://github.com/user-attachments/assets/7805dc54-0854-4a28-8bcd-4b007fa01151
</details>
<details>
<details id='feature-node-title-edit'>
<summary>v1.2.38: **Litegraph** Double click node title to edit</summary>
https://github.com/user-attachments/assets/d61d5d0e-f200-4153-b293-3e3f6a212b30
</details>
<details>
<details id='feature-drag-multi-link'>
<summary>v1.2.7: **Litegraph** drags multiple links with shift pressed</summary>
https://github.com/user-attachments/assets/68826715-bb55-4b2a-be6e-675cfc424afe
@@ -197,7 +211,7 @@ https://github.com/user-attachments/assets/c142c43f-2fe9-4030-8196-b3bfd4c6977d
</details>
<details>
<details id='feature-auto-connect-link'>
<summary>v1.2.2: **Litegraph** auto connects to correct slot</summary>
#### Before
@@ -207,7 +221,7 @@ https://github.com/user-attachments/assets/c142c43f-2fe9-4030-8196-b3bfd4c6977d
https://github.com/user-attachments/assets/b6360ac0-f0d2-447c-9daa-8a2e20c0dc1d
</details>
<details>
<details id='feature-hide-text-overflow'>
<summary>v1.1.8: **Litegraph** hides text overflow on widget value</summary>
https://github.com/user-attachments/assets/5696a89d-4a47-4fcc-9e8c-71e1264943f2
@@ -215,6 +229,55 @@ https://github.com/user-attachments/assets/c142c43f-2fe9-4030-8196-b3bfd4c6977d
### Developer APIs
<details>
<summary>v1.6.13: prompt/confirm/alert replacements for ComfyUI desktop</summary>
Several browser-only APIs are not available in ComfyUI desktop's electron environment.
- `window.prompt`
- `window.confirm`
- `window.alert`
Please use the following APIs as replacements.
```js
// window.prompt
window['app'].extensionManager.dialog
.prompt({
title: 'Test Prompt',
message: 'Test Prompt Message'
})
.then((value: string) => {
// Do something with the value user entered
})
```
![image](https://github.com/user-attachments/assets/c73f74d0-9bb4-4555-8d56-83f1be4a1d7e)
```js
// window.confirm
window['app'].extensionManager.dialog
.confirm({
title: 'Test Confirm',
message: 'Test Confirm Message'
})
.then((value: boolean) => {
// Do something with the value user entered
})
```
![image](https://github.com/user-attachments/assets/8dec7a42-7443-4245-85be-ceefb1116e96)
```js
// window.alert
window['app'].extensionManager.toast
.addAlert("Test Alert")
```
![image](https://github.com/user-attachments/assets/9b18bdca-76ef-4432-95de-5cd2369684f2)
</details>
<details>
<summary>v1.3.34: Register about panel badges</summary>
@@ -235,7 +298,7 @@ app.registerExtension({
</details>
<details>
<details id='extension-api-bottom-panel-tabs'>
<summary>v1.3.22: Register bottom panel tabs</summary>
```js
@@ -258,7 +321,7 @@ app.registerExtension({
</details>
<details>
<details id='extension-api-settings'>
<summary>v1.3.22: New settings API</summary>
Legacy settings API.
@@ -304,7 +367,7 @@ app.extensionManager.setting.set('TestSetting', 'Hello, universe!')
</details>
<details>
<details id='extension-api-commands-keybindings'>
<summary>v1.3.7: Register commands and keybindings</summary>
Extensions can call the following API to register commands and keybindings. Do
@@ -333,7 +396,7 @@ app.extensionManager.setting.set('TestSetting', 'Hello, universe!')
</details>
<details>
<details id='extension-api-topbar-menu'>
<summary>v1.3.1: Extension API to register custom topbar menu items</summary>
Extensions can call the following API to register custom topbar menu items.
@@ -362,7 +425,7 @@ app.extensionManager.setting.set('TestSetting', 'Hello, universe!')
![image](https://github.com/user-attachments/assets/ae7b082f-7ce9-4549-a446-4563567102fe)
</details>
<details>
<details id='extension-api-toast'>
<summary>v1.2.27: Extension API to add toast message</summary>i
Extensions can call the following API to add toast messages.
@@ -380,7 +443,7 @@ Documentation of all supported options can be found here: <https://primevue.org/
![image](https://github.com/user-attachments/assets/de02cd7e-cd81-43d1-a0b0-bccef92ff487)
</details>
<details>
<details id='extension-api-sidebar-tab'>
<summary>v1.2.4: Extension API to register custom sidebar tab</summary>
Extensions now can call the following API to register a sidebar tab.
@@ -405,6 +468,35 @@ We will support custom icons later.
![image](https://github.com/user-attachments/assets/7bff028a-bf91-4cab-bf97-55c243b3f5e0)
</details>
<details id='extension-api-selection-toolbox'>
<summary>v1.10.9: Selection Toolbox API</summary>
Extensions can register commands that appear in the selection toolbox when specific items are selected on the canvas.
```js
app.registerExtension({
name: 'TestExtension1',
commands: [
{
id: 'test.selection.command',
label: 'Test Command',
icon: 'pi pi-star',
function: () => {
// Command logic here
}
}
],
// Return an array of command IDs to show in the selection toolbox
// when an item is selected
getSelectionToolboxCommands: (selectedItem) => ['test.selection.command']
})
```
The selection toolbox will display the command button when items are selected:
![Image](https://github.com/user-attachments/assets/28d91267-c0a9-4bd5-a7c4-36e8ec44c9bd)
</details>
## Development
### Tech Stack
@@ -414,6 +506,7 @@ We will support custom icons later.
- [PrimeVue](https://primevue.org/) with [TailwindCSS](https://tailwindcss.com/) for UI
- [Litegraph](https://github.com/Comfy-Org/litegraph.js) for node editor
- [zod](https://zod.dev/) for schema validation
- [vue-i18n](https://github.com/intlify/vue-i18n) for internationalization
### Git pre-commit hooks
@@ -456,8 +549,7 @@ navigate to `http://<server_ip>:5173` (e.g. `http://192.168.2.20:5173` here), to
- `git clone https://github.com/comfyanonymous/ComfyUI_examples.git` to `tests-ui/ComfyUI_examples` or the EXAMPLE_REPO_PATH location specified in .env
- `npm i` to install all dependencies
- `npm run test:generate` to fetch `tests-ui/data/object_info.json`
- `npm run test:generate:examples` to extract the example workflows
- `npm run test` to execute all unit tests.
- `npm run test:jest` to execute all unit tests.
### Component Test
@@ -480,14 +572,86 @@ This repo is using litegraph package hosted on <https://github.com/Comfy-Org/lit
This will replace the litegraph package in this repo with the local litegraph repo.
## Internationalization (i18n)
Our project supports multiple languages using `vue-i18n`. This allows users around the world to use the application in their preferred language.
### Supported Languages
- en (English)
- zh (中文)
- ru (Русский)
- ja (日本語)
- ko (한국어)
- fr (Français)
### How to Add a New Language
We welcome the addition of new languages. You can add a new language by following these steps:
#### 1. Generate language files
We use [lobe-i18n](https://github.com/lobehub/lobe-cli-toolbox/blob/master/packages/lobe-i18n/README.md) as our translation tool, which integrates with LLM for efficient localization.
Update the configuration file to include the new language(s) you wish to add:
```javascript
const { defineConfig } = require('@lobehub/i18n-cli');
module.exports = defineConfig({
entry: 'src/locales/en.json', // Base language file
entryLocale: 'en',
output: 'src/locales',
outputLocales: ['zh', 'ru', 'ja'], // Add the new language(s) here
});
```
Set your OpenAI API Key by running the following command:
```sh
npx lobe-i18n --option
```
Once configured, generate the translation files with:
```sh
npx lobe-i18n locale
```
This will create the language files for the specified languages in the configuration.
#### 2. Update i18n Configuration
Import the newly generated locale file(s) in the `src/i18n.ts` file to include them in the application's i18n setup.
#### 3. Enable Selection of the New Language
Add the newly added language to the following item in `src/constants/coreSettings.ts`:
```typescript
{
id: 'Comfy.Locale',
name: 'Locale',
type: 'combo',
// Add the new language(s) here
options: [
{ value: 'en', text: 'English' },
{ value: 'zh', text: '中文' },
{ value: 'ru', text: 'Русский' },
{ value: 'ja', text: '日本語' }
],
defaultValue: navigator.language.split('-')[0] || 'en'
},
```
This will make the new language selectable in the application's settings.
#### 4. Test the Translations
Start the development server, switch to the new language, and verify the translations.
You can switch languages by opening the ComfyUI Settings and selecting from the `ComfyUI > Locale` dropdown box.
## Deploy
- Option 1: Set `DEPLOY_COMFYUI_DIR` in `.env` and run `npm run deploy`.
- Option 2: Copy everything under `dist/` to `ComfyUI/web/` in your ComfyUI checkout manually.
## Publish release to ComfyUI main repo
Run following command to publish a release to ComfyUI main repo. The script will create a new branch and do a commit to `web/` folder by checkout `dist.zip`
from GitHub release.
- `python scripts/main_repo_release.py <path_to_comfyui_main_repo> <version>`

View File

@@ -34,6 +34,8 @@ There are two ways to run the tests:
```
This opens a user interface where you can select specific tests to run and inspect the test execution timeline.
To run the same test multiple times in Playwright's UI mode, you must launch the main ComfyUI process with the `--multi-user` flag.
![Playwright UI Mode](https://github.com/user-attachments/assets/6a1ebef0-90eb-4157-8694-f5ee94d03755)
## Screenshot Expectations

View File

@@ -1,6 +1,7 @@
import type { Response } from '@playwright/test'
import type { StatusWsMessage } from '../src/types/apiTypes.ts'
import { expect, mergeTests } from '@playwright/test'
import type { StatusWsMessage } from '../src/schemas/apiSchema.ts'
import { comfyPageFixture } from './fixtures/ComfyPage'
import { webSocketFixture } from './fixtures/ws.ts'

View File

@@ -0,0 +1,37 @@
{
"last_node_id": 1,
"last_link_id": 0,
"nodes": [
{
"id": 1,
"type": "CLIPTextEncode",
"pos": [20, 50],
"size": [400, 200],
"flags": { "collapsed": true },
"order": 0,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": null,
"localized_name": "clip"
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": null,
"localized_name": "CONDITIONING"
}
],
"properties": {},
"widgets_values": ["Should not be displayed."]
}
],
"links": [],
"groups": [],
"config": {},
"version": 0.4
}

View File

@@ -114,7 +114,7 @@
{ "name": "VAE", "type": "VAE", "links": [8], "slot_index": 2 }
],
"properties": {},
"widgets_values": ["v1-5-pruned-emaonly.ckpt"]
"widgets_values": ["v1-5-pruned-emaonly-fp16.safetensors"]
}
],
"links": [

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

View File

@@ -0,0 +1,163 @@
{
"last_node_id": 19,
"last_link_id": 14,
"nodes": [
{
"id": 19,
"type": "workflow>two_VAE_decode",
"pos": [
1368.800048828125,
768.7999877929688
],
"size": [
418.1999816894531,
86
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": null
},
{
"name": "vae",
"type": "VAE",
"link": null
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": null
},
{
"name": "VAEDecode IMAGE",
"type": "IMAGE",
"links": null
}
],
"properties": {}
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
},
"node_versions": {},
"ue_links": [],
"groupNodes": {
"two_VAE_decode": {
"nodes": [
{
"id": -1,
"type": "VAEDecode",
"pos": [
1368.800048828125,
768.7999877929688
],
"size": [
210,
46
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": null,
"localized_name": "samples"
},
{
"name": "vae",
"type": "VAE",
"link": null,
"localized_name": "vae"
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": null,
"localized_name": "IMAGE"
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"index": 0
},
{
"id": -1,
"type": "VAEDecode",
"pos": [
1368.800048828125,
873.7999877929688
],
"size": [
210,
46
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": null,
"localized_name": "samples"
},
{
"name": "vae",
"type": "VAE",
"link": null,
"localized_name": "vae"
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": null,
"localized_name": "IMAGE"
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"index": 1
}
],
"links": [],
"external": [],
"config": {
"1": {
"input": {
"samples": {
"visible": false
},
"vae": {
"visible": false
}
}
}
}
}
}
},
"version": 0.4
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 KiB

After

Width:  |  Height:  |  Size: 260 KiB

View File

@@ -18,7 +18,7 @@
{
"name": "fake_model.safetensors",
"url": "http://localhost:8188/api/devtools/fake_model.safetensors",
"directory": "clip"
"directory": "text_encoders"
}
],
"version": 0.4

View File

@@ -0,0 +1,49 @@
{
"last_node_id": 1,
"last_link_id": 1,
"nodes": [
{
"id": 1,
"type": "CheckpointLoaderSimple",
"pos": [256, 256],
"size": [315, 98],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": null
},
{
"name": "CLIP",
"type": "CLIP",
"links": null
},
{
"name": "VAE",
"type": "VAE",
"links": null
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple",
"models": [
{
"name": "fake_model.safetensors",
"url": "http://localhost:8188/api/devtools/fake_model.safetensors",
"directory": "text_encoders"
}
]
},
"widgets_values": ["fake_model.safetensors"]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {},
"version": 0.4
}

View File

@@ -0,0 +1,63 @@
{
"last_node_id": 1,
"last_link_id": 0,
"nodes": [
{
"id": 1,
"type": "UNKNOWN NODE",
"pos": [
48,
86
],
"size": {
"0": 358.80780029296875,
"1": 314.7989501953125
},
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": null,
"slot_index": 0
},
{
"name": "foo",
"type": "STRING",
"link": null,
"slot_index": 1,
"widget": {
"name": "foo"
}
}
],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": [],
"slot_index": 0,
"shape": 6
}
],
"properties": {
"Node name for S&R": "UNKNOWN NODE"
},
"widgets_values": [
"wd-v1-4-moat-tagger-v2",
0.35,
0.85,
false,
false,
""
]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {},
"version": 0.4
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 152 B

View File

@@ -0,0 +1,37 @@
{
"last_node_id": 16,
"last_link_id": 17,
"nodes": [
{
"id": 16,
"type": "DevToolsNodeWithOptionalComboInput",
"pos": [1605, 480],
"size": [378, 58],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": null
}
],
"properties": {
"Node name for S&R": "DevToolsNodeWithOptionalComboInput"
},
"widgets_values": ["Random Unique Option 1740551583.3507228"]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 2.0875710456451313,
"offset": [-1311.5753953400676, -176.7620403697558]
}
},
"version": 0.4
}

View File

@@ -0,0 +1,48 @@
{
"last_node_id": 15,
"last_link_id": 10,
"nodes": [
{
"id": 15,
"type": "DevToolsRemoteWidgetNode",
"pos": [
495,
735
],
"size": [
315,
58
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": null
}
],
"properties": {
"Node name for S&R": "DevToolsRemoteWidgetNode"
},
"widgets_values": [
"v1-5-pruned-emaonly-fp16.safetensors"
]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 0.8008869919566275,
"offset": [
538.9801226576359,
-55.24554581806672
]
}
},
"version": 0.4
}

View File

@@ -0,0 +1,49 @@
{
"last_node_id": 12,
"last_link_id": 9,
"nodes": [
{
"id": 12,
"type": "DevToolsSimpleSlider",
"pos": [
50,
50
],
"size": [
315,
58
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "FLOAT",
"type": "FLOAT",
"links": null,
"label": "FLOAT"
}
],
"properties": {
"Node name for S&R": "DevToolsSimpleSlider"
},
"widgets_values": [
0.5
]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
}
},
"version": 0.4
}

View File

@@ -0,0 +1,116 @@
{
"last_node_id": 16,
"last_link_id": 18,
"nodes": [
{
"id": 12,
"type": "VAEDecode",
"pos": [620, 260],
"size": [210, 46],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": null
},
{
"name": "vae",
"type": "VAE",
"link": 18
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": null
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
},
{
"id": 13,
"type": "Reroute",
"pos": [510, 280],
"size": [75, 26],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "",
"type": "*",
"link": 13
}
],
"outputs": [
{
"name": "",
"type": "VAE",
"links": [18],
"slot_index": 0
}
],
"properties": {
"showOutputText": false,
"horizontal": false
}
},
{
"id": 4,
"type": "CheckpointLoaderSimple",
"pos": [160, 240],
"size": [315, 98],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [13],
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": ["v1-5-pruned-emaonly.safetensors"]
}
],
"links": [
[13, 4, 2, 13, 0, "*"],
[18, 13, 0, 12, 1, "VAE"]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": {
"0": 0,
"1": 0
}
}
},
"version": 0.4
}

View File

@@ -0,0 +1,35 @@
{
"last_node_id": 11,
"last_link_id": 9,
"nodes": [
{
"id": 11,
"type": "DevToolsNodeWithBooleanInput",
"pos": [
0,
30
],
"size": [
315,
58
],
"flags": {
"collapsed": false
},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {
"Node name for S&R": "DevToolsNodeWithBooleanInput"
},
"widgets_values": [
false
]
}
],
"links": [],
"groups": [],
"config": {},
"version": 0.4
}

View File

@@ -0,0 +1,43 @@
{
"last_node_id": 10,
"last_link_id": 9,
"nodes": [
{
"id": 10,
"type": "DevToolsNodeWithSeedInput",
"pos": [
20,
50
],
"size": [
315,
82
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {
"Node name for S&R": "DevToolsNodeWithSeedInput"
},
"widgets_values": [
0,
"randomize"
]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
}
},
"version": 0.4
}

View File

@@ -1,4 +1,5 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
test.describe('Browser tab title', () => {

View File

@@ -1,11 +1,8 @@
import {
ComfyPage,
comfyPageFixture as test,
comfyExpect as expect
comfyExpect as expect,
comfyPageFixture as test
} from './fixtures/ComfyPage'
import type { useWorkspaceStore } from '../src/stores/workspaceStore'
type WorkspaceStore = ReturnType<typeof useWorkspaceStore>
async function beforeChange(comfyPage: ComfyPage) {
await comfyPage.page.evaluate(() => {
@@ -26,64 +23,41 @@ test.describe('Change Tracker', () => {
})
test('Can undo multiple operations', async ({ comfyPage }) => {
function isModified() {
return comfyPage.page.evaluate(async () => {
return !!(window['app'].extensionManager as WorkspaceStore).workflow
.activeWorkflow?.isModified
})
}
function getUndoQueueSize() {
return comfyPage.page.evaluate(() => {
const workflow = (window['app'].extensionManager as WorkspaceStore)
.workflow.activeWorkflow
return workflow?.changeTracker.undoQueue.length
})
}
function getRedoQueueSize() {
return comfyPage.page.evaluate(() => {
const workflow = (window['app'].extensionManager as WorkspaceStore)
.workflow.activeWorkflow
return workflow?.changeTracker.redoQueue.length
})
}
expect(await getUndoQueueSize()).toBe(0)
expect(await getRedoQueueSize()).toBe(0)
expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.getRedoQueueSize()).toBe(0)
// Save, confirm no errors & workflow modified flag removed
await comfyPage.menu.topbar.saveWorkflow('undo-redo-test')
expect(await comfyPage.getToastErrorCount()).toBe(0)
expect(await isModified()).toBe(false)
expect(await getUndoQueueSize()).toBe(0)
expect(await getRedoQueueSize()).toBe(0)
expect(await comfyPage.isCurrentWorkflowModified()).toBe(false)
expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.getRedoQueueSize()).toBe(0)
const node = (await comfyPage.getFirstNodeRef())!
await node.click('title')
await node.click('collapse')
await expect(node).toBeCollapsed()
expect(await isModified()).toBe(true)
expect(await getUndoQueueSize()).toBe(1)
expect(await getRedoQueueSize()).toBe(0)
expect(await comfyPage.isCurrentWorkflowModified()).toBe(true)
expect(await comfyPage.getUndoQueueSize()).toBe(1)
expect(await comfyPage.getRedoQueueSize()).toBe(0)
await comfyPage.ctrlB()
await expect(node).toBeBypassed()
expect(await isModified()).toBe(true)
expect(await getUndoQueueSize()).toBe(2)
expect(await getRedoQueueSize()).toBe(0)
expect(await comfyPage.isCurrentWorkflowModified()).toBe(true)
expect(await comfyPage.getUndoQueueSize()).toBe(2)
expect(await comfyPage.getRedoQueueSize()).toBe(0)
await comfyPage.ctrlZ()
await expect(node).not.toBeBypassed()
expect(await isModified()).toBe(true)
expect(await getUndoQueueSize()).toBe(1)
expect(await getRedoQueueSize()).toBe(1)
expect(await comfyPage.isCurrentWorkflowModified()).toBe(true)
expect(await comfyPage.getUndoQueueSize()).toBe(1)
expect(await comfyPage.getRedoQueueSize()).toBe(1)
await comfyPage.ctrlZ()
await expect(node).not.toBeCollapsed()
expect(await isModified()).toBe(false)
expect(await getUndoQueueSize()).toBe(0)
expect(await getRedoQueueSize()).toBe(2)
expect(await comfyPage.isCurrentWorkflowModified()).toBe(false)
expect(await comfyPage.getUndoQueueSize()).toBe(0)
expect(await comfyPage.getRedoQueueSize()).toBe(2)
})
})
@@ -174,4 +148,20 @@ test.describe('Change Tracker', () => {
await expect(node).toBePinned()
await expect(node).toBeCollapsed()
})
test('Can detect changes in workflow.extra', async ({ comfyPage }) => {
expect(await comfyPage.getUndoQueueSize()).toBe(0)
await comfyPage.page.evaluate(() => {
window['app'].graph.extra.foo = 'bar'
})
// Click empty space to trigger a change detection.
await comfyPage.clickEmptySpace()
expect(await comfyPage.getUndoQueueSize()).toBe(1)
})
test('Ignores changes in workflow.ds', async ({ comfyPage }) => {
expect(await comfyPage.getUndoQueueSize()).toBe(0)
await comfyPage.pan({ x: 10, y: 10 })
expect(await comfyPage.getUndoQueueSize()).toBe(0)
})
})

View File

@@ -1,7 +1,9 @@
import { expect } from '@playwright/test'
import type { Palette } from '../src/schemas/colorPaletteSchema'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
const customColorPalettes = {
const customColorPalettes: Record<string, Palette> = {
obsidian: {
version: 102,
id: 'obsidian',
@@ -127,23 +129,62 @@ const customColorPalettes = {
'tr-odd-bg-color': 'rgba(19,19,19,.9)'
}
}
},
// A custom light theme with fg color red
light_red: {
id: 'light_red',
name: 'Light Red',
light_theme: true,
colors: {
node_slot: {},
litegraph_base: {},
comfy_base: {
'fg-color': '#ff0000'
}
}
}
}
test.describe('Color Palette', () => {
test.beforeEach(async ({ comfyPage }) => {
test('Can show custom color palette', async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.CustomColorPalettes', customColorPalettes)
// Reload to apply the new setting. Setting Comfy.CustomColorPalettes directly
// doesn't update the store immediately.
await comfyPage.setup()
await comfyPage.loadWorkflow('every_node_color')
await comfyPage.setSetting('Comfy.ColorPalette', 'obsidian_dark')
await expect(comfyPage.canvas).toHaveScreenshot(
'custom-color-palette-obsidian-dark-all-colors.png'
)
await comfyPage.setSetting('Comfy.ColorPalette', 'light_red')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot(
'custom-color-palette-light-red.png'
)
await comfyPage.setSetting('Comfy.ColorPalette', 'dark')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('default-color-palette.png')
})
test('Can show custom color palette', async ({ comfyPage }) => {
test('Can add custom color palette', async ({ comfyPage }) => {
await comfyPage.page.evaluate((p) => {
window['app'].extensionManager.colorPalette.addCustomColorPalette(p)
}, customColorPalettes.obsidian_dark)
expect(await comfyPage.getToastErrorCount()).toBe(0)
await comfyPage.setSetting('Comfy.ColorPalette', 'obsidian_dark')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot(
'custom-color-palette-obsidian-dark.png'
)
// Legacy `custom_` prefix is still supported
await comfyPage.setSetting('Comfy.ColorPalette', 'custom_obsidian_dark')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot(
'custom-color-palette-obsidian-dark.png'
)
await comfyPage.setSetting('Comfy.ColorPalette', 'dark')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('default-color-palette.png')
})
})
@@ -192,7 +233,7 @@ test.describe('Node Color Adjustments', () => {
const workflow = await comfyPage.page.evaluate(() => {
return localStorage.getItem('workflow')
})
for (const node of JSON.parse(workflow).nodes) {
for (const node of JSON.parse(workflow ?? '{}').nodes) {
if (node.bgcolor) expect(node.bgcolor).not.toMatch(/hsla/)
if (node.color) expect(node.color).not.toMatch(/hsla/)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

@@ -1,4 +1,5 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
test.describe('Keybindings', () => {

View File

@@ -1,4 +1,5 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
test.describe('Copy Paste', () => {
@@ -10,6 +11,14 @@ test.describe('Copy Paste', () => {
await expect(comfyPage.canvas).toHaveScreenshot('copied-node.png')
})
test('Can copy and paste node with link', async ({ comfyPage }) => {
await comfyPage.clickTextEncodeNode1()
await comfyPage.page.mouse.move(10, 10)
await comfyPage.ctrlC()
await comfyPage.page.keyboard.press('Control+Shift+V')
await expect(comfyPage.canvas).toHaveScreenshot('copied-node-with-link.png')
})
test('Can copy and paste text', async ({ comfyPage }) => {
const textBox = comfyPage.widgetTextBox
await textBox.click()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

@@ -1,4 +1,6 @@
import { expect } from '@playwright/test'
import { Locator, expect } from '@playwright/test'
import type { Keybinding } from '../src/schemas/keyBindingSchema'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
test.describe('Load workflow warning', () => {
@@ -42,6 +44,18 @@ test.describe('Execution error', () => {
const executionError = comfyPage.page.locator('.comfy-error-report')
await expect(executionError).toBeVisible()
})
test('Can display Issue Report form', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('execution_error')
await comfyPage.queueButton.click()
await comfyPage.nextFrame()
await comfyPage.page.getByLabel('Help Fix This').click()
const issueReportForm = comfyPage.page.getByText(
'Submit Error Report (Optional)'
)
await expect(issueReportForm).toBeVisible()
})
})
test.describe('Missing models warning', () => {
@@ -52,9 +66,84 @@ test.describe('Missing models warning', () => {
}, comfyPage.url)
})
test('Should display a warning when missing models are found', async ({
comfyPage
}) => {
await comfyPage.loadWorkflow('missing_models')
const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models')
await expect(missingModelsWarning).toBeVisible()
const downloadButton = missingModelsWarning.getByLabel('Download')
await expect(downloadButton).toBeVisible()
})
test('Should display a warning when missing models are found in node properties', async ({
comfyPage
}) => {
// Load workflow that has a node with models metadata at the node level
await comfyPage.loadWorkflow('missing_models_from_node_properties')
const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models')
await expect(missingModelsWarning).toBeVisible()
const downloadButton = missingModelsWarning.getByLabel('Download')
await expect(downloadButton).toBeVisible()
})
test('Should not display a warning when no missing models are found', async ({
comfyPage
}) => {
const modelFoldersRes = {
status: 200,
body: JSON.stringify([
{
name: 'text_encoders',
folders: ['ComfyUI/models/text_encoders']
}
])
}
comfyPage.page.route(
'**/api/experiment/models',
(route) => route.fulfill(modelFoldersRes),
{ times: 1 }
)
// Reload page to trigger indexing of model folders
await comfyPage.setup()
const clipModelsRes = {
status: 200,
body: JSON.stringify([
{
name: 'fake_model.safetensors',
pathIndex: 0
}
])
}
comfyPage.page.route(
'**/api/experiment/models/text_encoders',
(route) => route.fulfill(clipModelsRes),
{ times: 1 }
)
await comfyPage.loadWorkflow('missing_models')
const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models')
await expect(missingModelsWarning).not.toBeVisible()
})
test('should show on tutorial workflow', async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.TutorialCompleted', false)
await comfyPage.setup({ clearStorage: true })
const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models')
await expect(missingModelsWarning).toBeVisible()
expect(await comfyPage.getSetting('Comfy.TutorialCompleted')).toBe(true)
})
// Flaky test after parallelization
// https://github.com/Comfy-Org/ComfyUI_frontend/pull/1400
test.skip('Should display a warning when missing models are found', async ({
test.skip('Should download missing model when clicking download button', async ({
comfyPage
}) => {
// The fake_model.safetensors is served by
@@ -72,13 +161,60 @@ test.describe('Missing models warning', () => {
const download = await downloadPromise
expect(download.suggestedFilename()).toBe('fake_model.safetensors')
})
test.describe('Do not show again checkbox', () => {
let checkbox: Locator
let closeButton: Locator
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setSetting(
'Comfy.Workflow.ShowMissingModelsWarning',
true
)
await comfyPage.loadWorkflow('missing_models')
checkbox = comfyPage.page.getByLabel("Don't show this again")
closeButton = comfyPage.page.getByLabel('Close')
})
test('Should disable warning dialog when checkbox is checked', async ({
comfyPage
}) => {
await checkbox.click()
const changeSettingPromise = comfyPage.page.waitForRequest(
'**/api/settings/Comfy.Workflow.ShowMissingModelsWarning'
)
await closeButton.click()
await changeSettingPromise
const settingValue = await comfyPage.getSetting(
'Comfy.Workflow.ShowMissingModelsWarning'
)
expect(settingValue).toBe(false)
})
test('Should keep warning dialog enabled when checkbox is unchecked', async ({
comfyPage
}) => {
await closeButton.click()
const settingValue = await comfyPage.getSetting(
'Comfy.Workflow.ShowMissingModelsWarning'
)
expect(settingValue).toBe(true)
})
})
})
test.describe('Settings', () => {
test('@mobile Should be visible on mobile', async ({ comfyPage }) => {
await comfyPage.page.keyboard.press('Control+,')
const searchBox = comfyPage.page.locator('.settings-content')
await expect(searchBox).toBeVisible()
const settingsContent = comfyPage.page.locator('.settings-content')
await expect(settingsContent).toBeVisible()
const isUsableHeight = await settingsContent.evaluate(
(el) => el.clientHeight > 30
)
expect(isUsableHeight).toBeTruthy()
})
test('Can open settings with hotkey', async ({ comfyPage }) => {
@@ -94,8 +230,90 @@ test.describe('Settings', () => {
test('Can change canvas zoom speed setting', async ({ comfyPage }) => {
const maxSpeed = 2.5
await comfyPage.setSetting('Comfy.Graph.ZoomSpeed', maxSpeed)
test.step('Setting should persist', async () => {
await test.step('Setting should persist', async () => {
expect(await comfyPage.getSetting('Comfy.Graph.ZoomSpeed')).toBe(maxSpeed)
})
})
test('Should persist keybinding setting', async ({ comfyPage }) => {
// Open the settings dialog
await comfyPage.page.keyboard.press('Control+,')
await comfyPage.page.waitForSelector('.settings-container')
// Open the keybinding tab
await comfyPage.page.getByLabel('Keybinding').click()
await comfyPage.page.waitForSelector(
'[placeholder="Search Keybindings..."]'
)
// Focus the 'New Blank Workflow' row
const newBlankWorkflowRow = comfyPage.page.locator('tr', {
has: comfyPage.page.getByRole('cell', { name: 'New Blank Workflow' })
})
await newBlankWorkflowRow.click()
// Click edit button
const editKeybindingButton = newBlankWorkflowRow.locator('.pi-pencil')
await editKeybindingButton.click()
// Set new keybinding
const input = comfyPage.page.getByPlaceholder('Press keys for new binding')
await input.press('Alt+n')
const requestPromise = comfyPage.page.waitForRequest(
'**/api/settings/Comfy.Keybinding.NewBindings'
)
// Save keybinding
const saveButton = comfyPage.page
.getByLabel('New Blank Workflow')
.getByLabel('Save')
await saveButton.click()
const request = await requestPromise
const expectedSetting: Keybinding = {
commandId: 'Comfy.NewBlankWorkflow',
combo: {
key: 'n',
ctrl: false,
alt: true,
shift: false
}
}
expect(request.postData()).toContain(JSON.stringify(expectedSetting))
})
})
test.describe('Feedback dialog', () => {
test('Should open from topmenu help command', async ({ comfyPage }) => {
// Open feedback dialog from top menu
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.menu.topbar.triggerTopbarCommand(['Help', 'Feedback'])
// Verify feedback dialog content is visible
const feedbackHeader = comfyPage.page.getByRole('heading', {
name: 'Feedback'
})
await expect(feedbackHeader).toBeVisible()
})
test('Should close when close button clicked', async ({ comfyPage }) => {
// Open feedback dialog
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.menu.topbar.triggerTopbarCommand(['Help', 'Feedback'])
const feedbackHeader = comfyPage.page.getByRole('heading', {
name: 'Feedback'
})
// Close feedback dialog
await comfyPage.page
.getByLabel('', { exact: true })
.getByLabel('Close')
.click()
await feedbackHeader.waitFor({ state: 'hidden' })
// Verify dialog is closed
await expect(feedbackHeader).not.toBeVisible()
})
})

View File

@@ -0,0 +1,27 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
test.describe('DOM Widget', () => {
test('Collapsed multiline textarea is not visible', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('collapsed_multiline')
expect(comfyPage.page.locator('.comfy-multiline-input')).not.toBeVisible()
})
test('Multiline textarea correctly collapses', async ({ comfyPage }) => {
const multilineTextAreas = comfyPage.page.locator('.comfy-multiline-input')
const firstMultiline = multilineTextAreas.first()
const lastMultiline = multilineTextAreas.last()
await expect(firstMultiline).toBeVisible()
await expect(lastMultiline).toBeVisible()
const nodes = await comfyPage.getNodeRefsByType('CLIPTextEncode')
for (const node of nodes) {
await node.click('collapse')
}
await expect(firstMultiline).not.toBeVisible()
await expect(lastMultiline).not.toBeVisible()
})
})

View File

@@ -1,4 +1,6 @@
import { expect, Locator } from '@playwright/test'
import { expect } from '@playwright/test'
import { SettingParams } from '../src/types/settingTypes'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
test.describe('Topbar commands', () => {
@@ -133,6 +135,90 @@ test.describe('Topbar commands', () => {
expect(await comfyPage.getSetting('Comfy.TestSetting')).toBe(true)
expect(await comfyPage.page.evaluate(() => window['changeCount'])).toBe(2)
})
test.describe('Passing through attrs to setting components', () => {
const testCases: Array<{
config: Partial<SettingParams>
selector: string
}> = [
{
config: {
type: 'boolean',
defaultValue: true
},
selector: '.p-toggleswitch.p-component'
},
{
config: {
type: 'number',
defaultValue: 10
},
selector: '.p-inputnumber input'
},
{
config: {
type: 'slider',
defaultValue: 10
},
selector: '.p-slider.p-component'
},
{
config: {
type: 'combo',
defaultValue: 'foo',
options: ['foo', 'bar', 'baz']
},
selector: '.p-select.p-component'
},
{
config: {
type: 'text',
defaultValue: 'Hello'
},
selector: '.p-inputtext'
},
{
config: {
type: 'color',
defaultValue: '#000000'
},
selector: '.p-colorpicker-preview'
}
] as const
for (const { config, selector } of testCases) {
test(`${config.type} component should respect disabled attr`, async ({
comfyPage
}) => {
await comfyPage.page.evaluate((config) => {
window['app'].registerExtension({
name: 'TestExtension1',
settings: [
{
id: 'Comfy.TestSetting',
name: 'Test',
// The `disabled` attr is common to all settings components
attrs: { disabled: true },
...config
}
]
})
}, config)
await comfyPage.settingDialog.open()
const component = comfyPage.settingDialog.root
.getByText('TestSetting Test')
.locator(selector)
const isDisabled = await component.evaluate((el) =>
el.tagName === 'INPUT'
? (el as HTMLInputElement).disabled
: el.classList.contains('p-disabled')
)
expect(isDisabled).toBe(true)
})
}
})
})
test.describe('About panel', () => {
@@ -157,4 +243,100 @@ test.describe('Topbar commands', () => {
expect(await badge.textContent()).toContain('Test Badge')
})
})
test.describe('Dialog', () => {
test('Should allow showing a prompt dialog', async ({ comfyPage }) => {
await comfyPage.page.evaluate(() => {
window['app'].extensionManager.dialog
.prompt({
title: 'Test Prompt',
message: 'Test Prompt Message'
})
.then((value: string) => {
window['value'] = value
})
})
await comfyPage.fillPromptDialog('Hello, world!')
expect(await comfyPage.page.evaluate(() => window['value'])).toBe(
'Hello, world!'
)
})
test('Should allow showing a confirmation dialog', async ({
comfyPage
}) => {
await comfyPage.page.evaluate(() => {
window['app'].extensionManager.dialog
.confirm({
title: 'Test Confirm',
message: 'Test Confirm Message'
})
.then((value: boolean) => {
window['value'] = value
})
})
await comfyPage.confirmDialog.click('confirm')
expect(await comfyPage.page.evaluate(() => window['value'])).toBe(true)
})
test('Should allow dismissing a dialog', async ({ comfyPage }) => {
await comfyPage.page.evaluate(() => {
window['value'] = 'foo'
window['app'].extensionManager.dialog
.confirm({
title: 'Test Confirm',
message: 'Test Confirm Message'
})
.then((value: boolean) => {
window['value'] = value
})
})
await comfyPage.confirmDialog.click('reject')
expect(await comfyPage.page.evaluate(() => window['value'])).toBeNull()
})
})
test.describe('Selection Toolbox', () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.Canvas.SelectionToolbox', true)
})
test('Should allow adding commands to selection toolbox', async ({
comfyPage
}) => {
// Register an extension with a selection toolbox command
await comfyPage.page.evaluate(() => {
window['app'].registerExtension({
name: 'TestExtension1',
commands: [
{
id: 'test.selection.command',
label: 'Test Command',
icon: 'pi pi-star',
function: () => {
window['selectionCommandExecuted'] = true
}
}
],
getSelectionToolboxCommands: () => ['test.selection.command']
})
})
await comfyPage.selectNodes(['CLIP Text Encode (Prompt)'])
// Click the command button in the selection toolbox
const toolboxButton = comfyPage.page.locator(
'.selection-toolbox button:has(.pi-star)'
)
await toolboxButton.click()
// Verify the command was executed
expect(
await comfyPage.page.evaluate(() => window['selectionCommandExecuted'])
).toBe(true)
})
})
})

View File

@@ -1,25 +1,38 @@
import type { Page, Locator, APIRequestContext } from '@playwright/test'
import type { LGraphNode } from '@comfyorg/litegraph'
import type { APIRequestContext, Locator, Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { test as base } from '@playwright/test'
import { ComfyActionbar } from '../helpers/actionbar'
import dotenv from 'dotenv'
dotenv.config()
import * as fs from 'fs'
import type { NodeId } from '../../src/schemas/comfyWorkflowSchema'
import type { KeyCombo } from '../../src/schemas/keyBindingSchema'
import type { useWorkspaceStore } from '../../src/stores/workspaceStore'
import { NodeBadgeMode } from '../../src/types/nodeSource'
import type { NodeId } from '../../src/types/comfyWorkflow'
import type { KeyCombo } from '../../src/types/keyBindingTypes'
import { ComfyActionbar } from '../helpers/actionbar'
import { ComfyTemplates } from '../helpers/templates'
import { ComfyNodeSearchBox } from './components/ComfyNodeSearchBox'
import { SettingDialog } from './components/SettingDialog'
import {
NodeLibrarySidebarTab,
QueueSidebarTab,
WorkflowsSidebarTab
} from './components/SidebarTab'
import { Topbar } from './components/Topbar'
import { NodeReference } from './utils/litegraphUtils'
import type { Position, Size } from './types'
import { SettingDialog } from './components/SettingDialog'
import { NodeReference } from './utils/litegraphUtils'
import TaskHistory from './utils/taskHistory'
dotenv.config()
type WorkspaceStore = ReturnType<typeof useWorkspaceStore>
class ComfyMenu {
private _nodeLibraryTab: NodeLibrarySidebarTab | null = null
private _workflowsTab: WorkflowsSidebarTab | null = null
private _queueTab: QueueSidebarTab | null = null
private _topbar: Topbar | null = null
public readonly sideToolbar: Locator
public readonly themeToggleButton: Locator
public readonly saveButton: Locator
@@ -33,15 +46,23 @@ class ComfyMenu {
}
get nodeLibraryTab() {
return new NodeLibrarySidebarTab(this.page)
this._nodeLibraryTab ??= new NodeLibrarySidebarTab(this.page)
return this._nodeLibraryTab
}
get workflowsTab() {
return new WorkflowsSidebarTab(this.page)
this._workflowsTab ??= new WorkflowsSidebarTab(this.page)
return this._workflowsTab
}
get queueTab() {
this._queueTab ??= new QueueSidebarTab(this.page)
return this._queueTab
}
get topbar() {
return new Topbar(this.page)
this._topbar ??= new Topbar(this.page)
return this._topbar
}
async toggleTheme() {
@@ -72,7 +93,33 @@ type FolderStructure = {
[key: string]: FolderStructure | string
}
type KeysOfType<T, Match> = {
[K in keyof T]: T[K] extends Match ? K : never
}[keyof T]
class ConfirmDialog {
public readonly delete: Locator
public readonly overwrite: Locator
public readonly reject: Locator
public readonly confirm: Locator
constructor(public readonly page: Page) {
this.delete = page.locator('button.p-button[aria-label="Delete"]')
this.overwrite = page.locator('button.p-button[aria-label="Overwrite"]')
this.reject = page.locator('button.p-button[aria-label="Cancel"]')
this.confirm = page.locator('button.p-button[aria-label="Confirm"]')
}
async click(locator: KeysOfType<ConfirmDialog, Locator>) {
const loc = this[locator]
await expect(loc).toBeVisible()
await loc.click()
}
}
export class ComfyPage {
private _history: TaskHistory | null = null
public readonly url: string
// All canvas position operations are based on default view of canvas.
public readonly canvas: Locator
@@ -91,6 +138,7 @@ export class ComfyPage {
public readonly actionbar: ComfyActionbar
public readonly templates: ComfyTemplates
public readonly settingDialog: SettingDialog
public readonly confirmDialog: ConfirmDialog
/** Worker index to test user ID */
public readonly userIds: string[] = []
@@ -115,6 +163,7 @@ export class ComfyPage {
this.actionbar = new ComfyActionbar(page)
this.templates = new ComfyTemplates(page)
this.settingDialog = new SettingDialog(page)
this.confirmDialog = new ConfirmDialog(page)
}
convertLeafToContent(structure: FolderStructure): FolderStructure {
@@ -204,6 +253,11 @@ export class ComfyPage {
}
}
setupHistory(): TaskHistory {
this._history ??= new TaskHistory(this)
return this._history
}
async setup({ clearStorage = true }: { clearStorage?: boolean } = {}) {
await this.goto()
if (clearStorage) {
@@ -225,8 +279,8 @@ export class ComfyPage {
await this.page.addStyleTag({
content: `
* {
font-family: 'Roboto Mono', 'Noto Color Emoji';
}`
font-family: 'Roboto Mono', 'Noto Color Emoji';
}`
})
await this.page.waitForFunction(() => document.fonts.ready)
await this.page.waitForFunction(
@@ -316,11 +370,6 @@ export class ComfyPage {
}, settingId)
}
async reload({ clearStorage = true }: { clearStorage?: boolean } = {}) {
await this.page.reload({ timeout: 15000 })
await this.setup({ clearStorage })
}
async goto() {
await this.page.goto(this.url)
}
@@ -487,6 +536,17 @@ export class ComfyPage {
return { x: 427, y: 98 }
}
get promptDialogInput() {
return this.page.locator('.p-dialog-content input[type="text"]')
}
async fillPromptDialog(value: string) {
await this.promptDialogInput.fill(value)
await this.page.keyboard.press('Enter')
await this.promptDialogInput.waitFor({ state: 'hidden' })
await this.nextFrame()
}
async disconnectEdge() {
await this.dragAndDrop(this.clipTextEncodeNode1InputSlot, this.emptySpace)
}
@@ -587,6 +647,18 @@ export class ComfyPage {
await this.nextFrame()
}
async selectNodes(nodeTitles: string[]) {
await this.page.keyboard.down('Control')
for (const nodeTitle of nodeTitles) {
const nodes = await this.getNodeRefsByTitle(nodeTitle)
for (const node of nodes) {
await node.click('title')
}
}
await this.page.keyboard.up('Control')
await this.nextFrame()
}
async select2Nodes() {
// Select 2 CLIP nodes.
await this.page.keyboard.down('Control')
@@ -737,28 +809,27 @@ export class ComfyPage {
)
}
async confirmDialog(prompt: string, text: string = 'Yes') {
async clickDialogButton(prompt: string, buttonText: string = 'Yes') {
const modal = this.page.locator(
`.comfy-modal-content:has-text("${prompt}")`
)
await expect(modal).toBeVisible()
await modal
.locator('.comfyui-button', {
hasText: text
hasText: buttonText
})
.click()
await expect(modal).toBeHidden()
}
async convertAllNodesToGroupNode(groupNodeName: string) {
this.page.on('dialog', async (dialog) => {
await dialog.accept(groupNodeName)
})
await this.canvas.press('Control+a')
const node = await this.getFirstNodeRef()
await node!.clickContextMenuOption('Convert to Group Node')
await this.fillPromptDialog(groupNodeName)
await this.nextFrame()
}
async convertOffsetToCanvas(pos: [number, number]) {
return this.page.evaluate((pos) => {
return window['app'].canvas.ds.convertOffsetToCanvas(pos)
@@ -767,17 +838,34 @@ export class ComfyPage {
async getNodeRefById(id: NodeId) {
return new NodeReference(id, this)
}
async getNodes() {
return await this.page.evaluate(() => {
return window['app'].graph.nodes
})
}
async getNodeRefsByType(type: string): Promise<NodeReference[]> {
return Promise.all(
(
await this.page.evaluate((type) => {
return window['app'].graph.nodes
.filter((n) => n.type === type)
.map((n) => n.id)
.filter((n: LGraphNode) => n.type === type)
.map((n: LGraphNode) => n.id)
}, type)
).map((id: NodeId) => this.getNodeRefById(id))
)
}
async getNodeRefsByTitle(title: string): Promise<NodeReference[]> {
return Promise.all(
(
await this.page.evaluate((title) => {
return window['app'].graph.nodes
.filter((n: LGraphNode) => n.title === title)
.map((n: LGraphNode) => n.id)
}, title)
).map((id: NodeId) => this.getNodeRefById(id))
)
}
async getFirstNodeRef(): Promise<NodeReference | null> {
const id = await this.page.evaluate(() => {
return window['app'].graph.nodes[0]?.id
@@ -788,29 +876,68 @@ export class ComfyPage {
async moveMouseToEmptyArea() {
await this.page.mouse.move(10, 10)
}
async getUndoQueueSize() {
return this.page.evaluate(() => {
const workflow = (window['app'].extensionManager as WorkspaceStore)
.workflow.activeWorkflow
return workflow?.changeTracker.undoQueue.length
})
}
async getRedoQueueSize() {
return this.page.evaluate(() => {
const workflow = (window['app'].extensionManager as WorkspaceStore)
.workflow.activeWorkflow
return workflow?.changeTracker.redoQueue.length
})
}
async isCurrentWorkflowModified() {
return this.page.evaluate(() => {
return (window['app'].extensionManager as WorkspaceStore).workflow
.activeWorkflow?.isModified
})
}
async getExportedWorkflow({ api = false }: { api?: boolean } = {}) {
return this.page.evaluate(async (api) => {
return (await window['app'].graphToPrompt())[api ? 'output' : 'workflow']
}, api)
}
async setFocusMode(focusMode: boolean) {
await this.page.evaluate((focusMode) => {
window['app'].extensionManager.focusMode = focusMode
}, focusMode)
await this.nextFrame()
}
}
export const comfyPageFixture = base.extend<{ comfyPage: ComfyPage }>({
comfyPage: async ({ page, request }, use) => {
comfyPage: async ({ page, request }, use, testInfo) => {
const comfyPage = new ComfyPage(page, request)
const { parallelIndex } = comfyPageFixture.info()
const { parallelIndex } = testInfo
const username = `playwright-test-${parallelIndex}`
const userId = await comfyPage.setupUser(username)
comfyPage.userIds[parallelIndex] = userId
await comfyPage.setupSettings({
'Comfy.UseNewMenu': 'Disabled',
// Hide canvas menu/info by default.
'Comfy.Graph.CanvasInfo': false,
'Comfy.Graph.CanvasMenu': false,
// Hide all badges by default.
'Comfy.NodeBadge.NodeIdBadgeMode': NodeBadgeMode.None,
'Comfy.NodeBadge.NodeSourceBadgeMode': NodeBadgeMode.None,
// Disable tooltips by default to avoid flakiness.
'Comfy.EnableTooltips': false,
'Comfy.userId': userId
})
try {
await comfyPage.setupSettings({
'Comfy.UseNewMenu': 'Disabled',
// Hide canvas menu/info/selection toolbox by default.
'Comfy.Graph.CanvasInfo': false,
'Comfy.Graph.CanvasMenu': false,
'Comfy.Canvas.SelectionToolbox': false,
// Hide all badges by default.
'Comfy.NodeBadge.NodeIdBadgeMode': NodeBadgeMode.None,
'Comfy.NodeBadge.NodeSourceBadgeMode': NodeBadgeMode.None,
// Disable tooltips by default to avoid flakiness.
'Comfy.EnableTooltips': false,
'Comfy.userId': userId,
// Set tutorial completed to true to avoid loading the tutorial workflow.
'Comfy.TutorialCompleted': true
})
} catch (e) {
console.error(e)
}
await comfyPage.setup()
await use(comfyPage)
}
@@ -845,5 +972,19 @@ const makeMatcher = function <T>(
export const comfyExpect = expect.extend({
toBePinned: makeMatcher((n) => n.isPinned(), 'pinned'),
toBeBypassed: makeMatcher((n) => n.isBypassed(), 'bypassed'),
toBeCollapsed: makeMatcher((n) => n.isCollapsed(), 'collapsed')
toBeCollapsed: makeMatcher((n) => n.isCollapsed(), 'collapsed'),
async toHaveFocus(locator: Locator, options = { timeout: 256 }) {
const isFocused = await locator.evaluate(
(el) => el === document.activeElement
)
await expect(async () => {
expect(isFocused).toBe(!this.isNot)
}).toPass(options)
return {
pass: isFocused,
message: () => `Expected element to ${isFocused ? 'not ' : ''}be focused.`
}
}
})

View File

@@ -0,0 +1,41 @@
import { test as base } from '@playwright/test'
import { Page } from 'playwright'
export class UserSelectPage {
constructor(
public readonly url: string,
public readonly page: Page
) {}
get selectionUrl() {
return this.url + '/user-select'
}
get container() {
return this.page.locator('#comfy-user-selection')
}
get newUserInput() {
return this.container.locator('#new-user-input')
}
get existingUserSelect() {
return this.container.locator('#existing-user-select')
}
get nextButton() {
return this.container.getByText('Next')
}
}
export const userSelectPageFixture = base.extend<{
userSelectPage: UserSelectPage
}>({
userSelectPage: async ({ page }, use) => {
const userSelectPage = new UserSelectPage(
process.env.PLAYWRIGHT_TEST_URL || 'http://localhost:8188',
page
)
await use(userSelectPage)
}
})

View File

@@ -3,6 +3,13 @@ import { Locator, Page } from '@playwright/test'
export class ComfyNodeSearchFilterSelectionPanel {
constructor(public readonly page: Page) {}
get header() {
return this.page
.getByRole('dialog')
.locator('div')
.filter({ hasText: 'Add node filter condition' })
}
async selectFilterType(filterType: string) {
await this.page
.locator(

View File

@@ -3,6 +3,10 @@ import { Page } from '@playwright/test'
export class SettingDialog {
constructor(public readonly page: Page) {}
get root() {
return this.page.locator('div.settings-container')
}
async open() {
const button = this.page.locator('button.comfy-settings-btn:visible')
await button.click()

View File

@@ -22,6 +22,12 @@ class SidebarTab {
}
await this.tabButton.click()
}
async close() {
if (!this.tabButton.isVisible()) {
return
}
await this.tabButton.click()
}
}
export class NodeLibrarySidebarTab extends SidebarTab {
@@ -85,32 +91,36 @@ export class WorkflowsSidebarTab extends SidebarTab {
super(page, 'workflows')
}
get root() {
return this.page.locator('.workflows-sidebar-tab')
}
get browseGalleryButton() {
return this.page.locator('.browse-templates-button')
return this.root.locator('.browse-templates-button')
}
get newBlankWorkflowButton() {
return this.page.locator('.new-blank-workflow-button')
return this.root.locator('.new-blank-workflow-button')
}
get openWorkflowButton() {
return this.page.locator('.open-workflow-button')
return this.root.locator('.open-workflow-button')
}
async getOpenedWorkflowNames() {
return await this.page
return await this.root
.locator('.comfyui-workflows-open .node-label')
.allInnerTexts()
}
async getActiveWorkflowName() {
return await this.page
return await this.root
.locator('.comfyui-workflows-open .p-tree-node-selected .node-label')
.innerText()
}
async getTopLevelSavedWorkflowNames() {
return await this.page
return await this.root
.locator('.comfyui-workflows-browse .node-label')
.allInnerTexts()
}
@@ -122,13 +132,13 @@ export class WorkflowsSidebarTab extends SidebarTab {
}
getOpenedItem(name: string) {
return this.page.locator('.comfyui-workflows-open .node-label', {
return this.root.locator('.comfyui-workflows-open .node-label', {
hasText: name
})
}
getPersistedItem(name: string) {
return this.page.locator('.comfyui-workflows-browse .node-label', {
return this.root.locator('.comfyui-workflows-browse .node-label', {
hasText: name
})
}
@@ -142,4 +152,132 @@ export class WorkflowsSidebarTab extends SidebarTab {
await this.page.keyboard.press('Enter')
await this.page.waitForTimeout(300)
}
async insertWorkflow(locator: Locator) {
await locator.click({ button: 'right' })
await this.page
.locator('.p-contextmenu-item-content', { hasText: 'Insert' })
.click()
}
}
export class QueueSidebarTab extends SidebarTab {
constructor(public readonly page: Page) {
super(page, 'queue')
}
get root() {
return this.page.locator('.sidebar-content-container', { hasText: 'Queue' })
}
get tasks() {
return this.root.locator('[data-virtual-grid-item]')
}
get visibleTasks() {
return this.tasks.locator('visible=true')
}
get clearButton() {
return this.root.locator('.clear-all-button')
}
get collapseTasksButton() {
return this.getToggleExpandButton(false)
}
get expandTasksButton() {
return this.getToggleExpandButton(true)
}
get noResultsPlaceholder() {
return this.root.locator('.no-results-placeholder')
}
get galleryImage() {
return this.page.locator('.galleria-image')
}
private getToggleExpandButton(isExpanded: boolean) {
const iconSelector = isExpanded ? '.pi-image' : '.pi-images'
return this.root.locator(`.toggle-expanded-button ${iconSelector}`)
}
async open() {
await super.open()
return this.root.waitFor({ state: 'visible' })
}
async close() {
await super.close()
await this.root.waitFor({ state: 'hidden' })
}
async expandTasks() {
await this.expandTasksButton.click()
await this.collapseTasksButton.waitFor({ state: 'visible' })
}
async collapseTasks() {
await this.collapseTasksButton.click()
await this.expandTasksButton.waitFor({ state: 'visible' })
}
async waitForTasks() {
return Promise.all([
this.tasks.first().waitFor({ state: 'visible' }),
this.tasks.last().waitFor({ state: 'visible' })
])
}
async scrollTasks(direction: 'up' | 'down') {
const scrollToEl =
direction === 'up' ? this.tasks.last() : this.tasks.first()
await scrollToEl.scrollIntoViewIfNeeded()
await this.waitForTasks()
}
async clearTasks() {
await this.clearButton.click()
const confirmButton = this.page.getByLabel('Delete')
await confirmButton.click()
await this.noResultsPlaceholder.waitFor({ state: 'visible' })
}
/** Set the width of the tab (out of 100). Must call before opening the tab */
async setTabWidth(width: number) {
if (width < 0 || width > 100) {
throw new Error('Width must be between 0 and 100')
}
return this.page.evaluate((width) => {
localStorage.setItem('queue', JSON.stringify([width, 100 - width]))
}, width)
}
getTaskPreviewButton(taskIndex: number) {
return this.tasks.nth(taskIndex).getByRole('button')
}
async openTaskPreview(taskIndex: number) {
const previewButton = this.getTaskPreviewButton(taskIndex)
await previewButton.click()
return this.galleryImage.waitFor({ state: 'visible' })
}
getGalleryImage(imageFilename: string) {
return this.galleryImage.and(this.page.getByAltText(imageFilename))
}
getTaskImage(imageFilename: string) {
return this.tasks.getByAltText(imageFilename)
}
/** Trigger the queue store and tasks to update */
async triggerTasksUpdate() {
await this.page.evaluate(() => {
window['app']['api'].dispatchCustomEvent('status', {
exec_info: { queue_remaining: 0 }
})
})
}
}

View File

@@ -9,6 +9,12 @@ export class Topbar {
.allInnerTexts()
}
async getActiveTabName(): Promise<string> {
return this.page
.locator('.workflow-tabs .p-togglebutton-checked')
.innerText()
}
async openSubmenuMobile() {
await this.page.locator('.p-menubar-mobile .p-menubar-button').click()
}
@@ -40,7 +46,14 @@ export class Topbar {
return this._saveWorkflow(workflowName, 'Save As')
}
async _saveWorkflow(workflowName: string, command: 'Save' | 'Save As') {
exportWorkflow(workflowName: string): Promise<void> {
return this._saveWorkflow(workflowName, 'Export')
}
async _saveWorkflow(
workflowName: string,
command: 'Save' | 'Save As' | 'Export'
) {
await this.triggerTopbarCommand(['Workflow', command])
await this.getSaveDialog().fill(workflowName)
await this.page.keyboard.press('Enter')

View File

@@ -1,6 +1,7 @@
import { ManageGroupNode } from '../../helpers/manageGroupNode'
import type { NodeId } from '../../../src/types/comfyWorkflow'
import type { Page } from '@playwright/test'
import type { NodeId } from '../../../src/types/comfyWorkflow'
import { ManageGroupNode } from '../../helpers/manageGroupNode'
import type { ComfyPage } from '../ComfyPage'
import type { Position, Size } from '../types'
@@ -61,6 +62,9 @@ export class NodeWidgetReference {
readonly node: NodeReference
) {}
/**
* @returns The position of the widget's center
*/
async getPosition(): Promise<Position> {
const pos: [number, number] = await this.node.comfyPage.page.evaluate(
([id, index]) => {
@@ -82,6 +86,28 @@ export class NodeWidgetReference {
y: pos[1]
}
}
async click() {
await this.node.comfyPage.canvas.click({
position: await this.getPosition()
})
}
async dragHorizontal(delta: number) {
const pos = await this.getPosition()
const canvas = this.node.comfyPage.canvas
const canvasPos = (await canvas.boundingBox())!
this.node.comfyPage.dragAndDrop(
{
x: canvasPos.x + pos.x,
y: canvasPos.y + pos.y
},
{
x: canvasPos.x + pos.x + delta,
y: canvasPos.y + pos.y
}
)
}
}
export class NodeReference {
@@ -233,10 +259,8 @@ export class NodeReference {
await ctx.getByText(optionText).click()
}
async convertToGroupNode(groupNodeName: string = 'GroupNode') {
this.comfyPage.page.once('dialog', async (dialog) => {
await dialog.accept(groupNodeName)
})
await this.clickContextMenuOption('Convert to Group Node')
await this.comfyPage.fillPromptDialog(groupNodeName)
await this.comfyPage.nextFrame()
const nodes = await this.comfyPage.getNodeRefsByType(
`workflow>${groupNodeName}`

View File

@@ -0,0 +1,162 @@
import fs from 'fs'
import _ from 'lodash'
import path from 'path'
import type { Request, Route } from 'playwright'
import { v4 as uuidv4 } from 'uuid'
import type {
HistoryTaskItem,
TaskItem,
TaskOutput
} from '../../../src/schemas/apiSchema'
import type { ComfyPage } from '../ComfyPage'
/** keyof TaskOutput[string] */
type OutputFileType = 'images' | 'audio' | 'animated'
const DEFAULT_IMAGE = 'example.webp'
const getFilenameParam = (request: Request) => {
const url = new URL(request.url())
return url.searchParams.get('filename') || DEFAULT_IMAGE
}
const getContentType = (filename: string, fileType: OutputFileType) => {
const subtype = path.extname(filename).slice(1)
switch (fileType) {
case 'images':
return `image/${subtype}`
case 'audio':
return `audio/${subtype}`
case 'animated':
return `video/${subtype}`
}
}
const setQueueIndex = (task: TaskItem) => {
task.prompt[0] = TaskHistory.queueIndex++
}
const setPromptId = (task: TaskItem) => {
task.prompt[1] = uuidv4()
}
export default class TaskHistory {
static queueIndex = 0
static readonly defaultTask: Readonly<HistoryTaskItem> = {
prompt: [0, 'prompt-id', {}, { client_id: uuidv4() }, []],
outputs: {},
status: {
status_str: 'success',
completed: true,
messages: []
},
taskType: 'History'
}
private tasks: HistoryTaskItem[] = []
private outputContentTypes: Map<string, string> = new Map()
constructor(readonly comfyPage: ComfyPage) {}
private loadAsset: (filename: string) => Buffer = _.memoize(
(filename: string) => {
const filePath = this.comfyPage.assetPath(filename)
return fs.readFileSync(filePath)
}
)
private async handleGetHistory(route: Route) {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(this.tasks)
})
}
private async handleGetView(route: Route) {
const fileName = getFilenameParam(route.request())
if (!this.outputContentTypes.has(fileName)) route.continue()
const asset = this.loadAsset(fileName)
return route.fulfill({
status: 200,
contentType: this.outputContentTypes.get(fileName),
body: asset,
headers: {
'Cache-Control': 'public, max-age=31536000',
'Content-Length': asset.byteLength.toString()
}
})
}
async setupRoutes() {
return this.comfyPage.page.route(
/.*\/api\/(view|history)(\?.*)?$/,
async (route) => {
const request = route.request()
const method = request.method()
const isViewReq = request.url().includes('view') && method === 'GET'
if (isViewReq) return this.handleGetView(route)
const isHistoryPath = request.url().includes('history')
const isGetHistoryReq = isHistoryPath && method === 'GET'
if (isGetHistoryReq) return this.handleGetHistory(route)
const isClearReq =
method === 'POST' &&
isHistoryPath &&
request.postDataJSON()?.clear === true
if (isClearReq) return this.clearTasks()
return route.continue()
}
)
}
private createOutputs(
filenames: string[],
filetype: OutputFileType
): TaskOutput {
return filenames.reduce((outputs, filename, i) => {
const nodeId = `${i + 1}`
outputs[nodeId] = {
[filetype]: [{ filename, subfolder: '', type: 'output' }]
}
const contentType = getContentType(filename, filetype)
this.outputContentTypes.set(filename, contentType)
return outputs
}, {})
}
private addTask(task: HistoryTaskItem) {
setPromptId(task)
setQueueIndex(task)
this.tasks.unshift(task) // Tasks are added to the front of the queue
}
clearTasks(): this {
this.tasks = []
return this
}
withTask(
outputFilenames: string[],
outputFiletype: OutputFileType = 'images',
overrides: Partial<HistoryTaskItem> = {}
): this {
this.addTask({
...TaskHistory.defaultTask,
outputs: this.createOutputs(outputFilenames, outputFiletype),
...overrides
})
return this
}
/** Repeats the last task in the task history a specified number of times. */
repeat(n: number): this {
for (let i = 0; i < n; i++)
this.addTask(structuredClone(this.tasks.at(0)) as HistoryTaskItem)
return this
}
}

View File

@@ -1,7 +1,8 @@
import { FullConfig } from '@playwright/test'
import { backupPath } from './utils/backupUtils'
import dotenv from 'dotenv'
import { backupPath } from './utils/backupUtils'
dotenv.config()
export default function globalSetup(config: FullConfig) {

View File

@@ -1,7 +1,8 @@
import { FullConfig } from '@playwright/test'
import { restorePath } from './utils/backupUtils'
import dotenv from 'dotenv'
import { restorePath } from './utils/backupUtils'
dotenv.config()
export default function globalTeardown(config: FullConfig) {

View File

@@ -1,4 +1,5 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
test.describe('Graph Canvas Menu', () => {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 100 KiB

View File

@@ -1,4 +1,5 @@
import { expect } from '@playwright/test'
import { ComfyPage, comfyPageFixture as test } from './fixtures/ComfyPage'
import type { NodeReference } from './fixtures/utils/litegraphUtils'
@@ -103,6 +104,67 @@ test.describe('Group Node', () => {
await expect(comfyPage.page.locator('.node-tooltip')).toBeVisible()
})
test('Manage group opens with the correct group selected', async ({
comfyPage
}) => {
const makeGroup = async (name, type1, type2) => {
const node1 = (await comfyPage.getNodeRefsByType(type1))[0]
const node2 = (await comfyPage.getNodeRefsByType(type2))[0]
await node1.click('title')
await node2.click('title', {
modifiers: ['Shift']
})
return await node2.convertToGroupNode(name)
}
const group1 = await makeGroup(
'g1',
'CLIPTextEncode',
'CheckpointLoaderSimple'
)
const group2 = await makeGroup('g2', 'EmptyLatentImage', 'KSampler')
const manage1 = await group1.manageGroupNode()
await comfyPage.nextFrame()
expect(await manage1.getSelectedNodeType()).toBe('g1')
await manage1.close()
await expect(manage1.root).not.toBeVisible()
const manage2 = await group2.manageGroupNode()
expect(await manage2.getSelectedNodeType()).toBe('g2')
})
test('Preserves hidden input configuration when containing duplicate node types', async ({
comfyPage
}) => {
await comfyPage.loadWorkflow('group_node_identical_nodes_hidden_inputs')
await comfyPage.nextFrame()
const groupNodeId = 19
const groupNodeName = 'two_VAE_decode'
const totalInputCount = await comfyPage.page.evaluate((nodeName) => {
const {
extra: { groupNodes }
} = window['app'].graph
const { nodes } = groupNodes[nodeName]
return nodes.reduce((acc: number, node) => {
return acc + node.inputs.length
}, 0)
}, groupNodeName)
const visibleInputCount = await comfyPage.page.evaluate((id) => {
const node = window['app'].graph.getNodeById(id)
return node.inputs.length
}, groupNodeId)
// Verify there are 4 total inputs (2 VAE decode nodes with 2 inputs each)
expect(totalInputCount).toBe(4)
// Verify there are 2 visible inputs (2 have been hidden in config)
expect(visibleInputCount).toBe(2)
})
test('Reconnects inputs after configuration changed via manage dialog save', async ({
comfyPage
}) => {

View File

@@ -1,4 +1,5 @@
import type { Page, Locator } from '@playwright/test'
import type { Locator, Page } from '@playwright/test'
import type { AutoQueueMode } from '../../src/stores/queueStore'
export class ComfyActionbar {

View File

@@ -1,12 +1,15 @@
import { Locator, Page } from '@playwright/test'
export class ManageGroupNode {
footer: Locator
header: Locator
constructor(
readonly page: Page,
readonly root: Locator
) {
this.footer = root.locator('footer')
this.header = root.locator('header')
}
async setLabel(name: string, label: string) {
@@ -23,6 +26,11 @@ export class ManageGroupNode {
await this.footer.getByText('Close').click()
}
async getSelectedNodeType() {
const select = this.header.locator('select').first()
return await select.inputValue()
}
async selectNode(name: string) {
const list = this.root.locator('.comfy-group-manage-list-items')
const item = list.getByText(name)

View File

@@ -1,4 +1,9 @@
import { Locator, Page } from '@playwright/test'
import path from 'path'
import { CORE_TEMPLATES } from '../../src/constants/coreTemplates'
import { TemplateInfo } from '../../src/types/workflowTemplateTypes'
export class ComfyTemplates {
readonly content: Locator
@@ -7,6 +12,17 @@ export class ComfyTemplates {
}
async loadTemplate(id: string) {
await this.content.getByTestId(`template-workflow-${id}`).click()
await this.content
.getByTestId(`template-workflow-${id}`)
.getByRole('img')
.click()
}
getAllTemplates(): TemplateInfo[] {
return CORE_TEMPLATES.flatMap((category) => category.templates)
}
getTemplatePath(filename: string): string {
return path.join('public', 'templates', filename)
}
}

View File

@@ -1,4 +1,5 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from './fixtures/ComfyPage'
test.describe('Item Interaction', () => {
@@ -452,6 +453,9 @@ test.describe('Canvas Interaction', () => {
expect(await getCursorStyle()).toBe('default')
await comfyPage.page.mouse.down()
expect(await getCursorStyle()).toBe('grabbing')
// Move mouse should not alter cursor style.
await comfyPage.page.mouse.move(10, 20)
expect(await getCursorStyle()).toBe('grabbing')
await comfyPage.page.mouse.up()
expect(await getCursorStyle()).toBe('default')
@@ -465,6 +469,43 @@ test.describe('Canvas Interaction', () => {
expect(await getCursorStyle()).toBe('default')
})
// https://github.com/Comfy-Org/litegraph.js/pull/424
test('Properly resets dragging state after pan mode sequence', async ({
comfyPage
}) => {
const getCursorStyle = async () => {
return await comfyPage.page.evaluate(() => {
return (
document.getElementById('graph-canvas')!.style.cursor || 'default'
)
})
}
// Initial state check
await comfyPage.page.mouse.move(10, 10)
expect(await getCursorStyle()).toBe('default')
// Click and hold
await comfyPage.page.mouse.down()
expect(await getCursorStyle()).toBe('grabbing')
// Press space while holding click
await comfyPage.page.keyboard.down('Space')
expect(await getCursorStyle()).toBe('grabbing')
// Release click while space is still down
await comfyPage.page.mouse.up()
expect(await getCursorStyle()).toBe('grab')
// Release space
await comfyPage.page.keyboard.up('Space')
expect(await getCursorStyle()).toBe('default')
// Move mouse - cursor should remain default
await comfyPage.page.mouse.move(20, 20)
expect(await getCursorStyle()).toBe('default')
})
test('Can pan when dragging a link', async ({ comfyPage }) => {
const posSlot1 = comfyPage.clipTextEncodeNode1InputSlot
await comfyPage.page.mouse.move(posSlot1.x, posSlot1.y)
@@ -552,7 +593,7 @@ test.describe('Load workflow', () => {
}) => {
await comfyPage.loadWorkflow('single_ksampler')
await expect(comfyPage.canvas).toHaveScreenshot('single_ksampler.png')
await comfyPage.reload({ clearStorage: false })
await comfyPage.setup({ clearStorage: false })
await expect(comfyPage.canvas).toHaveScreenshot('single_ksampler.png')
})
@@ -569,11 +610,72 @@ test.describe('Load workflow', () => {
await expect(comfyPage.canvas).toHaveScreenshot(
'single_ksampler_modified.png'
)
await comfyPage.reload({ clearStorage: false })
await comfyPage.setup({ clearStorage: false })
await expect(comfyPage.canvas).toHaveScreenshot(
'single_ksampler_modified.png'
)
})
test.describe('Restore all open workflows on reload', () => {
let workflowA: string
let workflowB: string
const generateUniqueFilename = (extension = '') =>
`${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}${extension}`
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
workflowA = generateUniqueFilename()
await comfyPage.menu.topbar.saveWorkflow(workflowA)
workflowB = generateUniqueFilename()
await comfyPage.menu.topbar.triggerTopbarCommand(['Workflow', 'New'])
await comfyPage.menu.topbar.saveWorkflow(workflowB)
// Wait for localStorage to persist the workflow paths before reloading
await comfyPage.page.waitForFunction(
() => !!window.localStorage.getItem('Comfy.OpenWorkflowsPaths')
)
await comfyPage.setup({ clearStorage: false })
})
test('Restores topbar workflow tabs after reload', async ({
comfyPage
}) => {
await comfyPage.setSetting(
'Comfy.Workflow.WorkflowTabsPosition',
'Topbar'
)
const tabs = await comfyPage.menu.topbar.getTabNames()
const activeWorkflowName = await comfyPage.menu.topbar.getActiveTabName()
expect(tabs).toEqual(expect.arrayContaining([workflowA, workflowB]))
expect(tabs.indexOf(workflowA)).toBeLessThan(tabs.indexOf(workflowB))
expect(activeWorkflowName).toEqual(workflowB)
})
test('Restores sidebar workflows after reload', async ({ comfyPage }) => {
await comfyPage.setSetting(
'Comfy.Workflow.WorkflowTabsPosition',
'Sidebar'
)
await comfyPage.menu.workflowsTab.open()
const openWorkflows =
await comfyPage.menu.workflowsTab.getOpenedWorkflowNames()
const activeWorkflowName =
await comfyPage.menu.workflowsTab.getActiveWorkflowName()
const workflowPathA = `${workflowA}.json`
const workflowPathB = `${workflowB}.json`
expect(openWorkflows).toEqual(
expect.arrayContaining([workflowPathA, workflowPathB])
)
expect(openWorkflows.indexOf(workflowPathA)).toBeLessThan(
openWorkflows.indexOf(workflowPathB)
)
expect(activeWorkflowName).toEqual(workflowPathB)
})
})
})
test.describe('Load duplicate workflow', () => {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Some files were not shown because too many files have changed in this diff Show More