Compare commits

...

454 Commits

Author SHA1 Message Date
Chenlei Hu
33dc74fa2a scroll queue item for long text 2025-05-22 10:39:11 -04:00
Chenlei Hu
bd37da7161 nit 2025-05-22 10:39:11 -04:00
Chenlei Hu
0b8d98e1e7 Add to preview gallery 2025-05-22 10:39:09 -04:00
Chenlei Hu
25a6b9f393 Copy to clipboard 2025-05-22 10:38:52 -04:00
Chenlei Hu
bdf32790c9 wip 2025-05-22 10:38:48 -04:00
Comfy Org PR Bot
0095f02f46 1.21.0 (#3962)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-21 21:35:34 -04:00
Christian Byrne
178c79e559 [fix] Make gallery navigation buttons visible on mobile devices (#3953) 2025-05-21 21:34:13 -04:00
Christian Byrne
7c0040bfec Move user.css to user data (#3952) 2025-05-21 21:33:11 -04:00
Christian Byrne
77f91dea10 [Dev Tool] Add claude directives (#3960) 2025-05-21 21:32:18 -04:00
Christian Byrne
4ad6475283 [Feature] Add audio preview support to queue sidebar (#3954)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-21 21:31:38 -04:00
Terry Jia
b531d34027 [3d] performance improve (#3961) 2025-05-21 21:29:52 -04:00
Christian Byrne
55ad207345 Trigger browser test expectations update (#3959)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-21 17:20:55 -07:00
Christian Byrne
ccc1039abb [feat] Add file upload support to canvas background image setting (#3958)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-21 16:06:16 -07:00
Christian Byrne
49400c69b6 Set output as background (#3079)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-21 12:15:15 -04:00
Comfy Org PR Bot
32605eeb8f 1.20.4 (#3951)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-20 23:03:12 -04:00
Christian Byrne
f08ec0a981 [API Node] Add cost indicators on API nodes (#3924)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-05-20 21:59:11 -04:00
Christian Byrne
356886dc29 [Feature] Add MP4 workflow file open support (#3950) 2025-05-20 17:57:20 -07:00
Christian Byrne
f96de24a66 Migrate user.css file to upstream (#3949) 2025-05-20 20:11:06 -04:00
Christian Byrne
9d48487af8 [Dev Tools] Add more claude directives (#3948)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-20 13:45:31 -07:00
Christian Byrne
69b534bf14 [UI] Improve template card spacing and responsive image display (#3930)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-20 14:14:05 -04:00
Christian Byrne
2acb2ac181 [Style] Increase template card elevation in dark mode (#3946) 2025-05-20 14:13:12 -04:00
Christian Byrne
37a583e39c [fix] Adjust API node badge colors for light theme (#3945) 2025-05-20 14:12:51 -04:00
gfejer
d8821db2be PWA support (#3639)
Co-authored-by: bymyself <cbyrne@comfy.org>
2025-05-20 02:31:59 -07:00
Yiximail
f2c4e567e4 Add a button to selection toolbox to open mask editor (#3603)
Co-authored-by: bymyself <cbyrne@comfy.org>
2025-05-20 01:23:39 -07:00
Christian Byrne
fec4c4e928 [docs] Add comprehensive documentation for browser tests (#3942)
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2025-05-19 23:08:03 -07:00
Terry Jia
49d32f4809 [3d] support mtl for obj file (#3933)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-19 20:48:57 -07:00
Christian Byrne
07f0b88e30 Require description field to be non-empty when reporting issue from the UI (#3939)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-20 13:18:19 +10:00
Christian Byrne
d92ed22908 Remove leftover asset (#3938) 2025-05-20 12:46:35 +10:00
Christian Byrne
24c0c2c499 [Dev Tools] Add claude config (#3937) 2025-05-20 12:34:51 +10:00
Christian Byrne
774bff2ed6 [Refactor] Move component test next to component (#3940) 2025-05-20 11:52:26 +10:00
Comfy Org PR Bot
6d87f2b2ff 1.20.3 (#3932)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-18 21:26:18 -04:00
Christian Byrne
20911aa892 docs: improve README development section organization (#3929)
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2025-05-19 09:38:59 +10:00
Christian Byrne
3a6018589e Add testing documentation guides for frontend tests (#3927) 2025-05-19 08:41:51 +10:00
Christian Byrne
4c92a7142e Fix: Close user popover on button clicks (#3928) 2025-05-19 08:41:33 +10:00
Christian Byrne
293993e7de Hide manager button in missing nodes dialog when manager is not installed (#3925) 2025-05-18 12:16:24 -04:00
Christian Byrne
a7ee3fae05 Add tests for ChatHistoryWidget and related features (#3921) 2025-05-18 12:16:06 -04:00
Christian Byrne
22dc84324e [docs] add READMEs for major folders (#3923) 2025-05-18 12:11:56 -04:00
Christian Byrne
e76e9ec61a docs: enhance README with development setup and troubleshooting guides (#3920) 2025-05-17 17:15:10 -04:00
filtered
94fde504d0 [CI] Add dev release GH Action (#3910) 2025-05-17 12:43:01 +10:00
Comfy Org PR Bot
e3ecf90bb3 1.20.2 (#3917)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-16 22:02:09 -04:00
Yoland Yan
a131f36cf3 [Fix] Fix out of bound issue when window was close and reopen at diff size (#3906) 2025-05-16 22:01:30 -04:00
Christian Byrne
4cad1a9567 Add LLM chat history widget (#3907)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-16 22:00:45 -04:00
filtered
47a6c6d595 [Dev] Allow Vue dev tools to be disabled (#3911) 2025-05-16 21:59:23 -04:00
filtered
068279ec34 Replace reactive DragAndScale proxy with callback (#3915) 2025-05-16 21:58:21 -04:00
Comfy Org PR Bot
2885ebf5e0 [chore] Update litegraph to 0.15.11 (#3914)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-17 02:03:58 +10:00
Yoland Yan
d4e76ddc45 Add vite-plugin-html and vite-plugin-vue-devtools (#3903) 2025-05-15 14:51:39 -04:00
Chenlei Hu
9a5b80a279 [Refactor] Split SelectionToolbox buttons to components (#3902) 2025-05-15 11:20:51 -04:00
filtered
985dab7e1c Allow LGraph.configure to be made recursive (#3894) 2025-05-15 10:48:56 -04:00
filtered
7f2b8a5321 [CodeHealth] Add various minor fixes - logging, missed i18n (#3895)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-15 22:04:48 +10:00
filtered
59ce169ec9 Add selection changed state watcher (#3899) 2025-05-15 21:13:54 +10:00
Comfy Org PR Bot
4294b2c13b [chore] Update litegraph to 0.15.10 (#3898)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-15 20:22:01 +10:00
Comfy Org PR Bot
242c7e2885 1.20.1 (#3891)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-14 22:40:07 -04:00
Chenlei Hu
c1442ec755 [Cleanup] Remove api nodes news dialog (#3890)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-14 21:06:08 -04:00
Terry Jia
ebd9c96a28 [3d] bug fix and add loading for background image change (#3888) 2025-05-14 16:11:36 -04:00
Chenlei Hu
e6d649b596 [Refactor] Convert NodeBadge.vue to composable (#3883) 2025-05-13 21:56:26 -04:00
Comfy Org PR Bot
b037ba84e3 1.20.0 (#3850)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-05-13 21:05:21 -04:00
杨必赞
7c5c47c105 expose user loggedin in extensionManager (#3871) 2025-05-13 21:04:27 -04:00
Chenlei Hu
b152f67d95 [Refactor] useBrowserTabTitle composable (#3881) 2025-05-13 17:02:54 -04:00
Chenlei Hu
be84d81c32 [Branding] Show execution progress in favicon (#3880) 2025-05-13 15:57:18 -04:00
Christian Byrne
a474a094f3 [Manager] Fix search results render incorrectly when scrolling pages then changing query or tab (#3879) 2025-05-13 15:29:10 -04:00
Christian Byrne
bc360eef15 [Manager] Cache Algolia searches and limit suggestions queries (#3876) 2025-05-13 15:28:42 -04:00
Christian Byrne
a52cc0ebe9 [Manager] Don't show empty suggestions dropdown (#3878) 2025-05-13 11:40:15 -07:00
Christian Byrne
b3c6513e7a Fix bug: Virtual Grid increments page size when no results left to render (#3877) 2025-05-13 11:26:00 -07:00
Christian Byrne
a9bdc70e28 [API Node] Show message tip about API-key-based login (#3851)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <hcl@comfy.org>
2025-05-13 13:03:13 -04:00
filtered
58906fa821 [CodeHealth] Remove remaining uses of global app var (#3868) 2025-05-13 12:01:02 -04:00
filtered
a17fb04f83 [Test] Add per-workflow viewport comparison test (#3867)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-13 11:48:38 +10:00
Comfy Org PR Bot
5c0ad994d8 1.19.9 (#3866)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-12 16:25:19 -04:00
filtered
31be0a04f0 Use upstreamed viewport serialisation (#3864) 2025-05-13 05:33:10 +10:00
Comfy Org PR Bot
d9ab4270d1 [chore] Update litegraph to 0.15.9 (#3863)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-13 05:11:00 +10:00
filtered
36bd1f74ca [TS] Fix weak ds.offset type breaks litegraph CI (#3861) 2025-05-13 04:34:47 +10:00
filtered
7144ec54aa Fix UI crash when selecting broken node + TS fixes (#3859) 2025-05-12 17:57:59 +10:00
Dr.Lt.Data
b2f144c27b refine locales/ko (#3853) 2025-05-12 04:25:02 +10:00
Christian Byrne
014c0022c1 [API Node] Remove mailto on own address (#3852) 2025-05-11 11:12:54 +10:00
Comfy Org PR Bot
5d556c9c94 1.19.8 (#3849)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-10 18:18:54 -04:00
Christian Byrne
992c2ba822 Show text progress messages on executing nodes (#3824) 2025-05-10 16:10:58 -04:00
Christian Byrne
4cc6a15fde Fix refresh combos command fails on nodes using V2 spec (#3848) 2025-05-10 16:06:25 -04:00
Christian Byrne
3f50b8b46d [Test] Add missing plugins in component tests (#3847) 2025-05-10 16:05:30 -04:00
Christian Byrne
bb588ff44e [API Node] Use staging platform url while in dev environment (#3846) 2025-05-10 16:04:51 -04:00
Christian Byrne
974236ce5a Fix video previews not displayed if VHS previously installed but disabled or uninstalled (#3844) 2025-05-10 16:03:55 -04:00
Comfy Org PR Bot
6ed870d431 1.19.7 (#3837)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-09 19:40:11 -04:00
thot experiment
4e25a78d2d add audio preview widgets to new save nodes (#3840) 2025-05-09 19:34:37 -04:00
Christian Byrne
6408623b71 [API Node] Show user state when logged in via API key (#3838)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <hcl@comfy.org>
2025-05-09 14:45:32 -04:00
Comfy Org PR Bot
fdad2475ce Update locales for node definitions (#3792)
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
2025-05-09 14:11:38 -04:00
Chenlei Hu
5486fb94a0 [API Nodes] Add api pricing link to user popover (#3836)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-09 14:11:01 -04:00
Christian Byrne
34b1fd5a72 [API Node] Allow authentification via Comfy API key (#3815)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-09 13:42:03 -04:00
thot experiment
aa46524829 add workflow parsing for mp3 and opus formats (#3832) 2025-05-09 13:40:50 -04:00
filtered
3bd87820eb Fix undo / redo resets viewport (#3834) 2025-05-09 18:55:34 +10:00
filtered
0f95ed852e [TS] Fix / consolidate DOM widget types (#3830) 2025-05-09 16:24:31 +10:00
Comfy Org PR Bot
3501b480d4 [chore] Update litegraph to 0.15.8 (#3827)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-09 15:48:22 +10:00
filtered
5fa0401acd Fix workflow Export missing viewport scale/offset (#3828) 2025-05-09 14:58:16 +10:00
Comfy Org PR Bot
4d39dc28e0 1.19.6 (#3825)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-08 21:36:15 -04:00
Chenlei Hu
2a297e512d Fit view on workflow load without extra.ds (#3822)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-08 17:39:44 -04:00
Chenlei Hu
2019c1d877 Align reset_view param on json file load (#3823) 2025-05-08 16:00:13 -04:00
Chenlei Hu
2425e32d51 Partial execute to selected output nodes (#3818)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-08 11:44:26 -04:00
Comfy Org PR Bot
b6466c44e5 1.19.5 (#3817)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-07 22:36:19 -04:00
filtered
13441add24 Convert DOM widgets to Litegraph widget subclass (#3813) 2025-05-08 10:25:54 +10:00
Comfy Org PR Bot
64ce8ce5ed [chore] Update litegraph to 0.15.6 (#3814)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-08 09:39:07 +10:00
Comfy Org PR Bot
841ff0b46c [chore] Update litegraph to 0.15.5 (#3812)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-08 09:05:03 +10:00
Chenlei Hu
df86da3d67 [Bug] Add null check on customSpec being null (#3810) 2025-05-07 17:09:52 -04:00
filtered
3aea2c120a Update widget types to match Litegraph changes (#3808) 2025-05-08 06:56:53 +10:00
Comfy Org PR Bot
6fdef0308b [chore] Update litegraph to 0.15.4 (#3809)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-08 06:43:40 +10:00
Chenlei Hu
973a1eb0a9 [Bug] Guard link fixer with try-catch (#3806) 2025-05-07 16:10:21 -04:00
filtered
b9d9ce78f9 [TS] Widget typing (#3804) 2025-05-08 04:38:17 +10:00
Benjamin Lu
bb1ac32ccd Revert "Remove Release Summary section in README (#3607)" (#3802) 2025-05-07 13:56:05 -04:00
Christian Byrne
1ef3c007e6 [Auth] Allow user select GitHub account on login (#3801) 2025-05-07 12:03:23 -04:00
Terry Jia
db81b62274 [3d] add record video support for load3d animation node (#3798) 2025-05-07 10:12:33 -04:00
Comfy Org PR Bot
43365b4318 1.19.4 (#3800)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-07 23:11:01 +10:00
Comfy Org PR Bot
dfdffcd27e [chore] Update litegraph to 0.15.3 (#3799)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-07 22:47:16 +10:00
Comfy Org PR Bot
252454484f [chore] Update litegraph to 0.15.2 (#3797)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-07 22:41:23 +10:00
Comfy Org PR Bot
c1984f7ccd 1.19.3 (#3795)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-06 22:04:37 -04:00
Christian Byrne
bbbf140b1f Handle user avatar error (#3735)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-06 22:04:25 -04:00
Terry Jia
754eb807de [3d] some improvement for load3d recording video (#3794) 2025-05-06 22:03:12 -04:00
filtered
fad6c6c502 [nit] Further simplify watcher via whenever (#3790) 2025-05-06 20:23:46 -04:00
Chenlei Hu
926278e9ef [nit] Simplify selection overlay watcher (#3789) 2025-05-06 16:07:19 -04:00
Chenlei Hu
131fae72d4 [Branding] Use new logo on menu bar (#3788) 2025-05-06 15:18:50 -04:00
Comfy Org PR Bot
a8a7288e0d [chore] Update litegraph to 0.15.1 (#3784)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-07 02:01:50 +10:00
Chenlei Hu
2a21dd1004 [Branding] Use new logo favicon (#3787) 2025-05-06 11:02:49 -04:00
Chenlei Hu
3bdd814b3c [Branding] Use new comfyorg logo (#3786) 2025-05-06 10:54:37 -04:00
filtered
0da6be5cdc [Refactor] Update Litegraph widget types / cleanup (#3782) 2025-05-06 19:40:30 +10:00
Comfy Org PR Bot
6a3cf9e698 [chore] Update litegraph to 0.15.0 (#3759)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-05-06 18:54:33 +10:00
Christian Byrne
6b98f1de0e [API Node] Adjust notification dismiss logic and message (#3778) 2025-05-06 00:51:47 -07:00
Chenlei Hu
d05a340949 [Auth] Allow user select google account on login (#3777) 2025-05-05 23:16:16 -04:00
Comfy Org PR Bot
ca16e55579 1.19.2 (#3774)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-05 21:16:28 -04:00
Christian Byrne
a54529da40 [API Node] Refine locales (#3772) 2025-05-05 21:16:19 -04:00
Christian Byrne
f52915a590 Allow disabling proxy of /template path via env (#3773) 2025-05-05 17:48:11 -07:00
Christian Byrne
13b00cdbc6 Update template titles (#3771) 2025-05-05 19:05:35 -04:00
Christian Byrne
626b54da27 Fix: latent preview format is read from wrong byte of header (#3761) 2025-05-05 15:08:55 -07:00
Christian Byrne
c24472aeac [API Node] Add localizations for template workflow descriptions (#3769)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-05 12:53:02 -07:00
Chenlei Hu
ea605887fa [API Nodes] Add cost badge for api nodes (#3768) 2025-05-05 14:25:19 -04:00
Chenlei Hu
6edea73bf8 Update blog post link (#3767) 2025-05-05 13:56:20 -04:00
Chenlei Hu
6b8bf989f1 [API Nodes] Apply yellow color to api nodes by default (#3766) 2025-05-05 13:56:11 -04:00
Christian Byrne
3758a435cb [API Node] Sort API templates by localized display name (#3765)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-05 10:55:02 -07:00
Christian Byrne
813bf11484 Fix execution error message overflowing out of screen (#3762) 2025-05-05 23:20:32 +10:00
filtered
b5ae354bec Prevent node tooltip from breaking pan & zoom (#3760) 2025-05-05 22:48:25 +10:00
Comfy Org PR Bot
7a1a626b36 1.19.1 (#3756)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-04 20:45:43 -04:00
Comfy Org PR Bot
63d24301a3 [chore] Update litegraph to 0.15.0-3 (#3757)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-05 09:31:52 +10:00
Chenlei Hu
93d7d2c69c [Bug] Remove default dialog close button on news dialog (#3758) 2025-05-04 19:07:13 -04:00
Chenlei Hu
2d9a0d02ab [API Nodes] Add API Nodes new feature dialog (#3755)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-04 17:20:05 -04:00
filtered
6601cf6959 Add setting to enable Litegraph trackpad gestures (#3751)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-04 14:31:43 +10:00
Terry Jia
77ac4a415c [3d] add recording video support (#3749)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-03 23:00:07 -04:00
Comfy Org PR Bot
8ae36e2c8d [chore] Update litegraph to 0.15.0-2 (#3750)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-04 12:01:52 +10:00
Yiximail
cb9ec354e7 Implement mask editor undo/redo (#3708) 2025-05-03 19:55:37 -04:00
filtered
8713cd6e25 [TS] Require override keyword (#3746) 2025-05-03 19:54:45 -04:00
filtered
c30244ef66 [Desktop] Fix Server-Config panel does not load (#3743) 2025-05-04 05:13:04 +10:00
Comfy Org PR Bot
2024aa6562 1.19.0 (#3737)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-03 11:14:47 -04:00
filtered
00c2181bb6 Show warning toast when no items are selected (#3741) 2025-05-03 11:14:02 -04:00
Christian Byrne
743f3cb5a1 [Subgraph] Add subgraph breadcrumbs component (#3241)
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2025-05-03 09:31:45 +10:00
Comfy Org PR Bot
111fdcc71a [chore] Update litegraph to 0.15.0-1 (#3738)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-03 08:33:18 +10:00
Terry Jia
ba3b1bae87 add List view for workflow tempalte (#3710)
Co-authored-by: Chenlei Hu <hcl@comfy.org>
Co-authored-by: github-actions <github-actions@github.com>
2025-05-02 17:50:53 -04:00
Christian Byrne
23d32282bc Fix: server fails to load SVG outputs when user has "Preview Format" setting specified (#3734) 2025-05-02 10:09:50 -07:00
Chenlei Hu
197f33ffcd [Bug] Register dom widget when only node is added to graph (#3732) 2025-05-02 12:49:19 -04:00
filtered
b618ebe36d Change groupNode menu anchor to retain position (#3733) 2025-05-03 02:11:06 +10:00
Benjamin Lu
b61640c51b [Desktop] Add toasts for update check (#3723)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2025-05-02 11:06:51 -04:00
Comfy Org PR Bot
869f500d4e 1.18.6 (#3730)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-02 10:59:25 -04:00
Chenlei Hu
ec8ee49a2c [Bug] Fix zoom lag of DOM widget (#3714) 2025-05-02 10:58:51 -04:00
Comfy Org PR Bot
53372110d3 [chore] Update electron-types to 0.4.43 (#3731)
Co-authored-by: benceruleanlu <162923238+benceruleanlu@users.noreply.github.com>
2025-05-02 10:32:13 -04:00
Christian Byrne
1cbc0fc613 [API Node] Sort API templates by name (#3721) 2025-05-01 21:30:32 -04:00
filtered
c82401c61c [TS] Fix strict type on chain callback, widgetInput (#3727) 2025-05-01 21:29:43 -04:00
Comfy Org PR Bot
2c75948ab9 [chore] Update litegraph to 0.15.0-0 (#3725)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-02 10:27:52 +10:00
filtered
89b826a231 [Test] Add missing test expectation (#3724)
Co-authored-by: github-actions <github-actions@github.com>
2025-05-02 09:57:29 +10:00
Christian Byrne
3806ba3bf1 Increase template card titles' line height to 2 lines (#3722) 2025-05-01 19:28:02 -04:00
thot experiment
878aedb4f7 add svg metadata loading (#3719)
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2025-05-02 09:26:24 +10:00
Comfy Org PR Bot
f7e4ed23d7 [chore] Update litegraph to 0.14.6 (#3717)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-05-01 16:19:35 -04:00
Chenlei Hu
4461210f43 Prune widgets on graph configure (#3716) 2025-05-01 16:07:42 -04:00
dependabot[bot]
f868fac6e9 Bump vite from 5.4.18 to 5.4.19 (#3715)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-01 15:13:28 -04:00
Comfy Org PR Bot
f7b51bbf7d [chore] Update litegraph to 0.14.5 (#3713)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-02 02:56:39 +10:00
Comfy Org PR Bot
8b6758ddfc 1.18.5 (#3711)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-05-01 08:53:53 -04:00
Comfy Org PR Bot
0d87f301b9 [chore] Update litegraph to 0.14.4 (#3706)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-05-01 08:50:51 -04:00
Christian Byrne
8349181321 Fix parsing workflows from mp4 (isobmff) (#3707) 2025-05-01 08:50:24 -04:00
Chenlei Hu
98b75e4819 [Bug] Fix staging tag shown in prod (#3705) 2025-04-30 19:36:07 -04:00
Chenlei Hu
d41b8c4e83 [Refactor] Use single map to store dom widget and states (#3703) 2025-04-30 19:29:49 -04:00
Chenlei Hu
ee8f0bf013 [Style] Fix user icon size (#3701) 2025-04-30 16:19:59 -04:00
Chenlei Hu
834d5820d2 [Auth] Allow change password in user panel (#3699)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-30 16:12:57 -04:00
Comfy Org PR Bot
a43d1e1ee8 1.18.4 (#3686)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-30 10:32:08 -04:00
Benjamin Lu
35f0551244 Personal Data Consent Checkbox (#3697)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-30 10:29:46 -04:00
filtered
838acefd72 Fix graph.change called twice on keypress (#3695) 2025-04-30 17:59:01 +10:00
Chenlei Hu
df723b56da Show staging tag for staging firebase (#3693) 2025-04-29 21:32:00 -04:00
Benjamin Lu
c5eb97e563 Add contact info to auth modal (#3692)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-29 20:36:25 -04:00
Chenlei Hu
98d7256da4 Remove refresh button when all nodes are selected (#3690) 2025-04-29 19:59:49 -04:00
Christian Byrne
4828af9a13 [API Node] Update FAQ link to docs.comfy (#3691) 2025-04-29 19:59:28 -04:00
Benjamin Lu
4e0950d953 Adopt copilot instructions (#3689) 2025-04-29 18:46:53 -04:00
Chenlei Hu
beec20a382 [Style] Hide deprecated settings on UI (#3688) 2025-04-29 18:45:41 -04:00
Chenlei Hu
b4731637d4 [Style] Use icon for experimental setting tag (#3687) 2025-04-29 15:59:40 -04:00
Chenlei Hu
30ce4a243d [Refactor] Extract CreditTopUpOption component (#3685) 2025-04-29 14:10:09 -04:00
Chenlei Hu
a2f04844e0 [Bug] Identify api nodes as core nodes (#3683) 2025-04-29 11:45:52 -04:00
Comfy Org PR Bot
1531025070 1.18.3 (#3677)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-29 11:26:52 -04:00
Terry Jia
fb14d24047 [upstream] Upstream PreviewAny from rgthree-comfy (#3640) 2025-04-29 11:23:30 -04:00
filtered
04815605b4 Fix two undo steps on add node via context menu (#3674) 2025-04-29 11:23:12 -04:00
Terry Jia
c7435af51b better expression (#3678) 2025-04-29 11:18:01 -04:00
filtered
3bc9a3933f Fix two undo steps on alt-click to add reroute (#3675) 2025-04-28 19:20:00 -04:00
filtered
bd1890a422 [Refactor] Convert save viewport in workflow to watcher (#3673) 2025-04-29 06:49:41 +10:00
Chenlei Hu
5ec4ec8303 [Bug] Fix mp4 output preview in queue (#3672) 2025-04-28 15:25:53 -04:00
Chenlei Hu
b1a98437e4 [Auth] Warn insecure context on login (#3663)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-27 22:04:19 -04:00
Christian Byrne
96d954ceb2 [API Node] Conditional signup render (#3653)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <hcl@comfy.org>
2025-04-27 21:47:17 -04:00
Chenlei Hu
c6cb3f0a33 [Auth] Report better auth domain error (#3662)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-27 21:29:52 -04:00
Comfy Org PR Bot
25136cc63d [chore] Update litegraph to 0.14.3 (#3660)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-04-27 21:01:29 -04:00
Chenlei Hu
8472bde5dd [Cleanup] Remove unnecessary null check on auth (2/2) (#3661)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-27 20:50:59 -04:00
Comfy Org PR Bot
3b6dc28727 1.18.2 (#3659)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-27 19:14:19 -04:00
filtered
6835b2bb5c Add theme colour for disabled widgets (#3657) 2025-04-27 19:12:47 -04:00
Comfy Org PR Bot
8f540e6603 [chore] Update litegraph to 0.14.2 (#3650)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-27 05:41:32 +10:00
Christian Byrne
99cc587abf Load workflows from mp4/mov files (#3543)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-26 12:31:29 -07:00
Benjamin Lu
82c5f02c3d Add contributing guidelines to README.md (#3637)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-26 08:39:35 -04:00
Chenlei Hu
04f447c2a3 [Cleanup] Remove tooltip on current user button (#3636) 2025-04-25 19:27:47 -04:00
Benjamin Lu
84c14ddd92 Remove automatic nightly pytorch for blackwell users on desktop (#3613)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-25 18:08:37 -04:00
Comfy Org PR Bot
c7e6d66d47 [chore] Update electron-types to 0.4.42 (#3634)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-26 07:45:10 +10:00
filtered
5d4be8dc63 Fix electron type workflow (#3633) 2025-04-26 07:43:35 +10:00
Chenlei Hu
0bec26ca4b [Cleanup] Remove api.listUserData (#3632) 2025-04-25 15:55:42 -04:00
Chenlei Hu
45eb4701d2 Implement top menu user popover (#3631)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-25 15:26:41 -04:00
Chenlei Hu
25359575db [Refactor] Extract user credit component (#3630) 2025-04-25 15:02:36 -04:00
Comfy Org PR Bot
d0b99b95c6 1.18.1 (#3629)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-25 13:34:35 -04:00
filtered
ddff592561 Fix new link follows pointer until menu closed (#3628)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-26 03:26:03 +10:00
Benjamin Lu
8491ca91b7 Move component tests into the same directory as their component counterparts (#3625)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-25 13:13:30 -04:00
Yiximail
630fa04882 Fix dynamic screen height (#3626) 2025-04-25 13:12:30 -04:00
Comfy Org PR Bot
bf80ae7295 [chore] Update litegraph to 0.14.1 (#3627)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-26 02:38:46 +10:00
Yiximail
44348180f5 Fix long-press to open contextmenu on touch devices (#3624) 2025-04-25 11:30:13 -04:00
Benjamin Lu
4e12800336 Expand component test coverage to BrowserTabTitle (#3623)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-25 11:03:46 -04:00
Yiximail
d883448b86 Fix incorrect touch event handling by accurately tracking touch points (#3622) 2025-04-25 10:54:34 -04:00
Benjamin Lu
1c59e3b51b [nit] Use TorchMirrorUrl (#3617)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-25 10:52:52 -04:00
Chenlei Hu
b79cbf69af Use PrimeVue Avatar component (#3615) 2025-04-24 21:49:03 -04:00
Chenlei Hu
b05407ffdd [Refactor] Split authStore into authStore and authService (#3612)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-24 20:45:30 -04:00
Benjamin Lu
2a62f7ec7f ignore Vite timestamped config modules in .gitignore (#3614)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-24 20:40:18 -04:00
Benjamin Lu
bf757c11ef Reland "Add unified sidebar width setting" (#3611)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
2025-04-24 17:45:25 -04:00
Chenlei Hu
0ed29a198d [Cleanup] Remove unnecessary null check on auth (#3610) 2025-04-24 17:36:16 -04:00
Chenlei Hu
31d5671f24 Revert "Add unified sidebar width setting" (#3609) 2025-04-24 17:14:01 -04:00
Benjamin Lu
ba3e2edb8a Add unified sidebar width setting (#3605)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
2025-04-24 16:41:46 -04:00
Benjamin Lu
9c2300d780 Update README with Recommended Code Editor Configuration (#3606)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-24 16:34:38 -04:00
Benjamin Lu
3f85ff751c Remove Release Summary section in README (#3607)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-24 16:34:07 -04:00
Chenlei Hu
0caf1686c3 Add Comfy.User.SignOut command (#3608)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-24 16:33:26 -04:00
Chenlei Hu
26f98d24fb [Refactor] Async load all setting panels (#3604) 2025-04-24 13:00:42 -04:00
Comfy Org PR Bot
fcbdee54ec 1.18.0 (#3552)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-04-24 12:43:44 -04:00
filtered
a944372f39 Improve default node sizes (#3596)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-24 12:42:16 -04:00
Comfy Org PR Bot
df51e89311 [chore] Update litegraph to 0.14.0 (#3602)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-04-25 01:00:15 +10:00
Terry Jia
b314435f81 add importmap for vue-i18n (#3595) 2025-04-23 22:34:19 -04:00
Chenlei Hu
ba367c0214 [nit] Rename credit history to invoice history (#3598)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-23 22:33:52 -04:00
Chenlei Hu
64ad6a9bb0 Re-style TopUpCreditDialog to match design (#3597) 2025-04-23 22:28:35 -04:00
AustinMroz
3819db5ec4 Introduce widgetType option to inputSpec (#3550) 2025-04-23 20:36:01 -04:00
filtered
80517e8204 [Test] Add test expectation (#3593) 2025-04-24 08:48:06 +10:00
Comfy Org PR Bot
40034e77f9 1.17.11 (#3592)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-24 08:04:24 +10:00
filtered
2ef8b7cfd7 Fix opening search from context menu (#3591)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-24 07:54:27 +10:00
Comfy Org PR Bot
9cf3a0e568 1.17.10 (#3590)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-23 15:19:22 -04:00
Chenlei Hu
f562cf27cd [API Node] Workaround custom node hijack on api.queuePrompt (#3589)
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2025-04-23 15:18:37 -04:00
Chenlei Hu
4244a0a258 [Cleanup] Remove unused dialog functions (#3588) 2025-04-23 11:46:50 -04:00
Comfy Org PR Bot
ad3d2fe2e9 1.17.9 (#3585)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-23 11:16:46 -04:00
Chenlei Hu
4c23cfbd4d [API Node] Better execution error handling (#3587)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-23 11:15:38 -04:00
Chenlei Hu
9e10e55633 [Schema] Add api_node flag to node def schema (#3586) 2025-04-23 10:47:08 -04:00
Christian Byrne
59cbe90fd3 [API Node] Reset password (#3578)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-23 10:13:17 -04:00
Christian Byrne
16bd9abccd Translate user and credits settings categories (#3580)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-23 10:12:14 -04:00
Christian Byrne
e84bdc96cf Update FAQ link (#3579) 2025-04-23 10:12:02 -04:00
Comfy Org PR Bot
a57be36d4d 1.17.8 (#3573)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-22 22:26:48 -04:00
Christian Byrne
3bd508c001 Use generalized prod config var (#3574) 2025-04-22 22:26:31 -04:00
Chenlei Hu
612500a4dc [nit] Fix typo (#3577) 2025-04-22 21:35:26 -04:00
Christian Byrne
e9723407d8 [API Node] Fix credits fetch condition (#3575) 2025-04-22 21:33:44 -04:00
Christian Byrne
a01aa39423 [API Node] Show error toast (#3576) 2025-04-22 21:32:52 -04:00
Chenlei Hu
ab94a55858 Show user avatar on top menu if available (#3572) 2025-04-22 19:47:34 -04:00
Christian Byrne
1bcf5e28d4 [API Node] Contact support button (#3571)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-22 19:47:23 -04:00
Chenlei Hu
9e247063aa [nit] Adjust font size of User Panel header (#3570) 2025-04-22 19:03:40 -04:00
Comfy Org PR Bot
cdddf359a8 1.17.7 (#3569)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-22 18:52:13 -04:00
Christian Byrne
8558f87547 [API Node] User management (#3567)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <hcl@comfy.org>
2025-04-22 18:48:45 -04:00
Chenlei Hu
262991db6b [Bug] Prevent node pasting in signin dialog (#3568) 2025-04-22 16:18:25 -04:00
Chenlei Hu
585d52e24e [Bug] Fix DOM widgets position when canvas bounding box change (#3565)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-22 15:11:54 -04:00
Chenlei Hu
b7535755f0 Revert "[nit] Remove tab index on canvas element" (#3566) 2025-04-22 12:58:37 -04:00
Chenlei Hu
6b7b0f6ec1 [nit] Remove tab index on canvas element (#3563) 2025-04-22 11:40:22 -04:00
filtered
c7318bcf0a Update node search to use litegraph LinkConnector (#3546)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-22 10:35:49 -04:00
Christian Byrne
11f909436c [Manager] Fix reactivity of node pack version options dropdown (#3557) 2025-04-22 09:45:46 -04:00
Comfy Org PR Bot
d8f4dc95bb 1.17.6 (#3558)
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
2025-04-21 22:50:43 -07:00
Christian Byrne
c1bc664edd Add command to open signin dialog (#3556)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-21 22:46:31 -07:00
Christian Byrne
e7fe2046ba Checkout on credit add (#3555) 2025-04-21 22:46:05 -07:00
Comfy Org PR Bot
bf4ad38e9b 1.17.5 (#3551)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-21 20:08:30 -04:00
Chenlei Hu
2b024bb186 [Cleanup] Remove LGraphNode.isValidWidgetLink (#3549) 2025-04-21 15:48:55 -04:00
filtered
6e5930c355 [API] Add sockets to custom widgets by default (#3548) 2025-04-21 15:24:48 -04:00
Comfy Org PR Bot
6151d487c6 [chore] Update litegraph to 0.13.8 (#3547)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-22 02:17:12 +10:00
Comfy Org PR Bot
e027a9bf44 [chore] Update litegraph to 0.13.7 (#3544)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-04-21 11:00:10 -04:00
filtered
53ee5904e8 [TS] Fix serialisation type (#3541) 2025-04-21 21:13:42 +10:00
Christian Byrne
f82bb71b1e Fix client => canvas position conversion (#3540) 2025-04-21 20:21:25 +10:00
Terry Jia
40d08a890d [3d] move default values of backgroundColor, LightIntensity, LightMaximum, LightMinimum, LightStep to settings panel (#3536)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-20 23:08:23 -04:00
Chenlei Hu
ebf3c0c049 [API Nodes] Add credit management panel UI (#3535)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-20 22:11:43 -04:00
Comfy Org PR Bot
e77d5c1f57 1.17.4 (#3533)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-20 21:04:14 -04:00
Chenlei Hu
b5c1da22db [API Nodes] Remove cost from signin required dialog (#3532) 2025-04-20 17:02:42 -04:00
Chenlei Hu
0006dd3855 [Refactor] Split custom vite plugins to files under build/plugins (#3531) 2025-04-20 14:07:45 -04:00
Terry Jia
7355209c12 build vue and primevue separately and generate importmap (#3473)
Co-authored-by: Chenlei Hu <hcl@comfy.org>
2025-04-20 13:43:22 -04:00
Chenlei Hu
2aef0a9af8 [Bug] Fix model name (#3530) 2025-04-20 13:16:13 -04:00
Chenlei Hu
b74887d543 [i18n] Use gpt-o4-mini for translation (#3529) 2025-04-20 13:13:00 -04:00
Benjamin Lu
bf4ae227b3 Add manual update check (#3504)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-04-20 12:28:59 -04:00
Christian Byrne
184bb582da [Manager] Check if node is core node when inferring node pack (#3521) 2025-04-20 12:13:50 -04:00
Christian Byrne
3bc3179763 Apply filename text replacements (e.g., %date:hh:mm:ss%) in all save nodes (#3523) 2025-04-20 12:12:28 -04:00
Comfy Org PR Bot
eb100894ce [chore] Update Comfy Registry API types from comfy-api@7bc8051 (#3524)
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
2025-04-20 12:12:14 -04:00
Comfy Org PR Bot
9a992cb14d [chore] Update litegraph to 0.13.6 (#3528)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-21 01:18:27 +10:00
Comfy Org PR Bot
133aa9bc87 [chore] Update litegraph to 0.13.5 (#3527)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-20 21:31:02 +10:00
Dr.Lt.Data
3204637e5a refine locales/ko (#3526) 2025-04-20 21:14:33 +10:00
Comfy Org PR Bot
b2cb719026 1.17.3 (#3520)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-19 22:21:18 -04:00
Christian Byrne
add805460c Fix drag and drop image with embedded workflow on Firefox (#3519)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-19 22:19:48 -04:00
Benjamin Lu
9621b8f339 [Desktop] Support Nvidia Blackwell (#3480)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-19 21:42:30 -04:00
Christian Byrne
6be381b15d Allow git describe formatted versions of node packs in workflows (#3518) 2025-04-19 21:42:01 -04:00
Christian Byrne
8afe99f48c Fix node.widgets undefined on refresh (#3515) 2025-04-20 10:21:31 +10:00
Christian Byrne
9cd11261f9 [API Node] Set auth persistence in local stoarge (#3514) 2025-04-18 23:15:07 -04:00
Comfy Org PR Bot
fbc6665ff4 1.17.2 (#3513)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-18 22:26:07 -04:00
Christian Byrne
2daa51421c Remove fetch-templates script (#3500) 2025-04-18 20:34:03 -04:00
Christian Byrne
0f175c3dc1 [Api Node] Add ToS and privacy policy links (#3511) 2025-04-18 20:21:20 -04:00
Christian Byrne
8d4263c94e Use dev firebase and switch to prod in release workflow (#3499) 2025-04-18 17:23:10 -04:00
Chenlei Hu
04580ac031 [SettingUI] Group setting menu items (#3510) 2025-04-18 16:47:32 -04:00
Chenlei Hu
cd35f1d86d [Refactor] Generate DOM widget id in constructor (#3508) 2025-04-18 13:47:16 -04:00
Chenlei Hu
5d584577fe [Bug] Fix uuid generation in insecure context (#3505) 2025-04-18 11:43:25 -04:00
filtered
10a96d1af6 [TMP] Temporarily disable hidream template test (#3502) 2025-04-18 21:34:02 +10:00
Comfy Org PR Bot
03392a3cc7 1.17.1 (#3486)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-17 22:57:57 -04:00
Christian Byrne
12576243ad Remove unused tailwind classes (#3495) 2025-04-17 22:57:47 -04:00
Christian Byrne
e2a6dc2ec8 [Templates] Use fallbacks when translating template titles and category names (#3494) 2025-04-17 22:57:03 -04:00
Chenlei Hu
2f77d74891 [Refactor] Move tree logic to setting composable (#3491) 2025-04-17 16:34:42 -04:00
Chenlei Hu
dacb59f5d3 [Refactor] Extract setting dialog logic into composables (#3490) 2025-04-17 15:55:16 -04:00
Christian Byrne
74f991ec1b Translate Wan2.1-Fun template titles (#3489)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-17 15:55:08 -04:00
Christian Byrne
6bc03a624e Add HiDream templates translations (#3485)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-17 13:46:11 -04:00
Christian Byrne
1fb015e046 Remove templates build from release process (#3481) 2025-04-17 10:41:36 -04:00
Christian Byrne
87bf2310b6 Support previewing animated image uploads (#3479)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-17 10:20:09 -04:00
filtered
f1a25989d7 Fix corrupt workflow permanently corrupts session (#3484) 2025-04-17 10:18:14 -04:00
filtered
236e3fb3e9 Log errors in generic error handler (#3482) 2025-04-17 15:16:05 +10:00
Chenlei Hu
50382827bc [API Nodes] Add auth_token_comfy_org to queue prompt request body (#3477) 2025-04-16 15:26:25 -04:00
Christian Byrne
41675805b6 [Test] Add LGraphBadge light theme browser test (#3475)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-16 15:10:14 -04:00
Makki Shizu
6321fae6f3 fix 2_pass_pose_worship zh translation (#3474) 2025-04-16 11:04:28 -04:00
Chenlei Hu
06caa21a4d [API Nodes] Setup Google/Github login (#3471) 2025-04-15 20:56:18 -04:00
Chenlei Hu
9ce3cccfd4 [API Nodes] Wire password login (#3469) 2025-04-15 19:41:22 -04:00
Chenlei Hu
9935b322f0 [API Nodes] Signin/Signup dialog (#3466)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-15 17:37:53 -04:00
Comfy Org PR Bot
60dd242b23 [chore] Update Comfy Registry API types from comfy-api@b664e39 (#3465)
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
2025-04-15 17:16:02 -04:00
Christian Byrne
cec0dcbccd [Api Node] Firebase auth and user auth store (#3467) 2025-04-15 17:15:51 -04:00
Chenlei Hu
907632a250 Use bundler moduleResolution mode in tsconfig (#3464) 2025-04-15 11:17:07 -04:00
Comfy Org PR Bot
45c450cdb9 [chore] Update litegraph to 0.13.3 (#3463)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-15 11:03:32 -04:00
Chenlei Hu
ca85b2b144 [DevExperience] Add recommended extensions to .vscode (#3459) 2025-04-15 10:27:43 -04:00
Comfy Org PR Bot
1f28e6ef33 1.17.0 (#3458)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-14 21:06:33 -04:00
Comfy Org PR Bot
fee444c64b [chore] Update litegraph to 0.13.2 (#3460)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-14 21:06:23 -04:00
Chenlei Hu
851739a768 [API Node] Sign in required dialog (#3457)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-14 17:49:17 -04:00
Benjamin Lu
1631665efb Fix minor typo (#3456)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-14 13:24:13 -04:00
Terry Jia
1a066c7062 [3d] move default values of showPreview, showGrid, cameraType to settings panel (#3443)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-13 19:44:47 -04:00
Chenlei Hu
e45f5bdebb [lint] Fix remaining vue lint warnings (#3435) 2025-04-12 22:29:29 -04:00
Dr.Lt.Data
c270e7734a refine locales/ko (#3434) 2025-04-12 22:19:11 -04:00
Chenlei Hu
8d7a21e008 [lint] Add eslint-plugin-prettier (#3433) 2025-04-12 22:12:50 -04:00
Comfy Org PR Bot
29e63baca6 1.16.7 (#3430)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-12 21:22:02 -04:00
Benjamin Lu
b22713daf0 Add source prop to commands (#3429)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
2025-04-12 21:20:53 -04:00
Benjamin Lu
c8b8953e0a Add reset individual keybind button (#3423)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-12 16:59:00 -04:00
Benjamin Lu
731ce8599d Allow scrolling on .settings-content (#3427)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-12 16:58:08 -04:00
filtered
ec8e55c1c1 Allow zooming inside multi-line string widgets (#3422)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-12 13:13:00 -04:00
dependabot[bot]
04d38f2538 Bump vite from 5.4.17 to 5.4.18 (#3426)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-12 12:19:10 -04:00
Chenlei Hu
1c41db75f8 [Type] Enable strict schema type for setting entries (#3425) 2025-04-12 11:34:02 -04:00
Christian Byrne
c7a7397000 [Types] Make more types available directly in @comfyorg/comfyui-frontend-types package (#3418) 2025-04-12 11:33:34 -04:00
Terry Jia
e660e1d678 [3d] add support to output camera state (#3421) 2025-04-12 11:27:05 -04:00
Christian Byrne
fb19752389 [Types] Adds missing settings fields types (#3417) 2025-04-12 11:12:07 -04:00
Christian Byrne
d098d6ae4e [Types] Move enum to types file (#3416) 2025-04-12 11:11:41 -04:00
Christian Byrne
e4a5355f58 [Manager] Fix loading state on uninstall button (#3413) 2025-04-11 22:14:49 -04:00
Comfy Org PR Bot
42c004d41d 1.16.6 (#3410)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-11 20:33:25 -04:00
Benjamin Lu
009c389607 Rename reset keybindings to reset all keybindings (#3411)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
Co-authored-by: github-actions <github-actions@github.com>
2025-04-11 20:01:28 -04:00
Christian Byrne
b449dbd26b [Manager] Allowing changing sort field of registry search results (#3409)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-11 18:45:21 -04:00
Christian Byrne
67835edfca [Manager] Preview the individual nodes for packs on the registry (#3408)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-11 16:18:41 -04:00
filtered
60c0ce228a Generate a new workflow id when using "save as" (#3407) 2025-04-11 15:43:10 -04:00
Benjamin Lu
1990f25638 Allow keybind overwriting (#3393)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-11 14:28:36 -04:00
Comfy Org PR Bot
30c473db77 [chore] Update Comfy Registry API types from comfy-api@a28605f (#3405)
Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
2025-04-11 14:02:37 -04:00
Chenlei Hu
2371288fed [Bug] Fix widgets values migration (#3404) 2025-04-11 13:44:14 -04:00
Christian Byrne
2337fe6f8e [Manager] Fix hot reload after install of missing node pack (#3397)
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-04-11 12:55:02 -04:00
Benjamin Lu
25e6386b2a Do not trigger autosave on workflows that are not persisted (#3400)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-11 12:53:49 -04:00
Chenlei Hu
a03841cb1a [lint] Enable plugin vue recommended rules (#3403) 2025-04-11 12:53:20 -04:00
Chenlei Hu
dc5d7ea1be [lint] Enforce @typescript-eslint/no-floating-promises (#3402) 2025-04-11 12:19:22 -04:00
Christian Byrne
59e20964a0 [Manager] Add fallback to infer node pack when metadata is missing from workflow (#3396) 2025-04-11 09:50:30 -04:00
Comfy Org PR Bot
8f00d8ca6a 1.16.5 (#3394)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-10 21:29:17 -04:00
Christian Byrne
05e0036898 [Manager] Button to open manager from Missing Nodes dialog (#3395) 2025-04-10 21:28:42 -04:00
Benjamin Lu
9e7690405a keep user input on top of selection toolbox (#3389)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-10 20:50:19 -04:00
Christian Byrne
d687ea2cde [Manager] Fix infinite fetch attempts when response is empty (#3392) 2025-04-10 16:39:54 -07:00
Chenlei Hu
c801a0c854 Attach frontend version metadata on workflow export (#3386) 2025-04-10 14:19:54 -04:00
Chenlei Hu
615c183059 Disable reroute migration (2/2) (#3385) 2025-04-10 14:06:09 -04:00
Chenlei Hu
27c8389b9f [Cleanup] Remove ComfyApp.serializeGraph (#3383) 2025-04-10 11:50:27 -04:00
Chenlei Hu
261f671ef0 Disable native reroute migration (#3379)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-10 08:50:07 -04:00
Benjamin Lu
22ae30132c Add tag pi-language icon for Comfy.Locale setting (#3378)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-09 22:47:40 -04:00
Chenlei Hu
7d3bf372b0 [Bug] Apply link fixes regardless of fixed state (#3376) 2025-04-09 20:28:49 -04:00
Comfy Org PR Bot
cd35373c25 1.16.4 (#3372)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-09 19:41:01 -04:00
Chenlei Hu
a500a96c4a [TS] Fix widget GET_CONFIG on loading primitive nodes (#3374) 2025-04-09 17:48:28 -04:00
Chenlei Hu
dc9ea44f3a Prevent widget value serialization for media preview widgets (#3370) 2025-04-09 17:01:02 -04:00
Christian Byrne
2dc33b1eb9 [Manager] Remove outdated comment (#3371) 2025-04-09 16:51:16 -04:00
Comfy Org PR Bot
ed8f9a5a4f [chore] Update litegraph to 0.13.1 (#3369)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-09 16:45:31 -04:00
Chenlei Hu
6e72e1924e Update ComfyUI_devtools version in CI (#3368) 2025-04-09 14:59:07 -04:00
Christian Byrne
f7854a4e0b [Manager] Fix node pack icons not displaying in search results (#3366) 2025-04-09 13:51:47 -04:00
Chenlei Hu
05023b7889 Migrate defaultInput widget option (#3364)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-09 13:51:34 -04:00
Chenlei Hu
609496957b [Cleanup] Remove WidgetOptions.forceInput (#3362) 2025-04-09 11:36:35 -04:00
Chenlei Hu
a879f413bb [Cleanup] Remove WidgetOptions.inputIsOptional (#3361) 2025-04-09 10:45:51 -04:00
Comfy Org PR Bot
21d679a662 1.16.3 (#3357)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-08 23:05:29 -04:00
Chenlei Hu
34f9603961 [Feature Request]: Add resize keybinding (#3356) (#3358)
Co-authored-by: Emanuel F. <70411130+efrancisworks@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2025-04-08 23:05:21 -04:00
Christian Byrne
cf27a896f3 [Manager] Handle display of git hash versions for NIGHTLY node packs (#3359) 2025-04-08 23:00:36 -04:00
Chenlei Hu
e9a98161ca [Bug] Fix converted widget compression on export (#3354) 2025-04-08 20:20:19 -04:00
Christian Byrne
fa132e4106 Don't translate 'Stable Zero' (#3352) 2025-04-08 19:51:11 -04:00
Chenlei Hu
a489c19b07 Upstream rgthree's link fixer (#3350) 2025-04-08 18:32:43 -04:00
Comfy Org PR Bot
46af2f03f3 1.16.2 (#3345)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-08 11:08:53 -04:00
Chenlei Hu
3a1c95fb10 [Bug] Fix input link slots (#3349)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-08 11:08:42 -04:00
Comfy Org PR Bot
7a6f0e210e 1.16.1 (#3342)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-07 22:22:45 -04:00
Chenlei Hu
ac3bd7a848 [Test] Add test on dynamically added inputs (#3344)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-07 22:22:32 -04:00
Comfy Org PR Bot
77b5e487cf [chore] Update litegraph to 0.13.0 (#3343)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-07 20:04:18 -04:00
catboxanon
a7a8459e18 Add option to disable workflow persistence (#3341)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chenlei Hu <huchenlei@proton.me>
2025-04-07 17:06:41 -04:00
dependabot[bot]
65c9c264c6 Bump vite from 5.4.16 to 5.4.17 (#3338)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-06 21:37:16 -04:00
Comfy Org PR Bot
8ea070df12 1.16.0 (#3334)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-06 21:37:08 -04:00
Chenlei Hu
2c02d4ebb3 Migrate forceInput widgets_values (#3337)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-06 21:27:42 -04:00
Benjamin Lu
a2b3048b94 Clarify Playwright setup README and add note to .env_example (#3336)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-06 21:00:14 -04:00
Christian Byrne
549a42716f [Manager] Add tab for outdated node packs (has update available) (#3255)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-06 18:49:40 -04:00
Benjamin Lu
fa75614dc3 Add autosave feature (#3330)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-06 18:48:00 -04:00
Chenlei Hu
ac53296b2e Support associated socket for widgets (#3326)
Co-authored-by: github-actions <github-actions@github.com>
2025-04-06 11:50:21 -04:00
Comfy Org PR Bot
6eb2b76621 [chore] Update litegraph to 0.12.0 (#3335)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-06 11:31:42 -04:00
Christian Byrne
9dd3b9fff5 [3d] Add translations for material modes controls (#3325)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Terry Jia <terryjia88@gmail.com>
2025-04-05 22:29:46 -04:00
Chenlei Hu
785cad70ba [Cleanup] Remove extra.info from workflow schema (#3332) 2025-04-05 21:43:09 -04:00
Comfy Org PR Bot
026f076b8a 1.15.12 (#3331)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-05 21:22:08 -04:00
Christian Byrne
65f1561ec6 Add option to disable reconnecting toasts (#3327) 2025-04-05 18:50:25 -04:00
Benjamin Lu
bb094cf0ae Scroll to active offscreen tab when opened (#3320)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-05 16:06:45 -04:00
Christian Byrne
ec684ee6b8 [Manager] Fix primevue severity in status messages (#3324) 2025-04-05 16:04:30 -04:00
Comfy Org PR Bot
3978613f14 1.15.11 (#3322)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-05 17:56:18 +11:00
Comfy Org PR Bot
0a40e07f7e [chore] Update litegraph to 0.11.10 (#3321)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-04-05 17:42:24 +11:00
Comfy Org PR Bot
577af51ff8 1.15.10 (#3319)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-03 22:31:57 -04:00
Chenlei Hu
df7c7383e2 Only show reroute migration dialog when native reroute is not present (#3318) 2025-04-03 22:08:40 -04:00
Comfy Org PR Bot
1279f30f5a [chore] Update litegraph to 0.11.9 (#3316)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-03 14:49:35 -04:00
Benjamin Lu
9ab4b549c0 Enable double clicking keybind row to edit bind (#2924) (#3315)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-04-03 14:04:02 -04:00
Comfy Org PR Bot
10de4e5445 1.15.9 (#3314)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-02 19:35:18 -04:00
Chenlei Hu
30420f2c0a [TS] Add null checks to widgetInputs.ts (#3312) 2025-04-02 15:48:46 -04:00
Chenlei Hu
39c3a57c11 [Cleanup] Remove handling of legacy slot widget config (#3311) 2025-04-02 13:58:06 -04:00
Chenlei Hu
6d09b7165f [TS] Fix event type for executing listener (#3310) 2025-04-02 11:16:36 -04:00
Chenlei Hu
8fc6840434 [Bug] Fix progress bar display on last output node (#3309) 2025-04-02 11:07:25 -04:00
Chenlei Hu
db575425fe [nit] Show error message from response (#3308) 2025-04-02 10:39:10 -04:00
Laurent Erignoux
ccb71bf1a3 Ensures we clean missing local storage comfy UserId (#3289) 2025-04-01 22:42:00 -04:00
Chenlei Hu
733d71aaac [Refactor] Split node constructor logic (#3307) 2025-04-01 20:48:32 -04:00
Comfy Org PR Bot
e059b9b82f 1.15.8 (#3306)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-04-01 16:47:22 -04:00
Chenlei Hu
cfaf769a65 [TS] Properly type slot widget (#3305) 2025-04-01 15:13:46 -04:00
Chenlei Hu
b80e0e1a3c [Performance] Avoid layout thrashing (#3302) 2025-04-01 14:05:06 -04:00
Chenlei Hu
7b7d9905a7 Expose currently active color palette (#3304) 2025-04-01 14:04:57 -04:00
Chenlei Hu
594fc5945c Fix workflow persistence (#3303) 2025-04-01 13:52:04 -04:00
Chenlei Hu
e5abf765bd [Performance] Avoid per-frame workflow persistence (#3301) 2025-04-01 11:31:28 -04:00
dependabot[bot]
712c127bb5 Bump vite from 5.4.15 to 5.4.16 (#3295)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 00:11:55 -04:00
Chenlei Hu
854501ef27 Show object widget values as string on missing nodes (#3294)
Co-authored-by: github-actions <github-actions@github.com>
2025-03-31 20:55:50 -04:00
Comfy Org PR Bot
aea4493b4d 1.15.7 (#3293)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-03-31 20:07:19 -04:00
Chenlei Hu
df47226fd4 Add Reroute SplineOffset setting (#3292)
Co-authored-by: github-actions <github-actions@github.com>
2025-03-31 20:05:38 -04:00
Chenlei Hu
f26f5f25bb Add widget to node with missing definition (#3291)
Co-authored-by: github-actions <github-actions@github.com>
2025-03-31 14:23:44 -04:00
Comfy Org PR Bot
284902cabe 1.15.6 (#3287)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-03-30 21:48:18 -04:00
Chenlei Hu
58dec5ea42 Add reroute migration toast (#3286)
Co-authored-by: github-actions <github-actions@github.com>
2025-03-30 21:48:10 -04:00
Chenlei Hu
7e76665a22 Revert "Migrate legacy reroute to litegraph native reroute (#3151)" (#3285)
Co-authored-by: github-actions <github-actions@github.com>
2025-03-30 21:19:33 -04:00
Chenlei Hu
cb06d96930 [Refactor] Use NodeSlot.hasErrors API (#3284)
Co-authored-by: github-actions <github-actions@github.com>
2025-03-30 20:10:28 -04:00
Benjamin Lu
b01ddb6aff Make entire result image preview clickable (#3279)
Co-authored-by: Benjamin Lu <templu1107@proton.me>
2025-03-30 19:06:29 -04:00
Chenlei Hu
10bed33383 [Refactor] Use LGraphNode.progress API (#3281) 2025-03-30 18:13:31 -04:00
Comfy Org PR Bot
a57e60d60a [chore] Update litegraph to 0.11.7 (#3280)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-03-30 17:59:20 -04:00
Chenlei Hu
8c789bd05d [Refactor] Use litegraph LGraphNode.strokeStyles API (#3278) 2025-03-30 12:05:45 -04:00
Chenlei Hu
28def833f9 [TS] Fix node constructor signature (#3276) 2025-03-29 20:55:11 -04:00
Chenlei Hu
fcc22f06ac [Refactor/TS] Simplify node filter logic (#3275) 2025-03-29 13:00:18 -04:00
Chenlei Hu
3922a5882b [Refactor] Extract fuse search class as a separate file (#3274) 2025-03-29 12:04:29 -04:00
Comfy Org PR Bot
4a40e83b98 1.15.5 (#3268)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-03-28 21:20:27 -04:00
Chenlei Hu
21e0caa1b1 [Bug] Fix undo of colorization via selection toolbox (#3267) 2025-03-28 21:00:43 -04:00
Chenlei Hu
04af8cda4d Use new error dialog for queue prompt errors (#3266)
Co-authored-by: github-actions <github-actions@github.com>
2025-03-28 13:51:00 -04:00
Chenlei Hu
504b717575 [Refactor] Unify error dialog component (#3265)
Co-authored-by: github-actions <github-actions@github.com>
2025-03-28 11:53:29 -04:00
Chenlei Hu
62fdcd4949 [Refactor] Extract error report generation logic (#3263) 2025-03-28 10:50:27 -04:00
Yiximail
cb7adaef9b maskeditor pen input support for windows (#3201) 2025-03-28 13:58:53 +01:00
Comfy Org PR Bot
6aad5222ab 1.15.4 (#3261)
Co-authored-by: huchenlei <20929282+huchenlei@users.noreply.github.com>
2025-03-27 22:23:15 -04:00
Chenlei Hu
690326c374 [Reroute] Migrate floating link (#3260) 2025-03-27 22:13:16 -04:00
Comfy Org PR Bot
25ce267b2e [chore] Update litegraph to 0.11.5 (#3258)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-03-28 09:09:32 +11:00
Comfy Org PR Bot
78e3a20773 [chore] Update litegraph to 0.11.4 (#3257)
Co-authored-by: webfiltered <176114999+webfiltered@users.noreply.github.com>
2025-03-27 14:24:19 -04:00
Chenlei Hu
56dbcbbd22 [Bug] Fix convert dom widget placeholder render (#3256) 2025-03-27 14:09:30 -04:00
Christian Byrne
4bfc8e9e33 [Manager] Fetch lists of node packs in single request (#3250) 2025-03-27 11:49:05 -04:00
Chenlei Hu
6e72207927 [Bug] Fix this binding in useChainCallback (#3252) 2025-03-27 11:38:52 -04:00
Christian Byrne
71968ae133 Translate action history items (#3249)
Co-authored-by: github-actions <github-actions@github.com>
2025-03-27 11:13:24 -04:00
679 changed files with 54325 additions and 5854 deletions

View File

@@ -8,6 +8,15 @@ const vue3CompositionApiBestPractices = [
"Use watch and watchEffect for side effects",
"Implement lifecycle hooks with onMounted, onUpdated, etc.",
"Utilize provide/inject for dependency injection",
"Use vue 3.5 style of default prop declaration. Example:
const { nodes, showTotal = true } = defineProps<{
nodes: ApiNodeCost[]
showTotal?: boolean
}>()
",
"Organize vue component in <template> <script> <style> order",
]
// Folder structure
@@ -40,4 +49,6 @@ const additionalInstructions = `
7. Implement proper error handling
8. Follow Vue 3 style guide and naming conventions
9. Use Vite for fast development and building
10. Use vue-i18n in composition API for any string literals. Place new translation
entries in src/locales/en/main.json.
`;

View File

@@ -1,4 +1,5 @@
# Local development playwright target
# Note: Don't add a trailing / after the port
PLAYWRIGHT_TEST_URL=http://localhost:5173
# PLAYWRIGHT_TEST_URL=http://localhost:8188
@@ -17,3 +18,14 @@ TEST_COMFYUI_DIR=/home/ComfyUI
# Whether to enable minification of the frontend code.
ENABLE_MINIFY=true
# Whether to disable proxying the `/templates` route. If true, allows you to
# serve templates from the ComfyUI_frontend/public/templates folder (for
# locally testing changes to templates). When false or nonexistent, the
# templates are served via the normal method from the server's python site
# packages.
DISABLE_TEMPLATES_PROXY=false
# If playwright tests are being run via vite dev server, Vue plugins will
# invalidate screenshots. When `true`, vite plugins will not be loaded.
DISABLE_VUE_PLUGINS=false

37
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,37 @@
Use the Vue 3 Composition API instead of the Options API when writing Vue components. An exception is when overriding or extending a PrimeVue component for compatibility, you may use the Options API.
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
Use vue 3.5 style of default prop declaration.
Use Tailwind CSS for styling
Leverage VueUse functions for performance-enhancing styles
Use lodash for utility functions
Use TypeScript for type safety
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Implement proper error handling
Follow Vue 3 style guide and naming conventions
Use Vite for fast development and building
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json.

72
.github/workflows/dev-release.yaml vendored Normal file
View File

@@ -0,0 +1,72 @@
name: Create Dev PyPI Package
on:
workflow_dispatch:
inputs:
devVersion:
description: 'Dev version'
required: true
type: number
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.current_version.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- name: Get current version
id: current_version
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
- name: Build project
env:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_API_KEY: ${{ secrets.ALGOLIA_API_KEY }}
USE_PROD_CONFIG: 'true'
run: |
npm ci
npm run build
npm run zipdist
- name: Upload dist artifact
uses: actions/upload-artifact@v4
with:
name: dist-files
path: |
dist/
dist.zip
publish_pypi:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download dist artifact
uses: actions/download-artifact@v4
with:
name: dist-files
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install build dependencies
run: python -m pip install build
- name: Setup pypi package
run: |
mkdir -p comfyui_frontend_package/comfyui_frontend_package/static/
cp -r dist/* comfyui_frontend_package/comfyui_frontend_package/static/
- name: Build pypi package
run: python -m build
working-directory: comfyui_frontend_package
env:
COMFYUI_FRONTEND_VERSION: ${{ format('{0}.dev{1}', needs.build.outputs.version, inputs.devVersion) }}
- name: Publish pypi package
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_TOKEN }}
packages-dir: comfyui_frontend_package/dist

View File

@@ -29,9 +29,9 @@ jobs:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_API_KEY: ${{ secrets.ALGOLIA_API_KEY }}
USE_PROD_CONFIG: 'true'
run: |
npm ci
npm run fetch-templates
npm run build
npm run zipdist
- name: Upload dist artifact

View File

@@ -30,7 +30,7 @@ jobs:
with:
repository: 'Comfy-Org/ComfyUI_devtools'
path: 'ComfyUI/custom_nodes/ComfyUI_devtools'
ref: '080e6d4af809a46852d1c4b7ed85f06e8a3a72be'
ref: 'd05fd48dd787a4192e16802d4244cfcc0e2f9684'
- uses: actions/setup-node@v4
with:
@@ -39,7 +39,6 @@ jobs:
- name: Build ComfyUI_frontend
run: |
npm ci
npm run fetch-templates
npm run build
working-directory: ComfyUI_frontend

View File

@@ -32,7 +32,7 @@ jobs:
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.PR_GH_TOKEN }}
commit-message: '[chore] Update electron-types to ${{ steps.get-version.outputs.NEW_VERSION }}'
title: '[chore] Update electron-types to ${{ steps.get-version.outputs.NEW_VERSION }}'
body: |

3
.gitignore vendored
View File

@@ -55,3 +55,6 @@ dist.zip
# Temporary repository directory
templates_repo/
# Vites timestamped config modules
vite.config.mts.timestamp-*.mjs

View File

@@ -4,13 +4,13 @@
const { defineConfig } = require('@lobehub/i18n-cli');
module.exports = defineConfig({
modelName: 'gpt-4',
modelName: 'gpt-4.1',
splitToken: 1024,
entry: 'src/locales/en',
entryLocale: 'en',
output: 'src/locales',
outputLocales: ['zh', 'ru', 'ja', 'ko', 'fr', 'es'],
reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade, controlnet, lora.
reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade, stable zero, controlnet, lora, HiDream.
'latent' is the short form of 'latent space'.
'mask' is in the context of image processing.
`

25
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,25 @@
{
"recommendations": [
"austenc.tailwind-docs",
"bradlc.vscode-tailwindcss",
"davidanson.vscode-markdownlint",
"dbaeumer.vscode-eslint",
"eamodio.gitlens",
"esbenp.prettier-vscode",
"figma.figma-vscode-extension",
"github.vscode-github-actions",
"github.vscode-pull-request-github",
"hbenl.vscode-test-explorer",
"lokalise.i18n-ally",
"ms-playwright.playwright",
"vitest.explorer",
"vue.volar",
"sonarsource.sonarlint-vscode",
"deque-systems.vscode-axe-linter",
"kisstkondoros.vscode-codemetrics",
"donjayamanne.githistory",
"wix.vscode-import-cost",
"prograhammer.tslint-vue",
"antfu.vite"
]
}

38
CLAUDE.md Normal file
View File

@@ -0,0 +1,38 @@
- use npm run to see what commands are available
- After making code changes, follow this general process: (1) Create unit tests, component tests, browser tests (if appropriate for each), (2) run unit tests, component tests, and browser tests until passing, (3) run typecheck, lint, format (with prettier) -- you can use `npm run` command to see the scripts available, (4) check if any READMEs (including nested) or documentation needs to be updated, (5) Decide whether the changes are worth adding new content to the external documentation for (or would requires changes to the external documentation) at https://docs.comfy.org, then present your suggestion
- When referencing PrimeVue, you can get all the docs here: https://primevue.org. Do this instead of making up or inferring names of Components
- When trying to set tailwind classes for dark theme, use "dark-theme:" prefix rather than "dark:"
- Never add lines to PR descriptions that say "Generated with Claude Code"
- When making PR names and commit messages, if you are going to add a prefix like "docs:", "feat:", "bugfix:", use square brackets around the prefix term and do not use a colon (e.g., should be "[docs]" rather than "docs:").
- When I reference GitHub Repos related to Comfy-Org, you should proactively fetch or read the associated information in the repo. To do so, you should exhaust all options: (1) Check if we have a local copy of the repo, (2) Use the GitHub API to fetch the information; you may want to do this IN ADDITION to the other options, especially for reading speicifc branches/PRs/comments/reviews/metadata, and (3) curl the GitHub website and parse the html or json responses
- For information about ComfyUI, ComfyUI_frontend, or ComfyUI-Manager, you can web search or download these wikis: https://deepwiki.com/Comfy-Org/ComfyUI-Manager, https://deepwiki.com/Comfy-Org/ComfyUI_frontend/1-overview, https://deepwiki.com/comfyanonymous/ComfyUI/2-core-architecture
- If a question/project is related to Comfy-Org, Comfy, or ComfyUI ecosystem, you should proactively use the Comfy docs to answer the question. The docs may be referenced with URLs like https://docs.comfy.org
- When operating inside a repo, check for README files at key locations in the repo detailing info about the contents of that folder. E.g., top-level key folders like tests-ui, browser_tests, composables, extensions/core, stores, services often have their own README.md files. When writing code, make sure to frequently reference these README files to understand the overall architecture and design of the project. Pay close attention to the snippets to learn particular patterns that seem to be there for a reason, as you should emulate those.
- Prefer running single tests, and not the whole test suite, for performance
- If using a lesser known or complex CLI tool, run the --help to see the documentation before deciding what to run, even if just for double-checking or verifying things.
- IMPORTANT: the most important goal when writing code is to create clean, best-practices, sustainable, and scalable public APIs and interfaces. Our app is used by thousands of users and we have thousands of mods/extensions that are constantly changing and updating; and we are also always updating. That's why it is IMPORTANT that we design systems and write code that follows practices of domain-driven design, object-oriented design, and design patterns (such that you can assure stability while allowing for all components around you to change and evolve). We ABSOLUTELY prioritize clean APIs and public interfaces that clearly define and restrict how/what the mods/extensions can access.
- If any of these technologies are referenced, you can proactively read their docs at these locations: https://primevue.org/theming, https://primevue.org/forms/, https://www.electronjs.org/docs/latest/api/browser-window, https://vitest.dev/guide/browser/, https://atlassian.design/components/pragmatic-drag-and-drop/core-package/drop-targets/, https://playwright.dev/docs/api/class-test, https://playwright.dev/docs/api/class-electron, https://www.algolia.com/doc/api-reference/rest-api/, https://pyav.org/docs/develop/cookbook/basics.html
- IMPORTANT: Never add Co-Authored by Claude or any refrence to Claude or Claude Code in commit messages, PR descriptions, titles, or any documentation whatsoever
- The npm script to type check is called "typecheck" NOT "type check"
- Use the Vue 3 Composition API instead of the Options API when writing Vue components. An exception is when overriding or extending a PrimeVue component for compatibility, you may use the Options API.
- when we are solving an issue we know the link/number for, we should add "Fixes #n" (where n is the issue number) to the PR description.
- Never write css if you can accomplish the same thing with tailwind utility classes
- 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
- Use vue 3.5 style of default prop declaration. Do not define a `props` variable; instead, destructure props. Since vue 3.5, destructuring props does not strip them of reactivity.
- Use Tailwind CSS for styling
- Leverage VueUse functions for performance-enhancing styles
- Use lodash for utility functions
- Use TypeScript for type safety
- Implement proper props and emits definitions
- Utilize Vue 3's Teleport component when needed
- Use Suspense for async components
- Implement proper error handling
- Follow Vue 3 style guide and naming conventions
- Use Vite for fast development and building
- Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json.

166
README.md
View File

@@ -510,16 +510,62 @@ The selection toolbox will display the command button when items are selected:
</details>
## Contributing
We're building this frontend together and would love your help — no matter how you'd like to pitch in! You don't need to write code to make a difference.
Here are some ways to get involved:
- **Pull Requests:** Add features, fix bugs, or improve code health. Browse [issues](https://github.com/Comfy-Org/ComfyUI_frontend/issues) for inspiration.
- **Vote on Features:** Give a 👍 to the feature requests you care about to help us prioritize.
- **Verify Bugs:** Try reproducing reported issues and share your results (even if the bug doesn't occur!).
- **Community Support:** Hop into our [Discord](https://www.comfy.org/discord) to answer questions or get help.
- **Share & Advocate:** Tell your friends, tweet about us, or share tips to support the project.
Have another idea? Drop into Discord or open an issue, and let's chat!
## Development
### Tech Stack
### Prerequisites & Technology Stack
- [Vue 3](https://vuejs.org/) with [TypeScript](https://www.typescriptlang.org/)
- [Pinia](https://pinia.vuejs.org/) for state management
- [PrimeVue](https://primevue.org/) with [TailwindCSS](https://tailwindcss.com/) for UI
- [litegraph.js](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
- **Required Software**:
- Node.js (v16 or later) and npm
- Git for version control
- A running ComfyUI backend instance
- **Tech Stack**:
- [Vue 3](https://vuejs.org/) with [TypeScript](https://www.typescriptlang.org/)
- [Pinia](https://pinia.vuejs.org/) for state management
- [PrimeVue](https://primevue.org/) with [TailwindCSS](https://tailwindcss.com/) for UI
- [litegraph.js](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
### Initial Setup
1. Clone the repository:
```bash
git clone https://github.com/Comfy-Org/ComfyUI_frontend.git
cd ComfyUI_frontend
```
2. Install dependencies:
```bash
npm install
```
3. Configure environment (optional):
Create a `.env` file in the project root based on the provided [.env.example](.env.example) file.
**Note about ports**: By default, the dev server expects the ComfyUI backend at `localhost:8188`. If your ComfyUI instance runs on a different port, update this in your `.env` file.
### Dev Server Configuration
To launch ComfyUI and have it connect to your development server:
```bash
python main.py --port 8188
```
### Git pre-commit hooks
@@ -557,6 +603,12 @@ After you start the dev server, you should see following logs:
Make sure your desktop machine and touch device are on the same network. On your touch device,
navigate to `http://<server_ip>:5173` (e.g. `http://192.168.2.20:5173` here), to access the ComfyUI frontend.
### Recommended Code Editor Configuration
This project includes `.vscode/launch.json.default` and `.vscode/settings.json.default` files with recommended launch and workspace settings for editors that use the `.vscode` directory (e.g., VS Code, Cursor, etc.).
We've also included a list of recommended extensions in `.vscode/extensions.json`. Your editor should detect this file and show a human friendly list in the Extensions panel, linking each entry to its marketplace page.
### Unit Test
- `npm i` to install all dependencies
@@ -586,3 +638,103 @@ This will replace the litegraph package in this repo with the local litegraph re
### i18n
See [locales/README.md](src/locales/README.md) for details.
## Troubleshooting
> **Note**: For comprehensive troubleshooting and how-to guides, please refer to our [official documentation](https://docs.comfy.org/). This section covers only the most common issues related to frontend development.
> **Desktop Users**: For issues specific to the desktop application, please refer to the [ComfyUI desktop repository](https://github.com/Comfy-Org/desktop).
### Debugging Custom Node (Extension) Issues
If you're experiencing crashes, errors, or unexpected behavior with ComfyUI, it's often caused by custom nodes (extensions). Follow these steps to identify and resolve the issues:
#### Step 1: Verify if custom nodes are causing the problem
Run ComfyUI with the `--disable-all-custom-nodes` flag:
```bash
python main.py --disable-all-custom-nodes
```
If the issue disappears, a custom node is the culprit. Proceed to the next step.
#### Step 2: Identify the problematic custom node using binary search
Rather than disabling nodes one by one, use this more efficient approach:
1. Temporarily move half of your custom nodes out of the `custom_nodes` directory
```bash
# Create a temporary directory
# Linux/Mac
mkdir ~/custom_nodes_disabled
# Windows
mkdir %USERPROFILE%\custom_nodes_disabled
# Move half of your custom nodes (assuming you have node1 through node8)
# Linux/Mac
mv custom_nodes/node1 custom_nodes/node2 custom_nodes/node3 custom_nodes/node4 ~/custom_nodes_disabled/
# Windows
move custom_nodes\node1 custom_nodes\node2 custom_nodes\node3 custom_nodes\node4 %USERPROFILE%\custom_nodes_disabled\
```
2. Run ComfyUI again
- If the issue persists: The problem is in nodes 5-8 (the remaining half)
- If the issue disappears: The problem is in nodes 1-4 (the moved half)
3. Let's assume the issue disappeared, so the problem is in nodes 1-4. Move half of these for the next test:
```bash
# Move nodes 3-4 back to custom_nodes
# Linux/Mac
mv ~/custom_nodes_disabled/node3 ~/custom_nodes_disabled/node4 custom_nodes/
# Windows
move %USERPROFILE%\custom_nodes_disabled\node3 %USERPROFILE%\custom_nodes_disabled\node4 custom_nodes\
```
4. Run ComfyUI again
- If the issue reappears: The problem is in nodes 3-4
- If issue still gone: The problem is in nodes 1-2
5. Let's assume the issue reappeared, so the problem is in nodes 3-4. Test each one:
```bash
# Move node 3 back to disabled
# Linux/Mac
mv custom_nodes/node3 ~/custom_nodes_disabled/
# Windows
move custom_nodes\node3 %USERPROFILE%\custom_nodes_disabled\
```
6. Run ComfyUI again
- If the issue disappears: node3 is the problem
- If issue persists: node4 is the problem
7. Repeat until you identify the specific problematic node
#### Step 3: Update or replace the problematic node
Once identified:
1. Check for updates to the problematic custom node
2. Consider alternatives with similar functionality
3. Report the issue to the custom node developer with specific details
### Common Issues and Solutions
- **"Module not found" errors**: Usually indicates missing Python dependencies. Check the custom node's `requirements.txt` file for required packages and install them:
```bash
pip install -r custom_nodes/problematic_node/requirements.txt
```
- **Frontend or Templates Package Not Updated**: After updating ComfyUI via Git, ensure you update the frontend dependencies:
```bash
pip install -r requirements.txt
```
- **Can't Find Custom Node**: Make sure to disable node validation in ComfyUI settings.
- **Error Toast About Workflow Failing Validation**: Report the issue to the ComfyUI team. As a temporary workaround, disable workflow validation in settings.
- **Login Issues When Not on Localhost**: Normal login is only available when accessing from localhost. If you're running ComfyUI via LAN, another domain, or headless, you can use our API key feature to authenticate. The API key lets you log in normally through the UI. Generate an API key at [platform.comfy.org/login](https://platform.comfy.org/login) and use it in the API Key field in the login dialog or with the `--api-key` command line argument. Refer to our [API Key Integration Guide](https://docs.comfy.org/essentials/comfyui-server/api-key-integration#integration-of-api-key-to-use-comfyui-api-nodes) for complete setup instructions.

View File

@@ -1,6 +1,6 @@
# Playwright Testing for ComfyUI_frontend
This document outlines the setup and usage of Playwright for testing the ComfyUI_frontend project.
This document outlines the setup, usage, and common patterns for Playwright browser tests in the ComfyUI_frontend project.
## WARNING
@@ -9,18 +9,29 @@ If `TEST_COMFYUI_DIR` in `.env` isn't set to your `(Comfy Path)/ComfyUI` directo
## Setup
Clone <https://github.com/Comfy-Org/ComfyUI_devtools> to your `custom_nodes` directory.
ComfyUI_devtools adds additional API endpoints and nodes to ComfyUI for browser testing.
### ComfyUI devtools
Clone <https://github.com/Comfy-Org/ComfyUI_devtools> to your `custom_nodes` directory.
_ComfyUI_devtools adds additional API endpoints and nodes to ComfyUI for browser testing._
### Node.js & Playwright Prerequisites
Ensure you have Node.js v20 or later installed. Then, set up the Chromium test driver:
```bash
npx playwright install chromium --with-deps
```
### Environment Variables
Ensure the environment variables in `.env` are set correctly according to your setup.
The `.env` file will not exist until you create it yourself.
A template with helpful information can be found in `.env_example`.
### Multiple Tests
If you are running Playwright tests in parallel or running the same test multiple times, the flag `--multi-user` must be added to the main ComfyUI process.
## Running Tests
There are two ways to run the tests:
There are multiple ways to run the tests:
1. **Headless mode with report generation:**
```bash
@@ -34,18 +45,241 @@ 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)
3. **Running specific tests:**
```bash
npx playwright test widget.spec.ts
```
## Test Structure
Browser tests in this project follow a specific organization pattern:
- **Fixtures**: Located in `fixtures/` - These provide test setup and utilities
- `ComfyPage.ts` - The main fixture for interacting with ComfyUI
- `ComfyMouse.ts` - Utility for mouse interactions with the canvas
- Components fixtures in `fixtures/components/` - Page object models for UI components
- **Tests**: Located in `tests/` - The actual test specifications
- Organized by functionality (e.g., `widget.spec.ts`, `interaction.spec.ts`)
- Snapshot directories (e.g., `widget.spec.ts-snapshots/`) contain reference screenshots
- **Utilities**: Located in `utils/` - Common utility functions
- `litegraphUtils.ts` - Utilities for working with LiteGraph nodes
## Writing Effective Tests
When writing new tests, follow these patterns:
### Test Structure
```typescript
// Import the test fixture
import { comfyPageFixture as test } from '../fixtures/ComfyPage';
test.describe('Feature Name', () => {
// Set up test environment if needed
test.beforeEach(async ({ comfyPage }) => {
// Common setup
});
test('should do something specific', async ({ comfyPage }) => {
// Test implementation
});
});
```
### Leverage Existing Fixtures and Helpers
Always check for existing helpers and fixtures before implementing new ones:
- **ComfyPage**: Main fixture with methods for canvas interaction and node management
- **ComfyMouse**: Helper for precise mouse operations on the canvas
- **Helpers**: Check `browser_tests/helpers/` for specialized helpers like:
- `actionbar.ts`: Interact with the action bar
- `manageGroupNode.ts`: Group node management operations
- `templates.ts`: Template workflows operations
- **Component Fixtures**: Check `browser_tests/fixtures/components/` for UI component helpers
- **Utility Functions**: Check `browser_tests/utils/` and `browser_tests/fixtures/utils/` for shared utilities
Most common testing needs are already addressed by these helpers, which will make your tests more consistent and reliable.
### Key Testing Patterns
1. **Focus elements explicitly**:
Canvas-based elements often need explicit focus before interaction:
```typescript
// Click the canvas first to focus it before pressing keys
await comfyPage.canvas.click();
await comfyPage.page.keyboard.press('a');
```
2. **Mark canvas as dirty if needed**:
Some interactions need explicit canvas updates:
```typescript
// After programmatically changing node state, mark canvas dirty
await comfyPage.page.evaluate(() => {
window['app'].graph.setDirtyCanvas(true, true);
});
```
3. **Use node references over coordinates**:
Node references from `fixtures/utils/litegraphUtils.ts` provide stable ways to interact with nodes:
```typescript
// Prefer this:
const node = await comfyPage.getNodeRefsByType('LoadImage')[0];
await node.click('title');
// Over this:
await comfyPage.canvas.click({ position: { x: 100, y: 100 } });
```
4. **Wait for canvas to render after UI interactions**:
```typescript
await comfyPage.nextFrame();
```
5. **Clean up persistent server state**:
While most state is reset between tests, anything stored on the server persists:
```typescript
// Reset settings that affect other tests (these are stored on server)
await comfyPage.setSetting('Comfy.ColorPalette', 'dark');
await comfyPage.setSetting('Comfy.NodeBadge.NodeIdBadgeMode', 'None');
// Clean up uploaded files if needed
await comfyPage.request.delete(`${comfyPage.url}/api/delete/image.png`);
```
6. **Prefer functional assertions over screenshots**:
Use screenshots only when visual verification is necessary:
```typescript
// Prefer this:
expect(await node.isPinned()).toBe(true);
expect(await node.getProperty('title')).toBe('Expected Title');
// Over this - only use when needed:
await expect(comfyPage.canvas).toHaveScreenshot('state.png');
```
7. **Use minimal test workflows**:
When creating test workflows, keep them as minimal as possible:
```typescript
// Include only the components needed for the test
await comfyPage.loadWorkflow('single_ksampler');
```
## Common Patterns and Utilities
### Page Object Pattern
Tests use the Page Object pattern to create abstractions over the UI:
```typescript
// Using the ComfyPage fixture
test('Can toggle boolean widget', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('widgets/boolean_widget')
const node = (await comfyPage.getFirstNodeRef())!
const widget = await node.getWidget(0)
await widget.click()
});
```
### Node References
The `NodeReference` class provides helpers for interacting with LiteGraph nodes:
```typescript
// Getting node by type and interacting with it
const nodes = await comfyPage.getNodeRefsByType('LoadImage')
const loadImageNode = nodes[0]
const widget = await loadImageNode.getWidget(0)
await widget.click()
```
### Visual Regression Testing
Tests use screenshot comparisons to verify UI state:
```typescript
// Take a screenshot and compare to reference
await expect(comfyPage.canvas).toHaveScreenshot('boolean_widget_toggled.png')
```
### Waiting for Animations
Always call `nextFrame()` after actions that trigger animations:
```typescript
await comfyPage.canvas.click({ position: { x: 100, y: 100 } })
await comfyPage.nextFrame() // Wait for canvas to redraw
```
### Mouse Interactions
Canvas operations use special helpers to ensure proper timing:
```typescript
// Using ComfyMouse for drag and drop
await comfyMouse.dragAndDrop(
{ x: 100, y: 100 }, // From
{ x: 200, y: 200 } // To
)
// Standard ComfyPage helpers
await comfyPage.drag({ x: 100, y: 100 }, { x: 200, y: 200 })
await comfyPage.pan({ x: 200, y: 200 })
await comfyPage.zoom(-100) // Zoom in
```
### Workflow Management
Tests use workflows stored in `assets/` for consistent starting points:
```typescript
// Load a test workflow
await comfyPage.loadWorkflow('single_ksampler')
// Wait for workflow to load and stabilize
await comfyPage.nextFrame()
```
### Custom Assertions
The project includes custom Playwright assertions through `comfyExpect`:
```typescript
// Check if a node is in a specific state
await expect(node).toBePinned()
await expect(node).toBeBypassed()
await expect(node).toBeCollapsed()
```
## Troubleshooting Common Issues
### Flaky Tests
- **Timing Issues**: Always wait for animations to complete with `nextFrame()`
- **Coordinate Sensitivity**: Canvas coordinates are viewport-relative; use node references when possible
- **Test Isolation**: Tests run in parallel; avoid dependencies between tests
- **Screenshots vary**: Ensure your OS and browser match the reference environment (Linux)
- **Async / await**: Race conditions are a very common cause of test flakiness
## Screenshot Expectations
Due to variations in system font rendering, screenshot expectations are platform-specific. Please note:
- We maintain Linux screenshot expectations as our GitHub Action runner operates in a Linux environment.
- To set new test expectations:
1. Create a pull request from a `Comfy-Org/ComfyUI_frontend` branch.
2. Add the `New Browser Test Expectation` tag to your pull request.
3. This will trigger a GitHub action to update the screenshot expectations automatically.
- **DO NOT commit local screenshot expectations** to the repository
- We maintain Linux screenshot expectations as our GitHub Action runner operates in a Linux environment
- While developing, you can generate local screenshots for your tests, but these will differ from CI-generated ones
> **Note:** If you're making a pull request from a forked repository, the GitHub action won't be able to commit updated screenshot expectations directly to your PR branch.
To set new test expectations for PR:
1. Write your test with screenshot assertions using `toHaveScreenshot(filename)`
2. Create a pull request from a `Comfy-Org/ComfyUI_frontend` branch
3. Add the `New Browser Test Expectation` tag to your pull request
4. The GitHub CI will automatically generate and commit the reference screenshots
This approach ensures consistent screenshot expectations across all PRs and avoids issues with platform-specific rendering.
> **Note:** If you're making a pull request from a forked repository, the GitHub action won't be able to commit updated screenshot expectations directly to your PR branch.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,126 @@
{
"id": "51b9b184-770d-40ac-a478-8cc31667ff23",
"revision": 0,
"last_node_id": 5,
"last_link_id": 3,
"nodes": [
{
"id": 4,
"type": "KSampler",
"pos": [
867.4669799804688,
347.22369384765625
],
"size": [
315,
262
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": null
},
{
"name": "positive",
"type": "CONDITIONING",
"link": null
},
{
"name": "negative",
"type": "CONDITIONING",
"link": null
},
{
"name": "latent_image",
"type": "LATENT",
"link": null
},
{
"name": "steps",
"type": "INT",
"widget": {
"name": "steps"
},
"link": 3
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": null
}
],
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
20,
8,
"euler",
"normal",
1
]
},
{
"id": 5,
"type": "PrimitiveInt",
"pos": [
443.0852355957031,
441.131591796875
],
"size": [
315,
82
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "INT",
"type": "INT",
"links": [
3
]
}
],
"properties": {
"Node name for S&R": "PrimitiveInt"
},
"widgets_values": [
0,
"randomize"
]
}
],
"links": [
[
3,
5,
0,
4,
5,
"INT"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1.9487171000000016,
"offset": [
-325.57196748514497,
-168.13150517966463
]
}
},
"version": 0.4
}

View File

@@ -33,5 +33,11 @@
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}

View File

@@ -130,6 +130,11 @@
],
"groups": [],
"config": {},
"extra": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}

View File

@@ -0,0 +1,53 @@
{
"id": "9bcb9451-8319-492a-88d4-fb711d8c3d25",
"revision": 0,
"last_node_id": 6,
"last_link_id": 0,
"nodes": [
{
"id": 6,
"type": "DevToolsNodeWithDefaultInput",
"pos": [
8.39722728729248,
29.727279663085938
],
"size": [
315,
82
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"name": "float_input",
"shape": 7,
"type": "FLOAT",
"link": null
}
],
"outputs": [],
"properties": {
"Node name for S&R": "DevToolsNodeWithDefaultInput"
},
"widgets_values": [
0,
1,
0
]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
}
},
"version": 0.4
}

View File

@@ -0,0 +1,82 @@
{
"last_node_id": 9,
"last_link_id": 13,
"nodes": [
{
"id": 3,
"type": "KSampler",
"pos": [
0,
30
],
"size": {
"0": 315,
"1": 262
},
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": null
},
{
"name": "positive",
"type": "CONDITIONING",
"link": null
},
{
"name": "negative",
"type": "CONDITIONING",
"link": null
},
{
"name": "latent_image",
"type": "LATENT",
"link": null
} ,
{
"name": "dynamic_input",
"type": "FLOAT",
"link": null,
"_meta": "Dynamically added input via frontend JS logic"
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
156680208700286,
"randomize",
20,
8,
"euler",
"normal",
1
]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
0,
0
]
}
},
"version": 0.4
}

View File

@@ -499,6 +499,11 @@
],
"groups": [],
"config": {},
"extra": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}
}

View File

@@ -0,0 +1,85 @@
{
"id": "1a95532f-c8aa-4c9d-a7f6-f928ba2d4862",
"revision": 0,
"last_node_id": 4,
"last_link_id": 3,
"nodes": [
{
"id": 4,
"type": "PreviewAny",
"pos": [946.2566528320312, 598.4373168945312],
"size": [140, 76],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "source",
"type": "*",
"link": 3
}
],
"outputs": [],
"properties": {
"Node name for S&R": "PreviewAny"
},
"widgets_values": []
},
{
"id": 1,
"type": "PreviewAny",
"pos": [951.0236206054688, 421.3861083984375],
"size": [140, 76],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "source",
"type": "*",
"link": 2
}
],
"outputs": [],
"properties": {
"Node name for S&R": "PreviewAny"
},
"widgets_values": []
},
{
"id": 3,
"type": "PrimitiveString",
"pos": [575.1760864257812, 504.5214538574219],
"size": [270, 58],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": [2, 3]
}
],
"properties": {
"Node name for S&R": "PrimitiveString"
},
"widgets_values": ["foo"]
}
],
"links": [
[2, 3, 0, 1, 0, "*"],
[3, 3, 0, 4, 0, "*"]
],
"groups": [],
"config": {},
"extra": {
"frontendVersion": "1.19.1",
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}

View File

@@ -160,4 +160,4 @@
}
},
"version": 0.4
}
}

View File

@@ -43,6 +43,10 @@
"groups": [],
"config": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
},
"groupNodes": {
"group_node": {
"nodes": [
@@ -401,4 +405,4 @@
}
},
"version": 0.4
}
}

View File

@@ -0,0 +1,74 @@
{
"id": "51b9b184-770d-40ac-a478-8cc31667ff23",
"revision": 0,
"last_node_id": 2,
"last_link_id": 1,
"nodes": [
{
"id": 1,
"type": "CLIPTextEncode",
"pos": [904, 466],
"size": [400, 200],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "text",
"type": "STRING",
"widget": {
"name": "text"
},
"link": 1
},
{
"name": "clip",
"type": "CLIP",
"link": null
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": null
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [""]
},
{
"id": 2,
"type": "PrimitiveString",
"pos": [556.8589477539062, 472.94342041015625],
"size": [315, 58],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": [1]
}
],
"properties": {
"Node name for S&R": "PrimitiveString"
},
"widgets_values": ["foo"]
}
],
"links": [[1, 2, 0, 1, 0, "STRING"]],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1.7715610000000013,
"offset": [-388.521484375, -162.31336975097656]
}
},
"version": 0.4
}

View File

@@ -110,6 +110,10 @@
"groups": [],
"config": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
},
"groupNodes": {
"hello": {
"nodes": [
@@ -249,4 +253,4 @@
}
},
"version": 0.4
}
}

View File

@@ -44,6 +44,11 @@
"links": [],
"groups": [],
"config": {},
"extra": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}

View File

@@ -51,13 +51,21 @@
0.85,
false,
false,
""
"",
{
"foo": "bar"
}
]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}
}

View File

@@ -0,0 +1,36 @@
{
"id": "5635564e-189f-49e4-9b25-6b7634bcd595",
"revision": 0,
"last_node_id": 78,
"last_link_id": 53,
"nodes": [
{
"id": 78,
"type": "DevToolsNodeWithV2ComboInput",
"pos": [1320, 904],
"size": [270.3199157714844, 58],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "COMBO",
"type": "COMBO",
"links": null
}
],
"properties": {
"Node name for S&R": "DevToolsNodeWithV2ComboInput"
},
"widgets_values": ["A"]
}
],
"links": [],
"groups": [],
"config": {},
"extra": {
"frontendVersion": "1.19.7"
},
"version": 0.4
}

View File

@@ -50,6 +50,11 @@
"links": [],
"groups": [],
"config": {},
"extra": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}
}

View File

@@ -38,7 +38,11 @@
"groups": [],
"config": {},
"extra": {
"groupNodes": {}
"groupNodes": {},
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -54,6 +54,11 @@
"links": [],
"groups": [],
"config": {},
"extra": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}

View File

@@ -92,10 +92,14 @@
"groups": [],
"config": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
},
"VHS_latentpreview": true,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": false,
"VHS_KeepIntermediate": false
},
"version": 0.4
}
}

View File

@@ -84,6 +84,10 @@
"groups": [],
"config": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
},
"reroutes": [
{
"id": 1,

View File

@@ -106,10 +106,7 @@
"extra": {
"ds": {
"scale": 1,
"offset": {
"0": 0,
"1": 0
}
"offset": [0, 0]
}
},
"version": 0.4

View File

@@ -368,10 +368,10 @@
"ds": {
"scale": 1,
"offset": [
149.9747408641311,
383.8593224280729
0,
0
]
}
},
"version": 0.4
}
}

View File

@@ -31,5 +31,11 @@
"links": [],
"groups": [],
"config": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}
}

View File

@@ -0,0 +1,11 @@
{
"8": {
"inputs": {
"image": "animated_web.webp"
},
"class_type": "DevToolsLoadAnimatedImageTest",
"_meta": {
"title": "Load Animated Image"
}
}
}

View File

@@ -27,6 +27,11 @@
"links": [],
"groups": [],
"config": {},
"extra": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}

View File

@@ -41,6 +41,11 @@
"links": [],
"groups": [],
"config": {},
"extra": {},
"extra": {
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}
}

View File

@@ -0,0 +1,64 @@
{
"id": "3f1fcbf9-f9de-4935-8fad-401813f61b13",
"revision": 0,
"last_node_id": 10,
"last_link_id": 4,
"nodes": [
{
"id": 9,
"type": "SaveAnimatedWEBP",
"pos": [336, 104],
"size": [210, 368],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 4
}
],
"outputs": [],
"properties": {},
"widgets_values": ["ComfyUI", 6, true, 80, "default"]
},
{
"id": 10,
"type": "DevToolsLoadAnimatedImageTest",
"pos": [64, 104],
"size": [210, 316],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [4]
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"Node name for S&R": "DevToolsLoadAnimatedImageTest"
},
"widgets_values": ["animated_web.webp", "image"]
}
],
"links": [[4, 10, 0, 9, 0, "IMAGE"]],
"groups": [],
"config": {},
"extra": {
"frontendVersion": "1.17.0",
"ds": {
"offset": [0, 0],
"scale": 1
}
},
"version": 0.4
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 75 KiB

View File

@@ -133,6 +133,9 @@ export class ComfyPage {
// Inputs
public readonly workflowUploadInput: Locator
// Toasts
public readonly visibleToasts: Locator
// Components
public readonly searchBox: ComfyNodeSearchBox
public readonly menu: ComfyMenu
@@ -159,6 +162,8 @@ export class ComfyPage {
this.resetViewButton = page.getByRole('button', { name: 'Reset View' })
this.queueButton = page.getByRole('button', { name: 'Queue Prompt' })
this.workflowUploadInput = page.locator('#comfy-file-input')
this.visibleToasts = page.locator('.p-toast-message:visible')
this.searchBox = new ComfyNodeSearchBox(page)
this.menu = new ComfyMenu(page)
this.actionbar = new ComfyActionbar(page)
@@ -396,6 +401,30 @@ export class ComfyPage {
await this.nextFrame()
}
async deleteWorkflow(
workflowName: string,
whenMissing: 'ignoreMissing' | 'throwIfMissing' = 'ignoreMissing'
) {
// Open workflows tab
const { workflowsTab } = this.menu
await workflowsTab.open()
// Action to take if workflow missing
if (whenMissing === 'ignoreMissing') {
const workflows = await workflowsTab.getTopLevelSavedWorkflowNames()
if (!workflows.includes(workflowName)) return
}
// Delete workflow
await workflowsTab.getPersistedItem(workflowName).click({ button: 'right' })
await this.clickContextMenuItem('Delete')
await this.confirmDialog.delete.click()
// Clear toast & close tab
await this.closeToasts(1)
await workflowsTab.close()
}
async resetView() {
if (await this.resetViewButton.isVisible()) {
await this.resetViewButton.click()
@@ -412,7 +441,20 @@ export class ComfyPage {
}
async getVisibleToastCount() {
return await this.page.locator('.p-toast:visible').count()
return await this.visibleToasts.count()
}
async closeToasts(requireCount = 0) {
if (requireCount) await expect(this.visibleToasts).toHaveCount(requireCount)
// Clear all toasts
const toastCloseButtons = await this.page
.locator('.p-toast-close-button')
.all()
for (const button of toastCloseButtons) {
await button.click()
}
await expect(this.visibleToasts).toHaveCount(0)
}
async clickTextEncodeNode1() {
@@ -463,87 +505,129 @@ export class ComfyPage {
await this.nextFrame()
}
async dragAndDropFile(
fileName: string,
async dragAndDropExternalResource(
options: {
fileName?: string
url?: string
dropPosition?: Position
} = {}
) {
const { dropPosition = { x: 100, y: 100 } } = options
const { dropPosition = { x: 100, y: 100 }, fileName, url } = options
const filePath = this.assetPath(fileName)
if (!fileName && !url)
throw new Error('Must provide either fileName or url')
// Read the file content
const buffer = fs.readFileSync(filePath)
const evaluateParams: {
dropPosition: Position
fileName?: string
fileType?: string
buffer?: Uint8Array | number[]
url?: string
} = { dropPosition }
// Get file type
const getFileType = (fileName: string) => {
if (fileName.endsWith('.png')) return 'image/png'
if (fileName.endsWith('.webp')) return 'image/webp'
if (fileName.endsWith('.webm')) return 'video/webm'
if (fileName.endsWith('.json')) return 'application/json'
if (fileName.endsWith('.glb')) return 'model/gltf-binary'
return 'application/octet-stream'
// Dropping a file from the filesystem
if (fileName) {
const filePath = this.assetPath(fileName)
const buffer = fs.readFileSync(filePath)
const getFileType = (fileName: string) => {
if (fileName.endsWith('.png')) return 'image/png'
if (fileName.endsWith('.svg')) return 'image/svg+xml'
if (fileName.endsWith('.webp')) return 'image/webp'
if (fileName.endsWith('.webm')) return 'video/webm'
if (fileName.endsWith('.json')) return 'application/json'
if (fileName.endsWith('.glb')) return 'model/gltf-binary'
return 'application/octet-stream'
}
evaluateParams.fileName = fileName
evaluateParams.fileType = getFileType(fileName)
evaluateParams.buffer = [...new Uint8Array(buffer)]
}
const fileType = getFileType(fileName)
// Dropping a URL (e.g., dropping image across browser tabs in Firefox)
if (url) evaluateParams.url = url
await this.page.evaluate(
async ({ buffer, fileName, fileType, dropPosition }) => {
const file = new File([new Uint8Array(buffer)], fileName, {
type: fileType
})
const dataTransfer = new DataTransfer()
dataTransfer.items.add(file)
// Execute the drag and drop in the browser
await this.page.evaluate(async (params) => {
const dataTransfer = new DataTransfer()
const targetElement = document.elementFromPoint(
dropPosition.x,
dropPosition.y
)
if (!targetElement) {
console.error('No element found at drop position:', dropPosition)
return { success: false, error: 'No element at position' }
}
const eventOptions = {
bubbles: true,
cancelable: true,
dataTransfer,
clientX: dropPosition.x,
clientY: dropPosition.y
}
const dragOverEvent = new DragEvent('dragover', eventOptions)
const dropEvent = new DragEvent('drop', eventOptions)
Object.defineProperty(dropEvent, 'preventDefault', {
value: () => {},
writable: false
})
Object.defineProperty(dropEvent, 'stopPropagation', {
value: () => {},
writable: false
})
targetElement.dispatchEvent(dragOverEvent)
targetElement.dispatchEvent(dropEvent)
return {
success: true,
targetInfo: {
tagName: targetElement.tagName,
id: targetElement.id,
classList: Array.from(targetElement.classList)
// Add file if provided
if (params.buffer && params.fileName && params.fileType) {
const file = new File(
[new Uint8Array(params.buffer)],
params.fileName,
{
type: params.fileType
}
)
dataTransfer.items.add(file)
}
// Add URL data if provided
if (params.url) {
dataTransfer.setData('text/uri-list', params.url)
dataTransfer.setData('text/x-moz-url', params.url)
}
const targetElement = document.elementFromPoint(
params.dropPosition.x,
params.dropPosition.y
)
if (!targetElement) {
console.error('No element found at drop position:', params.dropPosition)
return { success: false, error: 'No element at position' }
}
const eventOptions = {
bubbles: true,
cancelable: true,
dataTransfer,
clientX: params.dropPosition.x,
clientY: params.dropPosition.y
}
const dragOverEvent = new DragEvent('dragover', eventOptions)
const dropEvent = new DragEvent('drop', eventOptions)
Object.defineProperty(dropEvent, 'preventDefault', {
value: () => {},
writable: false
})
Object.defineProperty(dropEvent, 'stopPropagation', {
value: () => {},
writable: false
})
targetElement.dispatchEvent(dragOverEvent)
targetElement.dispatchEvent(dropEvent)
return {
success: true,
targetInfo: {
tagName: targetElement.tagName,
id: targetElement.id,
classList: Array.from(targetElement.classList)
}
},
{ buffer: [...new Uint8Array(buffer)], fileName, fileType, dropPosition }
)
}
}, evaluateParams)
await this.nextFrame()
}
async dragAndDropFile(
fileName: string,
options: { dropPosition?: Position } = {}
) {
return this.dragAndDropExternalResource({ fileName, ...options })
}
async dragAndDropURL(url: string, options: { dropPosition?: Position } = {}) {
return this.dragAndDropExternalResource({ url, ...options })
}
async dragNode2() {
await this.dragAndDrop({ x: 622, y: 400 }, { x: 622, y: 300 })
await this.nextFrame()
@@ -882,10 +966,16 @@ export class ComfyPage {
return window['app'].canvas.ds.convertOffsetToCanvas(pos)
}, pos)
}
/** Get number of DOM widgets on the canvas. */
async getDOMWidgetCount() {
return await this.page.locator('.dom-widget').count()
}
async getNodeRefById(id: NodeId) {
return new NodeReference(id, this)
}
async getNodes() {
async getNodes(): Promise<LGraphNode[]> {
return await this.page.evaluate(() => {
return window['app'].graph.nodes
})

View File

@@ -81,7 +81,7 @@ export class NodeWidgetReference {
if (!widget) throw new Error(`Widget ${index} not found.`)
const [x, y, w, h] = node.getBounding()
return window['app'].canvas.ds.convertOffsetToCanvas([
return window['app'].canvasPosToClientPos([
x + w / 2,
y + window['LiteGraph']['NODE_TITLE_HEIGHT'] + widget.last_y + 1
])
@@ -94,6 +94,36 @@ export class NodeWidgetReference {
}
}
/**
* @returns The position of the widget's associated socket
*/
async getSocketPosition(): Promise<Position> {
const pos: [number, number] = await this.node.comfyPage.page.evaluate(
([id, index]) => {
const node = window['app'].graph.getNodeById(id)
if (!node) throw new Error(`Node ${id} not found.`)
const widget = node.widgets[index]
if (!widget) throw new Error(`Widget ${index} not found.`)
const slot = node.inputs.find(
(slot) => slot.widget?.name === widget.name
)
if (!slot) throw new Error(`Socket ${widget.name} not found.`)
const [x, y] = node.getBounding()
return window['app'].canvasPosToClientPos([
x + slot.pos[0],
y + slot.pos[1] + window['LiteGraph']['NODE_TITLE_HEIGHT']
])
},
[this.node.id, this.index] as const
)
return {
x: pos[0],
y: pos[1]
}
}
async click() {
await this.node.comfyPage.canvas.click({
position: await this.getPosition()
@@ -250,7 +280,7 @@ export class NodeReference {
const targetWidget = await targetNode.getWidget(targetWidgetIndex)
await this.comfyPage.dragAndDrop(
await originSlot.getPosition(),
await targetWidget.getPosition()
await targetWidget.getSocketPosition()
)
return originSlot
}

View File

@@ -0,0 +1,251 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
test.describe('Background Image Upload', () => {
test.beforeEach(async ({ comfyPage }) => {
// Reset the background image setting before each test
await comfyPage.setSetting('Comfy.Canvas.BackgroundImage', '')
})
test.afterEach(async ({ comfyPage }) => {
// Clean up background image setting after each test
await comfyPage.setSetting('Comfy.Canvas.BackgroundImage', '')
})
test('should show background image upload component in settings', async ({
comfyPage
}) => {
// Open settings dialog
await comfyPage.page.keyboard.press('Control+,')
// Navigate to Appearance category
const appearanceOption = comfyPage.page.locator('text=Appearance')
await appearanceOption.click()
// Find the background image setting
const backgroundImageSetting = comfyPage.page.locator(
'#Comfy\\.Canvas\\.BackgroundImage'
)
await expect(backgroundImageSetting).toBeVisible()
// Verify the component has the expected elements using semantic selectors
const urlInput = backgroundImageSetting.locator('input[type="text"]')
await expect(urlInput).toBeVisible()
await expect(urlInput).toHaveAttribute('placeholder')
const uploadButton = backgroundImageSetting.locator(
'button:has(.pi-upload)'
)
await expect(uploadButton).toBeVisible()
const clearButton = backgroundImageSetting.locator('button:has(.pi-trash)')
await expect(clearButton).toBeVisible()
await expect(clearButton).toBeDisabled() // Should be disabled when no image
})
test('should upload image file and set as background', async ({
comfyPage
}) => {
// Open settings dialog
await comfyPage.page.keyboard.press('Control+,')
// Navigate to Appearance category
const appearanceOption = comfyPage.page.locator('text=Appearance')
await appearanceOption.click()
// Find the background image setting
const backgroundImageSetting = comfyPage.page.locator(
'#Comfy\\.Canvas\\.BackgroundImage'
)
// Click the upload button to trigger file input
const uploadButton = backgroundImageSetting.locator(
'button:has(.pi-upload)'
)
// Set up file upload handler
const fileChooserPromise = comfyPage.page.waitForEvent('filechooser')
await uploadButton.click()
const fileChooser = await fileChooserPromise
// Upload the test image
await fileChooser.setFiles(comfyPage.assetPath('image32x32.webp'))
// Wait for upload to complete and verify the setting was updated
await comfyPage.page.waitForTimeout(500) // Give time for file reading
// Verify the URL input now has an API URL
const urlInput = backgroundImageSetting.locator('input[type="text"]')
const inputValue = await urlInput.inputValue()
expect(inputValue).toMatch(/^\/api\/view\?.*subfolder=backgrounds/)
// Verify clear button is now enabled
const clearButton = backgroundImageSetting.locator('button:has(.pi-trash)')
await expect(clearButton).toBeEnabled()
// Verify the setting value was actually set
const settingValue = await comfyPage.getSetting(
'Comfy.Canvas.BackgroundImage'
)
expect(settingValue).toMatch(/^\/api\/view\?.*subfolder=backgrounds/)
})
test('should accept URL input for background image', async ({
comfyPage
}) => {
const testImageUrl = 'https://example.com/test-image.png'
// Open settings dialog
await comfyPage.page.keyboard.press('Control+,')
// Navigate to Appearance category
const appearanceOption = comfyPage.page.locator('text=Appearance')
await appearanceOption.click()
// Find the background image setting
const backgroundImageSetting = comfyPage.page.locator(
'#Comfy\\.Canvas\\.BackgroundImage'
)
// Enter URL in the input field
const urlInput = backgroundImageSetting.locator('input[type="text"]')
await urlInput.fill(testImageUrl)
// Trigger blur event to ensure the value is set
await urlInput.blur()
// Verify clear button is now enabled
const clearButton = backgroundImageSetting.locator('button:has(.pi-trash)')
await expect(clearButton).toBeEnabled()
// Verify the setting value was updated
const settingValue = await comfyPage.getSetting(
'Comfy.Canvas.BackgroundImage'
)
expect(settingValue).toBe(testImageUrl)
})
test('should clear background image when clear button is clicked', async ({
comfyPage
}) => {
const testImageUrl = 'https://example.com/test-image.png'
// First set a background image
await comfyPage.setSetting('Comfy.Canvas.BackgroundImage', testImageUrl)
// Open settings dialog
await comfyPage.page.keyboard.press('Control+,')
// Navigate to Appearance category
const appearanceOption = comfyPage.page.locator('text=Appearance')
await appearanceOption.click()
// Find the background image setting
const backgroundImageSetting = comfyPage.page.locator(
'#Comfy\\.Canvas\\.BackgroundImage'
)
// Verify the input has the test URL
const urlInput = backgroundImageSetting.locator('input[type="text"]')
await expect(urlInput).toHaveValue(testImageUrl)
// Verify clear button is enabled
const clearButton = backgroundImageSetting.locator('button:has(.pi-trash)')
await expect(clearButton).toBeEnabled()
// Click the clear button
await clearButton.click()
// Verify the input is now empty
await expect(urlInput).toHaveValue('')
// Verify clear button is now disabled
await expect(clearButton).toBeDisabled()
// Verify the setting value was cleared
const settingValue = await comfyPage.getSetting(
'Comfy.Canvas.BackgroundImage'
)
expect(settingValue).toBe('')
})
test('should show tooltip on upload and clear buttons', async ({
comfyPage
}) => {
// Open settings dialog
await comfyPage.page.keyboard.press('Control+,')
// Navigate to Appearance category
const appearanceOption = comfyPage.page.locator('text=Appearance')
await appearanceOption.click()
// Find the background image setting
const backgroundImageSetting = comfyPage.page.locator(
'#Comfy\\.Canvas\\.BackgroundImage'
)
// Hover over upload button and verify tooltip appears
const uploadButton = backgroundImageSetting.locator(
'button:has(.pi-upload)'
)
await uploadButton.hover()
// Wait for tooltip to appear and verify it exists
await comfyPage.page.waitForTimeout(700) // Tooltip delay
const uploadTooltip = comfyPage.page.locator('.p-tooltip:visible')
await expect(uploadTooltip).toBeVisible()
// Move away to hide tooltip
await comfyPage.page.locator('body').hover()
await comfyPage.page.waitForTimeout(100)
// Set a background to enable clear button
const urlInput = backgroundImageSetting.locator('input[type="text"]')
await urlInput.fill('https://example.com/test.png')
await urlInput.blur()
// Hover over clear button and verify tooltip appears
const clearButton = backgroundImageSetting.locator('button:has(.pi-trash)')
await clearButton.hover()
// Wait for tooltip to appear and verify it exists
await comfyPage.page.waitForTimeout(700) // Tooltip delay
const clearTooltip = comfyPage.page.locator('.p-tooltip:visible')
await expect(clearTooltip).toBeVisible()
})
test('should maintain reactive updates between URL input and clear button state', async ({
comfyPage
}) => {
// Open settings dialog
await comfyPage.page.keyboard.press('Control+,')
// Navigate to Appearance category
const appearanceOption = comfyPage.page.locator('text=Appearance')
await appearanceOption.click()
// Find the background image setting
const backgroundImageSetting = comfyPage.page.locator(
'#Comfy\\.Canvas\\.BackgroundImage'
)
const urlInput = backgroundImageSetting.locator('input[type="text"]')
const clearButton = backgroundImageSetting.locator('button:has(.pi-trash)')
// Initially clear button should be disabled
await expect(clearButton).toBeDisabled()
// Type some text - clear button should become enabled
await urlInput.fill('test')
await expect(clearButton).toBeEnabled()
// Clear the text manually - clear button should become disabled again
await urlInput.fill('')
await expect(clearButton).toBeDisabled()
// Add text again - clear button should become enabled
await urlInput.fill('https://example.com/image.png')
await expect(clearButton).toBeEnabled()
// Use clear button - should clear input and disable itself
await clearButton.click()
await expect(urlInput).toHaveValue('')
await expect(clearButton).toBeDisabled()
})
})

View File

@@ -0,0 +1,139 @@
import { Page, expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
interface ChatHistoryEntry {
prompt: string
response: string
response_id: string
}
async function renderChatHistory(page: Page, history: ChatHistoryEntry[]) {
const nodeId = await page.evaluate(() => window['app'].graph.nodes[0]?.id)
// Simulate API sending display_component message
await page.evaluate(
({ nodeId, history }) => {
const event = new CustomEvent('display_component', {
detail: {
node_id: nodeId,
component: 'ChatHistoryWidget',
props: {
history: JSON.stringify(history)
}
}
})
window['app'].api.dispatchEvent(event)
return true
},
{ nodeId, history }
)
return nodeId
}
test.describe('Chat History Widget', () => {
let nodeId: string
test.beforeEach(async ({ comfyPage }) => {
nodeId = await renderChatHistory(comfyPage.page, [
{ prompt: 'Hello', response: 'World', response_id: '123' }
])
// Wait for chat history to be rendered
await comfyPage.page.waitForSelector('.pi-pencil')
})
test('displays chat history when receiving display_component message', async ({
comfyPage
}) => {
// Verify the chat history is displayed correctly
await expect(comfyPage.page.getByText('Hello')).toBeVisible()
await expect(comfyPage.page.getByText('World')).toBeVisible()
})
test('handles message editing interaction', async ({ comfyPage }) => {
// Get first node's ID
nodeId = await comfyPage.page.evaluate(() => {
const node = window['app'].graph.nodes[0]
// Make sure the node has a prompt widget (for editing functionality)
if (!node.widgets) {
node.widgets = []
}
// Add a prompt widget if it doesn't exist
if (!node.widgets.find((w) => w.name === 'prompt')) {
node.widgets.push({
name: 'prompt',
type: 'text',
value: 'Original prompt'
})
}
return node.id
})
await renderChatHistory(comfyPage.page, [
{
prompt: 'Message 1',
response: 'Response 1',
response_id: '123'
},
{
prompt: 'Message 2',
response: 'Response 2',
response_id: '456'
}
])
await comfyPage.page.waitForSelector('.pi-pencil')
const originalTextAreaInput = await comfyPage.page
.getByPlaceholder('text')
.nth(1)
.inputValue()
// Click edit button on first message
await comfyPage.page.getByLabel('Edit').first().click()
await comfyPage.nextFrame()
// Verify cancel button appears
await expect(comfyPage.page.getByLabel('Cancel')).toBeVisible()
// Click cancel edit
await comfyPage.page.getByLabel('Cancel').click()
// Verify prompt input is restored
await expect(comfyPage.page.getByPlaceholder('text').nth(1)).toHaveValue(
originalTextAreaInput
)
})
test('handles real-time updates to chat history', async ({ comfyPage }) => {
// Send initial history
await renderChatHistory(comfyPage.page, [
{
prompt: 'Initial message',
response: 'Initial response',
response_id: '123'
}
])
await comfyPage.page.waitForSelector('.pi-pencil')
// Update history with additional messages
await renderChatHistory(comfyPage.page, [
{
prompt: 'Follow-up',
response: 'New response',
response_id: '456'
}
])
await comfyPage.page.waitForSelector('.pi-pencil')
// Move mouse over the canvas to force update
await comfyPage.page.mouse.move(100, 100)
await comfyPage.nextFrame()
// Verify new messages appear
await expect(comfyPage.page.getByText('Follow-up')).toBeVisible()
await expect(comfyPage.page.getByText('New response')).toBeVisible()
})
})

View File

@@ -48,6 +48,7 @@ const customColorPalettes: Record<string, Palette> = {
WIDGET_OUTLINE_COLOR: '#333',
WIDGET_TEXT_COLOR: '#a3a3a8',
WIDGET_SECONDARY_TEXT_COLOR: '#97979c',
WIDGET_DISABLED_TEXT_COLOR: '#646464',
LINK_COLOR: '#9A9',
EVENT_LINK_COLOR: '#A86',
CONNECTING_LINK_COLOR: '#AFA'
@@ -111,6 +112,7 @@ const customColorPalettes: Record<string, Palette> = {
WIDGET_OUTLINE_COLOR: '#333',
WIDGET_TEXT_COLOR: '#a3a3a8',
WIDGET_SECONDARY_TEXT_COLOR: '#97979c',
WIDGET_DISABLED_TEXT_COLOR: '#646464',
LINK_COLOR: '#9A9',
EVENT_LINK_COLOR: '#A86',
CONNECTING_LINK_COLOR: '#AFA'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

@@ -32,7 +32,7 @@ test.describe('Keybindings', () => {
})
await comfyPage.executeCommand('TestCommand')
await expect(comfyPage.page.locator('.p-toast')).toBeVisible()
expect(await comfyPage.getToastErrorCount()).toBe(1)
})
test('Should handle async command errors', async ({ comfyPage }) => {
@@ -45,6 +45,6 @@ test.describe('Keybindings', () => {
})
await comfyPage.executeCommand('TestCommand')
await expect(comfyPage.page.locator('.p-toast')).toBeVisible()
expect(await comfyPage.getToastErrorCount()).toBe(1)
})
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

@@ -323,7 +323,48 @@ test.describe('Error dialog', () => {
await comfyPage.loadWorkflow('default')
const errorDialog = comfyPage.page.locator('.error-dialog-content')
const errorDialog = comfyPage.page.locator('.comfy-error-report')
await expect(errorDialog).toBeVisible()
})
test('Should display an error dialog when prompt execution fails', async ({
comfyPage
}) => {
await comfyPage.page.evaluate(async () => {
const app = window['app']
app.api.queuePrompt = () => {
throw new Error('Error on queuePrompt!')
}
await app.queuePrompt(0)
})
const errorDialog = comfyPage.page.locator('.comfy-error-report')
await expect(errorDialog).toBeVisible()
})
})
test.describe('Signin dialog', () => {
test('Paste content to signin dialog should not paste node on canvas', async ({
comfyPage
}) => {
const nodeNum = (await comfyPage.getNodes()).length
await comfyPage.clickEmptyLatentNode()
await comfyPage.ctrlC()
const textBox = comfyPage.widgetTextBox
await textBox.click()
await textBox.fill('test_password')
await textBox.press('Control+a')
await textBox.press('Control+c')
await comfyPage.page.evaluate(() => {
window['app'].extensionManager.dialog.showSignInDialog()
})
const input = comfyPage.page.locator('#comfy-org-sign-in-password')
await input.waitFor({ state: 'visible' })
await input.press('Control+v')
await expect(input).toHaveValue('test_password')
expect(await comfyPage.getNodes()).toHaveLength(nodeNum)
})
})

View File

@@ -24,4 +24,27 @@ test.describe('DOM Widget', () => {
await expect(firstMultiline).not.toBeVisible()
await expect(lastMultiline).not.toBeVisible()
})
test('Position update when entering focus mode', async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.executeCommand('Workspace.ToggleFocusMode')
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('focus-mode-on.png')
})
// No DOM widget should be created by creation of interim LGraphNode objects.
test('Copy node with DOM widget by dragging + alt', async ({ comfyPage }) => {
const initialCount = await comfyPage.getDOMWidgetCount()
// TextEncodeNode1
await comfyPage.page.mouse.move(618, 191)
await comfyPage.page.keyboard.down('Alt')
await comfyPage.page.mouse.down()
await comfyPage.page.mouse.move(100, 100)
await comfyPage.page.mouse.up()
await comfyPage.page.keyboard.up('Alt')
const finalCount = await comfyPage.getDOMWidgetCount()
expect(finalCount).toBe(initialCount + 1)
})
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@@ -0,0 +1,44 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
test.describe('Execution', () => {
test('Report error on unconnected slot', async ({ comfyPage }) => {
await comfyPage.disconnectEdge()
await comfyPage.clickEmptySpace()
await comfyPage.executeCommand('Comfy.QueuePrompt')
await expect(comfyPage.page.locator('.comfy-error-report')).toBeVisible()
await comfyPage.page.locator('.p-dialog-close-button').click()
await comfyPage.page.locator('.comfy-error-report').waitFor({
state: 'hidden'
})
await expect(comfyPage.canvas).toHaveScreenshot(
'execution-error-unconnected-slot.png'
)
})
})
test.describe('Execute to selected output nodes', () => {
test('Execute to selected output nodes', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('execution/partial_execution')
const input = await comfyPage.getNodeRefById(3)
const output1 = await comfyPage.getNodeRefById(1)
const output2 = await comfyPage.getNodeRefById(4)
expect(await (await input.getWidget(0)).getValue()).toBe('foo')
expect(await (await output1.getWidget(0)).getValue()).toBe('')
expect(await (await output2.getWidget(0)).getValue()).toBe('')
await output1.click('title')
await comfyPage.executeCommand('Comfy.QueueSelectedOutputNodes')
// @note: Wait for the execution to finish. We might want to move to a more
// reliable way to wait for the execution to finish. Workflow in this test
// is simple enough that this is fine for now.
await comfyPage.page.waitForTimeout(200)
expect(await (await input.getWidget(0)).getValue()).toBe('foo')
expect(await (await output1.getWidget(0)).getValue()).toBe('foo')
expect(await (await output2.getWidget(0)).getValue()).toBe('')
})
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View File

@@ -0,0 +1,21 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
test.describe('Graph', () => {
// Should be able to fix link input slot index after swap the input order
// Ref: https://github.com/Comfy-Org/ComfyUI_frontend/issues/3348
test('Fix link input slots', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('input_order_swap')
expect(
await comfyPage.page.evaluate(() => {
return window['app'].graph.links.get(1)?.target_slot
})
).toBe(1)
})
test('Validate workflow links', async ({ comfyPage }) => {
await comfyPage.loadWorkflow('bad_link')
await expect(comfyPage.getVisibleToastCount()).resolves.toBe(2)
})
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 99 KiB

View File

@@ -1,6 +1,6 @@
import { expect } from '@playwright/test'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import { type ComfyPage, comfyPageFixture as test } from '../fixtures/ComfyPage'
test.describe('Item Interaction', () => {
test('Can select/delete all items', async ({ comfyPage }) => {
@@ -666,6 +666,12 @@ test.describe('Load workflow', () => {
expect(activeWorkflowName).toEqual(workflowPathB)
})
})
test('Auto fit view after loading workflow', async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.EnableWorkflowViewRestore', false)
await comfyPage.loadWorkflow('single_ksampler')
await expect(comfyPage.canvas).toHaveScreenshot('single_ksampler_fit.png')
})
})
test.describe('Load duplicate workflow', () => {
@@ -683,3 +689,42 @@ test.describe('Load duplicate workflow', () => {
expect(await comfyPage.getGraphNodesCount()).toBe(1)
})
})
test.describe('Viewport settings', () => {
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.setSetting('Comfy.UseNewMenu', 'Top')
await comfyPage.setSetting('Comfy.Workflow.WorkflowTabsPosition', 'Topbar')
await comfyPage.setupWorkflowsDirectory({})
})
test('Keeps viewport settings when changing tabs', async ({
comfyPage,
comfyMouse
}) => {
// Screenshot the canvas element
await comfyPage.menu.topbar.saveWorkflow('Workflow A')
await expect(comfyPage.canvas).toHaveScreenshot('viewport-workflow-a.png')
// Save workflow as a new file, then zoom out before screen shot
await comfyPage.menu.topbar.saveWorkflowAs('Workflow B')
await comfyMouse.move(comfyPage.emptySpace)
for (let i = 0; i < 4; i++) {
await comfyMouse.wheel(0, 60)
}
await expect(comfyPage.canvas).toHaveScreenshot('viewport-workflow-b.png')
const tabA = comfyPage.menu.topbar.getWorkflowTab('Workflow A')
const tabB = comfyPage.menu.topbar.getWorkflowTab('Workflow B')
// Go back to Workflow A
await tabA.click()
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('viewport-workflow-a.png')
// And back to Workflow B
await tabB.click()
await comfyPage.nextFrame()
await expect(comfyPage.canvas).toHaveScreenshot('viewport-workflow-b.png')
})
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 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: 98 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 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: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 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: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

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