Integrates Stripe's pricing table web component into the subscription
dialog when the subscription_tiers_enabled feature flag is active. The
implementation includes a new StripePricingTable component that loads
Stripe's pricing table script and renders the table with proper error
handling and loading states. The subscription dialog now displays the
Stripe pricing table with contact us and enterprise links, using a
1100px width that balances multi-column layout with visual design.
Configuration supports environment variables, remote config, and window
config for the Stripe publishable key and pricing table ID.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7288-feat-add-Stripe-pricing-table-integration-for-subscription-dialog-conditional-on-featur-2c46d73d365081fa9d93c213df118996)
by [Unito](https://www.unito.io)
## Summary
- When the next minor branch (e.g., `core/1.35`) doesn't exist yet, fall
back to current minor (`core/1.34`) for patch releases instead of
failing
- Fixes the weekly release workflow failure when ComfyUI is on version
1.33.x and `core/1.34` doesn't exist yet
## Test plan
- [x] Tested locally with version where next minor exists (1.33.5 →
finds core/1.34)
- [x] Tested fallback when next minor doesn't exist (1.34.7 → falls back
to core/1.34)
- [x] Tested error case when neither branch exists
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7286-fix-Fall-back-to-current-minor-when-next-minor-branch-doesn-t-exist-2c46d73d365081009762c732954e148d)
by [Unito](https://www.unito.io)
Re-enables the system notification popup for cloud distribution,
allowing cloud devs to notify cloud users about new features and updates
without requiring a new release.
Cloud now fetches release notes from the "cloud" project (instead of
"comfyui") and uses the `cloud_version` field for version comparison.
Since cloud versions are git hashes rather than semver, a helper handles
both formats gracefully.
The "What's New" popup is enabled for cloud, while the update toast and
red dot indicator remain desktop-only since cloud auto-updates and
doesn't require user action.
You can test this by doing `pnpm dev:cloud` and you will see a
notification I added (for testing):
<img width="1891" height="2077" alt="image"
src="https://github.com/user-attachments/assets/6599a6dc-a3e1-406f-a22d-14262be1f258"
/>
Content is controlled by non-devs at cms.comfy.org.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7277-feat-Enable-system-notifications-on-cloud-2c46d73d365081bcb33cd79ec18faefe)
by [Unito](https://www.unito.io)
## Summary
Unify the current sidebar tabs, structurally and aesthetically.
## Changes
- Removes the Assets only Layout
- Standardizes the title styling and spacing across the tabs.
## Review Focus
<!-- Critical design decisions or edge cases that need attention -->
<!-- If this PR fixes an issue, uncomment and update the line below -->
<!-- Fixes #ISSUE_NUMBER -->
## Screenshots (if applicable)
<!-- Add screenshots or video recording to help explain your changes -->
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7215-WIP-Sidebar-Tabs-component-and-style-alignment-2c26d73d3650817193bfd752e0d0bbde)
by [Unito](https://www.unito.io)
## Summary
- make `useExternalLink` rely on the global i18n locale so it can be
used safely outside setup
- restore `electronAdapter` to use the shared `useExternalLink` helper
for docs URLs and static links
## Motivation
Desktop menu items disappeared because a top-level call to
`useExternalLink` in `electronAdapter` triggered `useI18n` at
module-eval time, throwing and blocking extension registration. By
making the composable global-locale-only and using it in
`electronAdapter`, the module can load without setup context while
preserving link behavior.
## Testing
- pnpm typecheck
- pnpm lint:fix
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7181-Fix-desktop-menu-docs-links-regression-2c06d73d36508157ae48cff078b9173e)
by [Unito](https://www.unito.io)
## Summary
Reduce lower level font definitions in most places. Default to Inter.
See #6912
## Review Focus
Comic Sans is still an option...
## Screenshots (if applicable)
<!-- Add screenshots or video recording to help explain your changes -->
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7220-Style-Font-Consistency-2c26d73d365081348f2dd8909dd9bb8f)
by [Unito](https://www.unito.io)
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
## Summary
report and fix https://github.com/Comfy-Org/ComfyUI_frontend/issues/3919
- Convert recursive gcd to iterative to avoid stack overflow
- Add epsilon tolerance (1e-10) for floating-point precision issues
This fixes workflow loading hangs when node trying merge values like
0.01 and 0.001, which caused the original recursive gcd to run
indefinitely due to floating-point modulo never reaching exactly zero.
please notice, we need both iterative and epsilon together to fix this
gcd issue
Call Chain
PrimitiveNode.onAfterGraphConfigured
→ #mergeWidgetConfig
→ #isValidConnection
→ mergeIfValid
→ mergeInputSpec
→ mergeNumericInputSpec
→ lcm(step1, step2)
→ gcd(a, b) ← Problem here
Why It Happened
When some nodes connect to multiple nodes, it may merge values using
LCM, which internally calls GCD.
Original recursive implementation:
```
export const gcd = (a: number, b: number): number => {
return b === 0 ? a : gcd(b, a % b)
}
```
Issues:
1. Stack Overflow: Recursive calls with many nodes exhausted the call
stack.
2. Floating-Point Precision: For values like gcd(0.01, 0.001):
` 0.01 % 0.001 = 0.0009999999999999994 // Not exactly 0!`
3. Due to Ifloating-point representation, the modulo never reaches
exactly zero, causing hundreds or thousands of iterations.
## Screenshots
### before
https://github.com/user-attachments/assets/cca4342c-a882-4590-a8d4-1e0bea19e5b7
### fix with only iterative, without epsilon
https://github.com/user-attachments/assets/1dc52aa4-a86a-40b5-8bac-904094c4c36b
### final fix with iterative and epsilon
https://github.com/user-attachments/assets/7b868b50-c3c9-4be4-8594-27cecbc08a26
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7258-performance-fix-prevent-gcd-infinite-loop-with-floating-point-step-values-2c46d73d3650818cbe8cf455c934a114)
by [Unito](https://www.unito.io)
## Summary
- Adds `auto-filter-focus` prop to Select component when filtering is
enabled
- When the dropdown opens, the filter input is automatically focused
- This prevents keystrokes from triggering global shortcuts while the
user is trying to filter options
## Root Cause
When a user opens a Select dropdown with a filter and starts typing
without explicitly clicking the search box, the filter input doesn't
have focus. Keystrokes are then captured by global shortcut handlers
(e.g., pressing "R" triggers "refresh nodes") instead of filtering the
options.
## Solution
PrimeVue's Select component has an `auto-filter-focus` prop that
automatically focuses the filter input when the dropdown opens. By
enabling this whenever filtering is enabled (`selectOptions.length >
4`), users can immediately start typing to filter without needing to
click the search box first.
## Test plan
- [ ] Open a Select dropdown with more than 4 options (e.g., Load
Checkpoint's ckpt_name)
- [ ] Verify the filter input is automatically focused when the dropdown
opens
- [ ] Type a character and verify it filters the list instead of
triggering shortcuts
- [ ] Verify no console errors when opening/closing the dropdown
Fixes#7221
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7253-fix-autofocus-filter-input-in-Select-dropdowns-to-prevent-shortcut-triggers-2c46d73d365081feacd1f3301aa3b413)
by [Unito](https://www.unito.io)
## Summary
This PR improves the user experience by automatically focusing the
search input field when opening the Workflows, Model Library, or Node
Library sidebar tabs.
## Changes
- **SearchBox.vue**: Exposed a `focus()` method to allow parent
components to programmatically set focus on the input.
- **WorkflowsSidebarTab.vue**: Added a watcher to focus the search box
when the tab is activated.
- **ModelLibrarySidebarTab.vue**: Added autofocus on component mount.
- **NodeLibrarySidebarTab.vue**: Added autofocus on component mount.
## Motivation
Users often switch to these tabs specifically to search for an item.
Automatically focusing the search box reduces friction and saves a
click.
https://github.com/user-attachments/assets/8438e71c-a5e4-4b6c-8665-04d535d3ad8e
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7179-feat-sidebar-autofocus-search-input-in-Workflows-Model-and-Node-tabs-2c06d73d36508199b8c0e83d19f1cd84)
by [Unito](https://www.unito.io)
## Summary
Fixes Vue Nodes 2.0 dropdowns not displaying the selected model when
created from the Asset Browser.
## Root Cause
Widget values were set AFTER the node was added to the graph, causing
Vue's reactivity system to capture stale initial values.
## Solution
Set widget value BEFORE adding node to graph in
`createModelNodeFromAsset.ts`.
## Changes
- **1 file changed**: `createModelNodeFromAsset.ts`
- **4 lines added, 1 removed**: Move widget value assignment before
graph.add()
This ensures Vue's reactivity system captures the correct initial widget
value when the node is created.
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Fix slot link drag and snap/attraction not working on mobile browsers
in Vue Nodes 2.0 mode
- Use `document.elementFromPoint()` to get the actual element under the
pointer instead of relying on `event.target`
## Root Cause
On touch/mobile devices, pointer events have "implicit pointer capture"
- when you touch an element, all subsequent pointer events
(`pointermove`, `pointerup`) for that touch are sent to the same element
where the touch started, regardless of where the pointer moves.
The code was using `event.target` to find slots under the pointer for
snap/attraction. On touch devices, this always returned the original
slot element (where the drag started), not the element currently under
the touch point. This caused:
- No snap/attraction when dragging links over other slots
- Connections failing when dropping on target slots
## Before
https://github.com/user-attachments/assets/55b56d5c-9744-4d6c-abfd-3a2136ab25bc
## After
https://github.com/user-attachments/assets/5bdf2a22-0025-4ae1-9358-35f0100b67d4
## Test plan
- [ ] Enable Vue Nodes 2.0 mode in settings
- [ ] Test on mobile browser or Chrome DevTools mobile simulation
- [ ] Drag a link from one node's output slot to another node's input
slot
- [ ] Verify the link snaps/attracts to compatible slots during drag
- [ ] Verify the connection is made successfully on drop
Fixes#7224
## Summary
Model selection dropdowns now automatically refresh after uploading a
new model, ensuring users see newly uploaded models immediately.
## Changes
- **Cache Orchestration**: Upload wizard now refreshes model caches by
coordinating between `modelToNodeStore` and `assetsStore`
- **Smart Refetching**: Only refreshes node types that use the uploaded
model category (e.g., uploading a checkpoint refreshes
`CheckpointLoaderSimple` but not `LoraLoader`)
- **Clean Architecture**: Stores remain decoupled - the upload wizard
composable orchestrates the refresh logic
## Technical Details
After successful upload, `useUploadModelWizard`:
1. Gets all node providers for the model type from `modelToNodeStore`
2. Calls `assetsStore.updateModelsForNodeType()` for each affected node
type
3. Model dropdowns reactively update via Pinia store watchers
## Review Focus
- Orchestration pattern in upload wizard keeps stores decoupled
- Efficient cache invalidation - only refreshes affected node types
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
When moving an existing link with subgraphInput as source to a new node,
the prior link is removed, but the previous target node would not have
it's link property cleared.
Resolves#7225
Also re-enables several functional skipped tests.
It feels like I'm having to play whack-a-mole reimplementing the same
fixes on every permutation of subgraphIO links. I'd like to setup up a
unified test set that covers them all, but wouldn't want the added work
to further delay this fix.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7229-When-moving-subgraphInput-link-properly-disconnect-old-link-2c36d73d36508149aca0ce477fee5c9e)
by [Unito](https://www.unito.io)
Previously the color of a link would simply use the type of the target
slot and fallback to the type of the origin slot. When a connection is
made to a node that accepts the any type ('*'), the link has the green
color of an unknown type.
Instead, when a connection is made, the type of a link is now calculated
as the greatest common type of the source and destination. This means
that connections to reroutes are correctly colored.
| Before | After |
| ------ | ----- |
| <img width="360" alt="before"
src="https://github.com/user-attachments/assets/a5544730-e69a-4c85-af33-b303bb30ae71"
/>| <img width="360" alt="after"
src="https://github.com/user-attachments/assets/7d7b59fd-1b79-440b-a97d-a1657313c484"
/>|
The code for calculating common types already exists, it has simply been
moved into litegraph and given a more descriptive name.
Resolves#7196
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7211-Color-links-as-common-type-2c16d73d365081188460f6b5973db962)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
## Summary
Adds an interactive video tutorial dialog to help users find CivitAI
model URLs during the Upload Model wizard.
## Changes
- **New Component**: Created reusable `VideoHelpDialog.vue` component
- Full-width video player with floating close button
- Configurable props: `videoUrl`, `loop`, `showControls`
- Custom ESC key handling to prevent parent dialog from closing
- Click backdrop to dismiss
- 70% dark backdrop for better video focus
- **Upload Model Flow**: Integrated video help button in step 1 footer
- "How do I find this?" button opens tutorial video
- Video demonstrates finding model URLs on CivitAI
- PostHog tracking attribute maintained (`upload-model-step1-help-link`)
## Review Focus
- ESC key event handling uses capture phase to prevent propagation to
parent dialogs
- Component follows existing patterns from `MediaVideoTop.vue` and
`BaseModalLayout.vue`
- Video player accessibility (ARIA labels, keyboard navigation)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7177-feat-Add-video-help-dialog-to-Upload-Model-flow-2c06d73d36508148963ad9ee60038ea3)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Fixes an issue where Playwright HTML reports were not being generated
for `chromium-2x`, `chromium-0.5x`, and `mobile-chrome` test runs,
causing 404 errors when accessing report links in PR comments.
## Problem
Only the first report link (chromium) had contents - the other three
browsers returned 404 errors. Investigation revealed that artifacts for
non-chromium browsers were only uploading 1 file (report.json) instead
of the full HTML report with ~32 files.
The root cause was that these browsers run very few tests (1-6 tests
each), and when using `--reporter=html --reporter=json` together,
Playwright would only generate the JSON report without the HTML assets.
## Solution
Changed the workflow for non-chromium browsers to use the same approach
as the sharded chromium tests:
1. Run tests with `--reporter=blob`
2. Generate HTML and JSON reports separately using `merge-reports`
This ensures both HTML and JSON reports are always generated with
complete assets, regardless of test count.
## Testing
The fix can be verified by:
1. Checking that this PR's workflow run uploads similar file counts for
all browsers
2. Confirming all 4 report links are accessible and show proper HTML
content
Related to #7186🤖 Generated with [Claude Code](https://claude.com/claude-code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7193-bugfix-Fix-E2E-test-report-generation-for-non-chromium-browsers-2c06d73d365081ba8ea3ed0d3f5d8d38)
by [Unito](https://www.unito.io)
Co-authored-by: Claude <noreply@anthropic.com>