Skip to content

Conversation

@JemiloII
Copy link
Contributor

@JemiloII JemiloII commented Jan 23, 2026

Summary

Added feature to drag and drop multiple images into the UI and connect them with a Batch Images node with tests to add convenience for users. Only works with a group of images, mixing files not supported.

Review Focus

I've updated our usage of Litegraph.createNode, honestly, that method is pretty bad, onNodeCreated option method doesn't even return the node created. I think I will probably go check out their repo to do a PR over there. Anyways, I made a createNode method to avoid race conditions when creating nodes for the paste actions. Will allow us to better programmatically create nodes that do not have workflows that also need to be connected to other nodes.

https://www.notion.so/comfy-org/Implement-Multi-image-drag-and-drop-to-canvas-2eb6d73d36508195ad8addfc4367db10

Screenshots (if applicable)

2026-01-22.04-04-39.mp4

┆Issue is synchronized with this Notion page by Unito

@JemiloII JemiloII requested a review from a team as a code owner January 23, 2026 20:33
@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Jan 23, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds async node creation (createNode), DataTransfer cloning (cloneDataTransfer), batch image paste flows (pasteImageNodes), FileList-aware drag extraction, LGraph.add null-safety, and corresponding app and test updates across paste handling, litegraph utilities, event handling, and ComfyApp batch positioning.

Changes

Cohort / File(s) Summary
Node creation utilities
src/utils/litegraphUtil.ts, src/utils/litegraphUtil.test.ts
Add exported async createNode(canvas, name): Promise<LGraphNode | null> that wraps LiteGraph.createNode, awaits a microtask, sets node.pos from canvas.graph_mouse, adds to graph, triggers graph.changed; tests added/expanded for success, empty name, null graph, positioning, and error toast.
Paste & clipboard utilities
src/composables/usePaste.ts, src/composables/usePaste.test.ts
Add cloneDataTransfer(original: DataTransfer): DataTransfer; convert pasteImageNode to async Promise<LGraphNode | null>; add pasteImageNodes(canvas, fileList): Promise<LGraphNode[]>; paste handling clones DataTransfer and awaits image-node creation; tests updated for async flows and null-node mocks.
ComfyApp batch processing
src/scripts/app.ts, src/scripts/app.test.ts
Add handleFileList(fileList) and positionBatchNodes(nodes, batchNode); drop/file-load flow delegates to pasteImageNodes for multi-file images; single-file path uses createNode('LoadImage') + pasteImageNode; tests cover batching, positioning, selection, connections, and error cases.
Drag-and-drop extraction
src/utils/eventUtils.ts, src/utils/__tests__/eventUtils.test.ts
Widen extractFileFromDragEvent return to Promise<File | FileList | undefined>; return FileList when multiple dropped files are all images; add tests for multi-image and multiple non-image drops.
LGraph null-safety
src/lib/litegraph/src/LGraph.ts, src/lib/litegraph/src/LGraph.test.ts
Extend LGraph.add signature to accept null and early-return when falsy; add tests asserting graceful handling and unchanged node count when null is added.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant EventUtils as EventUtils\n(extractFileFromDragEvent)
    participant ComfyApp as ComfyApp
    participant PasteUtils as usePaste\n(cloneDataTransfer, pasteImageNodes, pasteImageNode)
    participant CreateNode as litegraphUtil\n(createNode)
    participant LGraph as LGraph
    participant UI as UI

    User->>EventUtils: Drop images
    EventUtils-->>ComfyApp: FileList
    ComfyApp->>PasteUtils: pasteImageNodes(canvas, FileList)
    loop each file
        PasteUtils->>CreateNode: createNode(canvas, "LoadImage")
        CreateNode->>LGraph: LiteGraph.createNode(...)
        CreateNode-->>PasteUtils: positioned LGraphNode
        PasteUtils->>PasteUtils: await paste image into node
        PasteUtils-->>ComfyApp: image LGraphNode
    end
    ComfyApp->>CreateNode: createNode(canvas, "BatchImages")
    CreateNode-->>ComfyApp: batch LGraphNode
    ComfyApp->>ComfyApp: positionBatchNodes(imageNodes, batchNode)
    ComfyApp->>LGraph: connect image nodes to batch slots
    ComfyApp->>UI: select nodes / trigger graph.changed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • DrJKL
  • jtydhr88

Poem

"I hop through clipboard crumbs and trails,
I clone the paste and tweak the scales.
I place each image with tiny feet,
Batch them, link them — tidy and neat. 🐇🌿"

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Batch Drag & Drop Images' directly corresponds to the main feature added: batch image handling with drag-and-drop and automatic Batch Images node creation.
Description check ✅ Passed The description covers the main feature added, includes a review focus section explaining key design decisions (createNode wrapper and race condition handling), and provides a reference link; however, it lacks the structured 'Changes' section from the template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Jan 23, 2026

🎨 Storybook Build Status

loading Build is starting...

⏰ Started at: 01/28/2026, 11:24:15 PM UTC

🚀 Building Storybook

  • 📦 Installing dependencies...
  • 🔧 Building Storybook components...
  • 🌐 Preparing deployment to Cloudflare Pages...

⏱️ Please wait while the Storybook build is in progress...

@github-actions
Copy link

github-actions bot commented Jan 23, 2026

🎭 Playwright Tests: ⏳ Running...

Tests started at 01/28/2026, 11:24:13 PM UTC

📊 Browser Tests
  • chromium: Running...
  • chromium-0.5x: Running...
  • chromium-2x: Running...
  • mobile-chrome: Running...

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🤖 Fix all issues with AI agents
In `@src/composables/usePaste.test.ts`:
- Around line 112-115: Replace the opaque "as unknown as LGraphNode" casts in
tests by returning a typed partial mock and casting that to LGraphNode; update
the helper createMockNode to build and return Partial<LGraphNode> and then use
vi.mocked(createNode).mockResolvedValue(createMockNode() as Partial<LGraphNode>
as LGraphNode) (or simply cast the helper's Partial to LGraphNode where used).
Locate uses around createMockNode and createNode in the test (including the
other occurrences at lines ~195-201) and switch them to the Partial<LGraphNode>
pattern so mocks are explicit and centralized.
- Around line 372-383: The cloneDataTransfer helper is adding files from both
.files and .items causing duplicate File entries; change cloneDataTransfer to
deduplicate by identity (e.g., track added files in a Set using a stable key
like file.name+file.size+file.type or track File objects with a WeakSet) before
appending to the cloned DataTransfer, and update the test in usePaste.test.ts to
assert exact counts (expect(cloned.files.length).toBe(2) and still assert the
two specific files are present).

In `@src/composables/usePaste.ts`:
- Around line 12-43: cloneDataTransfer currently adds files from both
original.files and original.items which can produce duplicates; deduplicate
file-kind entries before calling persistent.items.add. In cloneDataTransfer
collect files from original.files and those from original.items (via
item.getAsFile()), use a Set key (e.g., name + size + lastModified) or compare
File references to filter out duplicates, then add only unique files via
persistent.items.add; leave string data and properties
(dropEffect/effectAllowed) as-is.

In `@src/scripts/app.test.ts`:
- Around line 34-44: The helper createMockNode currently uses `any` and an
`unknown` cast which hides missing fields; change the function signature to
accept options: Partial<LGraphNode> (not any), merge defaults with the provided
options, and do a single explicit cast to LGraphNode on the returned object
(remove the intermediate unknown cast) so tests remain fully typed and adhere to
the repo's typing rules.
- Around line 46-52: The mock uses an unsafe "as any" for the graph; change
createMockCanvas to type the graph explicitly (e.g., use graph: Partial<LGraph>
or graph: Partial<NonNullable<LGraphCanvas['graph']>> ) so the mock implements
the expected shape rather than using any, and type graph.change as a vi.fn()
with the correct signature; update the return signature of createMockCanvas
accordingly so TypeScript infers the mock types for LGraphCanvas and its graph
instead of relying on any.
- Around line 119-124: The test fails because ComfyApp.handleFileList
dereferences fileList[0] without guarding empty lists; modify
ComfyApp.handleFileList to immediately return (no-op) when the incoming fileList
is empty (e.g., check fileList.length === 0 or !fileList || fileList.length ===
0) before any dereference, and ensure any downstream logic handles the
early-return case. Then update the test (calling app.handleFileList) to assert
that the promise resolves (e.g., not rejected or returns undefined) instead of
expecting a throw so the test verifies the new safe no-op behavior.

In `@src/scripts/app.ts`:
- Around line 1552-1568: In positionBatchNodes, avoid calling
this.canvas.graph?.change() inside the nodes.forEach loop; instead, compute and
set all node.pos values (including batchNode.pos already set) within the loop
and then invoke this.canvas.graph?.change() a single time after the loop
completes to improve performance for large drops.
- Around line 1527-1545: handleFileList currently assumes fileList[0] exists and
that all files are images; update it to first validate the FileList is non-empty
and contains only image/* entries, and if not show a localized toast (add the
new i18n key in src/locales/en/main.json) and return early. After calling
pasteImageNodes(this.canvas, fileList) check that imageNodes is non-empty before
creating/connecting the BatchImagesNode (createNode(..., 'BatchImagesNode')) and
before calling positionBatchNodes(imageNodes, batchImagesNode); if imageNodes is
empty, bail without creating the batch node. Ensure you reference the existing
functions handleFileList, pasteImageNodes, positionBatchNodes and createNode
when making changes.

In `@src/utils/__tests__/eventUtils.test.ts`:
- Around line 36-55: The test repeats type assertions for the result of
extractFileFromDragEvent; to simplify, assign the awaited result to a typed
variable (e.g., const files = await extractFileFromDragEvent(event) as FileList)
and use files.length and files[0]/files[1] in the assertions; update references
in this spec to use the new variable and keep FakeDragEvent and
extractFileFromDragEvent as the source identifiers to locate the code to change.

In `@src/utils/eventUtils.ts`:
- Line 29: Replace the arrow constant using the boxed Boolean with a plain
function declaration that returns the primitive boolean; specifically change the
const hasImageType = ({ type }: File): Boolean => type.startsWith('image'); to a
function declaration like function hasImageType(file: File): boolean { return
file.type.startsWith('image'); } (use the File parameter name `file`, reference
the hasImageType function/method name, and return primitive `boolean`).
- Around line 1-12: The helper hasImageType is currently declared as an arrow
returning a Boolean object and should be a function declaration returning a
primitive boolean; replace the existing arrow-expression version with a function
declaration named hasImageType that takes a File ({ type }: File) and returns
type.startsWith('image') as a boolean, so callers (including
extractFileFromDragEvent) follow coding guidelines and get the correct primitive
return type.

In `@src/utils/litegraphUtil.test.ts`:
- Around line 31-88: Tests use unsafe any/opaque casts (mockGraph: any, null as
any, as unknown as LGraphNode); update them to use Partial types and proper
typings: declare mockGraph as Partial<LGraph> and mockNode as
Partial<LGraphNode> (typed as LGraphNode when needed), remove or adjust the
`null as any` test (either drop it since empty string covers falsy guard or
update createNode signature to accept string | null | undefined), and ensure
vi.mocked(LiteGraph.createNode) returns the Partial mock correctly; also type
mockCanvas as Partial<LGraphCanvas> to avoid any casts and keep
useToastStore/mockAddAlert typed consistently.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/composables/usePaste.ts (1)

167-177: Consider aligning audio node creation with the new async pattern.

The audio node creation still uses LiteGraph.createNode() directly, while image nodes now use the new async createNode() utility. For consistency and to avoid race conditions mentioned in the PR objectives, consider updating this path in a follow-up.

🤖 Fix all issues with AI agents
In `@src/composables/usePaste.ts`:
- Around line 23-31: The comment above the loop incorrectly states items.add()
is idempotent; update it to accurately explain why duplicates are avoided: note
that we only iterate original.items (and only add file-kind entries) rather than
iterating both .files and .items, so duplicates are prevented by the iteration
strategy, not by items.add() itself; change the comment near the loop that
references items.add(), original.items, and persistent.items to reflect this
accurate behavior.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/composables/usePaste.ts (1)

165-176: Inconsistent node creation pattern for audio nodes.

Audio node creation still uses the synchronous LiteGraph.createNode pattern, while image handling now uses the async createNode utility. Per PR objectives, createNode was introduced to avoid race conditions with onNodeCreated callbacks. This inconsistency could lead to the same race conditions for audio paste operations.

♻️ Suggested refactor
       } else if (item.type.startsWith('audio/')) {
         if (!audioNode) {
           // No audio node selected: add a new one
-          const newNode = LiteGraph.createNode('LoadAudio')
-          if (newNode) {
-            newNode.pos = [canvas.graph_mouse[0], canvas.graph_mouse[1]]
-            audioNode = graph?.add(newNode) ?? null
-          }
-          graph?.change()
+          audioNode = await createNode(canvas as LGraphCanvas, 'LoadAudio')
         }
         pasteItemsOnNode(items, audioNode, 'audio')
         return
       }
🤖 Fix all issues with AI agents
In `@src/composables/usePaste.ts`:
- Around line 92-109: The pasteImageNodes function iterates all files but
doesn't validate they're images; update pasteImageNodes to skip non-image files
by checking each File's MIME (e.g., file.type.startsWith("image/")) before
creating a DataTransfer and calling pasteImageNode, and optionally fall back to
checking file.name extensions if file.type is empty; only call pasteImageNode
and push into nodes for files that pass this image check (reference
pasteImageNodes and pasteImageNode and the LoadImage node behavior).

@DrJKL DrJKL requested a review from AustinMroz January 23, 2026 23:15
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/scripts/app.test.ts`:
- Around line 38-48: The createMockNode helper currently types its options
parameter as Record<string, unknown>; change its signature to use
Partial<LGraphNode> for better type safety (function createMockNode(options:
Partial<LGraphNode> = {})). Update any related casts if needed (the final as
unknown as LGraphNode can remain) and ensure the spread of ...options onto the
returned object still compiles against LGraphNode members; this makes TypeScript
validate that provided mock fields match LGraphNode properties.
- Around line 258-275: Replace the unsafe "as unknown as ReturnType<typeof
useToastStore>" cast with a Partial-based stub for the toast store: create a
const toastStub: Partial<ReturnType<typeof useToastStore>> = { addAlert:
mockAddAlert } and pass that to vi.mocked(useToastStore).mockReturnValue (or
cast only the Partial to the exact return type in a single safe cast if the mock
API requires it); update the test around useToastStore and mockAddAlert to use
toastStub instead of the as unknown as pattern so the test uses a typed Partial
of useToastStore rather than an unsafe double-cast.
♻️ Duplicate comments (2)
src/scripts/app.ts (1)

1527-1545: Guard empty/mixed FileList drops before batching.

The existing concern from the previous review still applies: Line 1533 assumes fileList[0] exists and will throw on empty drops. Additionally, the MIME type check should use 'image/' (with trailing slash) for correctness, and imageNodes should be validated as non-empty before proceeding.

src/scripts/app.test.ts (1)

125-130: Test documents a bug rather than desired behavior.

This test expects a throw for empty file lists, which confirms the implementation bug flagged in handleFileList. Once the implementation is fixed to guard against empty lists, update this test to assert a successful no-op.

♻️ Suggested update once implementation is fixed
   it('should handle empty file list', async () => {
     const dataTransfer = new DataTransfer()

-    // The implementation doesn't check for empty list and will throw
-    await expect(app.handleFileList(dataTransfer.files)).rejects.toThrow()
+    // Empty file list should be a no-op
+    await expect(app.handleFileList(dataTransfer.files)).resolves.toBeUndefined()
   })

@github-actions
Copy link

github-actions bot commented Jan 24, 2026

Bundle Size Report

Summary

  • Raw size: 19.8 MB baseline 19.8 MB — 🔴 +2.29 kB
  • Gzip: 4.23 MB baseline 4.22 MB — 🔴 +683 B
  • Brotli: 3.28 MB baseline 3.28 MB — 🔴 +654 B
  • Bundles: 235 current • 235 baseline • 111 added / 111 removed

Category Glance
Data & Services 🔴 +2.29 kB (2.11 MB) · Vendor & Third-Party ⚪ 0 B (8.67 MB) · Other ⚪ 0 B (7.29 MB) · Graph Workspace ⚪ 0 B (872 kB) · Panels & Settings ⚪ 0 B (454 kB) · Utilities & Hooks ⚪ 0 B (237 kB) · + 5 more

Per-category breakdown
App Entry Points — 22 kB (baseline 22 kB) • ⚪ 0 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-BxAGDaou.js (new) 22 kB 🔴 +22 kB 🔴 +7.17 kB 🔴 +6.24 kB
assets/index-CzQxfJUH.js (removed) 22 kB 🟢 -22 kB 🟢 -7.18 kB 🟢 -6.23 kB

Status: 1 added / 1 removed

Graph Workspace — 872 kB (baseline 872 kB) • ⚪ 0 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-C1eNyuux.js (new) 872 kB 🔴 +872 kB 🔴 +188 kB 🔴 +143 kB
assets/GraphView-dtlpoNK9.js (removed) 872 kB 🟢 -872 kB 🟢 -188 kB 🟢 -143 kB

Status: 1 added / 1 removed

Views & Navigation — 68.8 kB (baseline 68.8 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-BYd_LDXH.js (removed) 15.4 kB 🟢 -15.4 kB 🟢 -3.31 kB 🟢 -2.81 kB
assets/CloudSurveyView-D5UNrDhz.js (new) 15.4 kB 🔴 +15.4 kB 🔴 +3.31 kB 🔴 +2.81 kB
assets/CloudLoginView-B8TT0Hvo.js (new) 10.1 kB 🔴 +10.1 kB 🔴 +2.94 kB 🔴 +2.58 kB
assets/CloudLoginView-Di6AQPXb.js (removed) 10.1 kB 🟢 -10.1 kB 🟢 -2.94 kB 🟢 -2.58 kB
assets/UserCheckView-BKbl_sMD.js (removed) 8.38 kB 🟢 -8.38 kB 🟢 -2.21 kB 🟢 -1.92 kB
assets/UserCheckView-DMVJzmiq.js (new) 8.38 kB 🔴 +8.38 kB 🔴 +2.21 kB 🔴 +1.92 kB
assets/CloudSignupView-CyNGKsDM.js (removed) 7.46 kB 🟢 -7.46 kB 🟢 -2.35 kB 🟢 -2.06 kB
assets/CloudSignupView-Dic8a0Sw.js (new) 7.46 kB 🔴 +7.46 kB 🔴 +2.35 kB 🔴 +2.06 kB
assets/CloudLayoutView-BdujVnZd.js (removed) 6.45 kB 🟢 -6.45 kB 🟢 -2.11 kB 🟢 -1.84 kB
assets/CloudLayoutView-CQFNmOR4.js (new) 6.45 kB 🔴 +6.45 kB 🔴 +2.12 kB 🔴 +1.83 kB
assets/CloudForgotPasswordView-6nfYCZCh.js (new) 5.57 kB 🔴 +5.57 kB 🔴 +1.95 kB 🔴 +1.73 kB
assets/CloudForgotPasswordView-DXHltd-3.js (removed) 5.57 kB 🟢 -5.57 kB 🟢 -1.94 kB 🟢 -1.75 kB
assets/CloudAuthTimeoutView-BFIyfmr6.js (removed) 4.92 kB 🟢 -4.92 kB 🟢 -1.78 kB 🟢 -1.56 kB
assets/CloudAuthTimeoutView-CPpHJFEd.js (new) 4.92 kB 🔴 +4.92 kB 🔴 +1.78 kB 🔴 +1.56 kB
assets/CloudSubscriptionRedirectView-CiHOWJG-.js (new) 4.72 kB 🔴 +4.72 kB 🔴 +1.79 kB 🔴 +1.58 kB
assets/CloudSubscriptionRedirectView-IaPHEx-k.js (removed) 4.72 kB 🟢 -4.72 kB 🟢 -1.79 kB 🟢 -1.58 kB
assets/UserSelectView-D_Cg1OwX.js (removed) 4.46 kB 🟢 -4.46 kB 🟢 -1.62 kB 🟢 -1.45 kB
assets/UserSelectView-oTET7Zbz.js (new) 4.46 kB 🔴 +4.46 kB 🔴 +1.62 kB 🔴 +1.45 kB
assets/CloudSorryContactSupportView-SQIXD_6I.js 1.02 kB 1.02 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/layout-DymeLvkK.js 296 B 296 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 9 added / 9 removed

Panels & Settings — 454 kB (baseline 454 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/WorkspacePanel-Cfpf9d7G.js (removed) 26.8 kB 🟢 -26.8 kB 🟢 -5.62 kB 🟢 -4.93 kB
assets/WorkspacePanel-CGm4OL7T.js (new) 26.8 kB 🔴 +26.8 kB 🔴 +5.62 kB 🔴 +4.93 kB
assets/SecretsPanel-BSSUyw2T.js (removed) 21.5 kB 🟢 -21.5 kB 🟢 -5.29 kB 🟢 -4.63 kB
assets/SecretsPanel-CEQDHbfN.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +5.29 kB 🔴 +4.65 kB
assets/LegacyCreditsPanel-CwZltpx_.js (new) 20.8 kB 🔴 +20.8 kB 🔴 +5.61 kB 🔴 +4.92 kB
assets/LegacyCreditsPanel-hlrEBd2q.js (removed) 20.8 kB 🟢 -20.8 kB 🟢 -5.61 kB 🟢 -4.94 kB
assets/SubscriptionPanel-B5vluxlh.js (new) 18.7 kB 🔴 +18.7 kB 🔴 +4.76 kB 🔴 +4.2 kB
assets/SubscriptionPanel-DH9Lpgrq.js (removed) 18.7 kB 🟢 -18.7 kB 🟢 -4.76 kB 🟢 -4.21 kB
assets/KeybindingPanel-KDmMWY_G.js (removed) 12.6 kB 🟢 -12.6 kB 🟢 -3.63 kB 🟢 -3.22 kB
assets/KeybindingPanel-LMh9qtQq.js (new) 12.6 kB 🔴 +12.6 kB 🔴 +3.63 kB 🔴 +3.22 kB
assets/ExtensionPanel-B_qb7VoK.js (removed) 9.51 kB 🟢 -9.51 kB 🟢 -2.7 kB 🟢 -2.4 kB
assets/ExtensionPanel-BGjTZ9zz.js (new) 9.51 kB 🔴 +9.51 kB 🔴 +2.69 kB 🔴 +2.39 kB
assets/AboutPanel-B1jlnSXR.js (removed) 8.62 kB 🟢 -8.62 kB 🟢 -2.45 kB 🟢 -2.22 kB
assets/AboutPanel-FEz5ErIj.js (new) 8.62 kB 🔴 +8.62 kB 🔴 +2.45 kB 🔴 +2.22 kB
assets/ServerConfigPanel-Br4925gD.js (removed) 6.65 kB 🟢 -6.65 kB 🟢 -2.16 kB 🟢 -1.95 kB
assets/ServerConfigPanel-CLlSVcr4.js (new) 6.65 kB 🔴 +6.65 kB 🔴 +2.16 kB 🔴 +1.95 kB
assets/UserPanel-9KS2i2Vb.js (removed) 6.29 kB 🟢 -6.29 kB 🟢 -2.03 kB 🟢 -1.78 kB
assets/UserPanel-b2e6W5XN.js (new) 6.29 kB 🔴 +6.29 kB 🔴 +2.03 kB 🔴 +1.78 kB
assets/cloudRemoteConfig-C0s0BOiO.js (removed) 1.45 kB 🟢 -1.45 kB 🟢 -715 B 🟢 -623 B
assets/cloudRemoteConfig-DUU7eZg8.js (new) 1.45 kB 🔴 +1.45 kB 🔴 +717 B 🔴 +621 B
assets/refreshRemoteConfig-MgtetMXS.js (new) 1.14 kB 🔴 +1.14 kB 🔴 +520 B 🔴 +458 B
assets/refreshRemoteConfig-vBubiobJ.js (removed) 1.14 kB 🟢 -1.14 kB 🟢 -520 B 🟢 -453 B
assets/config-DTkEo7Es.js 996 B 996 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-B9-DRLUq.js 33.3 kB 33.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BBhF1Ra7.js 23.9 kB 23.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BPmk7MJq.js 28 kB 28 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-C6ThYRJH.js 27.1 kB 27.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CDls4Tnk.js 29.2 kB 29.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CXVW-KKN.js 27.3 kB 27.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CZBqKC2c.js 28.1 kB 28.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CzQJLe5j.js 29.8 kB 29.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-IyjFFWib.js 31.6 kB 31.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-LLMHzl4C.js 37.6 kB 37.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-XT2QcP7J.js 23.3 kB 23.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 11 added / 11 removed

User & Accounts — 16 kB (baseline 16 kB) • ⚪ 0 B

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/auth-CsDiqPZu.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.18 kB 🟢 -991 B
assets/auth-XF7EC_PX.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.18 kB 🔴 +991 B
assets/SignUpForm-BEZE2Udt.js (removed) 3.01 kB 🟢 -3.01 kB 🟢 -1.23 kB 🟢 -1.09 kB
assets/SignUpForm-Cg_XmiU3.js (new) 3.01 kB 🔴 +3.01 kB 🔴 +1.23 kB 🔴 +1.09 kB
assets/UpdatePasswordContent-D38acb1a.js (removed) 2.38 kB 🟢 -2.38 kB 🟢 -1.08 kB 🟢 -959 B
assets/UpdatePasswordContent-MgMBk9kO.js (new) 2.38 kB 🔴 +2.38 kB 🔴 +1.08 kB 🔴 +953 B
assets/firebaseAuthStore-CM4s8yQg.js (removed) 803 B 🟢 -803 B 🟢 -398 B 🟢 -358 B
assets/firebaseAuthStore-DcXjvy49.js (new) 803 B 🔴 +803 B 🔴 +398 B 🔴 +360 B
assets/auth-CckuougE.js (new) 317 B 🔴 +317 B 🔴 +205 B 🔴 +198 B
assets/auth-Dtd5up2z.js (removed) 317 B 🟢 -317 B 🟢 -205 B 🟢 -177 B
assets/PasswordFields-Dz_bXydQ.js 4.51 kB 4.51 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WorkspaceProfilePic-D2K-asRs.js 1.57 kB 1.57 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 removed

Editors & Dialogs — 751 B (baseline 751 B) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useSubscriptionDialog--dl4kHAB.js (removed) 751 B 🟢 -751 B 🟢 -388 B 🟢 -337 B
assets/useSubscriptionDialog-B2KCDQTz.js (new) 751 B 🔴 +751 B 🔴 +386 B 🔴 +335 B

Status: 1 added / 1 removed

UI Components — 36.5 kB (baseline 36.5 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useTerminalTabs-BsW45xVR.js (new) 9.86 kB 🔴 +9.86 kB 🔴 +3.41 kB 🔴 +3 kB
assets/useTerminalTabs-D6tbIs2X.js (removed) 9.86 kB 🟢 -9.86 kB 🟢 -3.41 kB 🟢 -3 kB
assets/ComfyQueueButton-BmZ9ZurJ.js (new) 7.17 kB 🔴 +7.17 kB 🔴 +2.32 kB 🔴 +2.07 kB
assets/ComfyQueueButton-sreORMvU.js (removed) 7.17 kB 🟢 -7.17 kB 🟢 -2.32 kB 🟢 -2.07 kB
assets/SubscribeButton-G2cdKO0l.js (removed) 2.35 kB 🟢 -2.35 kB 🟢 -1.02 kB 🟢 -891 B
assets/SubscribeButton-Qp01MZEc.js (new) 2.35 kB 🔴 +2.35 kB 🔴 +1.02 kB 🔴 +890 B
assets/cloudFeedbackTopbarButton-D9F3MVFK.js (removed) 1.61 kB 🟢 -1.61 kB 🟢 -867 B 🟢 -765 B
assets/cloudFeedbackTopbarButton-OAJU5PNK.js (new) 1.61 kB 🔴 +1.61 kB 🔴 +868 B 🔴 +776 B
assets/ComfyQueueButton-DGjKvYJ1.js (new) 808 B 🔴 +808 B 🔴 +402 B 🔴 +362 B
assets/ComfyQueueButton-NSysi7SK.js (removed) 808 B 🟢 -808 B 🟢 -401 B 🟢 -358 B
assets/Button-DJ97zW2s.js 3 kB 3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudBadge-bwJLQpsu.js 1.24 kB 1.24 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/TopbarBadge-C7EnSn9A.js 7.45 kB 7.45 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserAvatar-ki0RgWjr.js 1.17 kB 1.17 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetButton-C5FBfFE1.js 1.84 kB 1.84 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 removed

Data & Services — 2.11 MB (baseline 2.1 MB) • 🔴 +2.29 kB

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-DEmJapgM.js (new) 1.33 MB 🔴 +1.33 MB 🔴 +299 kB 🔴 +231 kB
assets/dialogService-BKLYfLvp.js (removed) 1.33 MB 🟢 -1.33 MB 🟢 -298 kB 🟢 -231 kB
assets/api-B2-x4jgV.js (removed) 647 kB 🟢 -647 kB 🟢 -146 kB 🟢 -116 kB
assets/api-CeTUg4lE.js (new) 647 kB 🔴 +647 kB 🔴 +146 kB 🔴 +116 kB
assets/load3dService-BcfIUntx.js (removed) 91 kB 🟢 -91 kB 🟢 -19 kB 🟢 -16.4 kB
assets/load3dService-dXyPuowR.js (new) 91 kB 🔴 +91 kB 🔴 +19 kB 🔴 +16.4 kB
assets/systemStatsStore-DLcE4Q9J.js (removed) 12.2 kB 🟢 -12.2 kB 🟢 -4.26 kB 🟢 -3.74 kB
assets/systemStatsStore-DwQByGva.js (new) 12.2 kB 🔴 +12.2 kB 🔴 +4.26 kB 🔴 +3.74 kB
assets/releaseStore-CeQYXAlK.js (new) 7.96 kB 🔴 +7.96 kB 🔴 +2.22 kB 🔴 +1.95 kB
assets/releaseStore-DEcx0nt8.js (removed) 7.96 kB 🟢 -7.96 kB 🟢 -2.22 kB 🟢 -1.95 kB
assets/keybindingService-B1ysR_m3.js (removed) 6.57 kB 🟢 -6.57 kB 🟢 -1.72 kB 🟢 -1.49 kB
assets/keybindingService-DVnapNqg.js (new) 6.57 kB 🔴 +6.57 kB 🔴 +1.72 kB 🔴 +1.49 kB
assets/bootstrapStore-BKyDNEL6.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -874 B 🟢 -789 B
assets/bootstrapStore-DE3-Wsfe.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +873 B 🔴 +791 B
assets/userStore-CEXHTLg3.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +719 B 🔴 +676 B
assets/userStore-YTJ0Ebe5.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -720 B 🟢 -633 B
assets/audioService-B-clvGeZ.js (removed) 1.73 kB 🟢 -1.73 kB 🟢 -845 B 🟢 -724 B
assets/audioService-Cr9rWe-C.js (new) 1.73 kB 🔴 +1.73 kB 🔴 +844 B 🔴 +723 B
assets/releaseStore-BORvmOUO.js (new) 775 B 🔴 +775 B 🔴 +394 B 🔴 +349 B
assets/releaseStore-Ci3jGrRp.js (removed) 775 B 🟢 -775 B 🟢 -392 B 🟢 -344 B
assets/workflowDraftStore-DFeeNgbq.js (removed) 751 B 🟢 -751 B 🟢 -387 B 🟢 -340 B
assets/workflowDraftStore-EF0iwXO3.js (new) 751 B 🔴 +751 B 🔴 +386 B 🔴 +340 B
assets/dialogService-BhbxMw10.js (removed) 740 B 🟢 -740 B 🟢 -380 B 🟢 -337 B
assets/dialogService-BjTuE2kY.js (new) 740 B 🔴 +740 B 🔴 +375 B 🔴 +335 B
assets/dialogStore-SMYg02Jv.js 4.1 kB 4.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/serverConfigStore-De5AGM62.js 2.32 kB 2.32 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 12 added / 12 removed

Utilities & Hooks — 237 kB (baseline 237 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useConflictDetection-d6DonSGy.js (removed) 178 kB 🟢 -178 kB 🟢 -39.4 kB 🟢 -32.8 kB
assets/useConflictDetection-KsIOinP-.js (new) 178 kB 🔴 +178 kB 🔴 +39.4 kB 🔴 +32.9 kB
assets/useLoad3d-BbAGaspl.js (removed) 14.6 kB 🟢 -14.6 kB 🟢 -3.63 kB 🟢 -3.21 kB
assets/useLoad3d-KbXCaq8z.js (new) 14.6 kB 🔴 +14.6 kB 🔴 +3.63 kB 🔴 +3.21 kB
assets/useLoad3dViewer-C8h3GM1p.js (new) 14.1 kB 🔴 +14.1 kB 🔴 +3.15 kB 🔴 +2.8 kB
assets/useLoad3dViewer-DKBRm4zb.js (removed) 14.1 kB 🟢 -14.1 kB 🟢 -3.15 kB 🟢 -2.8 kB
assets/useFeatureFlags-D02SLL5g.js (removed) 3.32 kB 🟢 -3.32 kB 🟢 -1.04 kB 🟢 -898 B
assets/useFeatureFlags-DVKFQZNc.js (new) 3.32 kB 🔴 +3.32 kB 🔴 +1.04 kB 🔴 +898 B
assets/useWorkspaceUI-BazAhwjF.js (new) 3.21 kB 🔴 +3.21 kB 🔴 +898 B 🔴 +775 B
assets/useWorkspaceUI-DmYspgFp.js (removed) 3.21 kB 🟢 -3.21 kB 🟢 -898 B 🟢 -766 B
assets/useSubscriptionCredits-3U3L4dNq.js (new) 2.75 kB 🔴 +2.75 kB 🔴 +1.04 kB 🔴 +899 B
assets/useSubscriptionCredits-DJZcf7vG.js (removed) 2.75 kB 🟢 -2.75 kB 🟢 -1.04 kB 🟢 -900 B
assets/subscriptionCheckoutUtil-BpAEuQxU.js (removed) 2.53 kB 🟢 -2.53 kB 🟢 -1.06 kB 🟢 -955 B
assets/subscriptionCheckoutUtil-DdPZI8JW.js (new) 2.53 kB 🔴 +2.53 kB 🔴 +1.06 kB 🔴 +954 B
assets/useErrorHandling-BBWtB6Ly.js (new) 1.34 kB 🔴 +1.34 kB 🔴 +553 B 🔴 +507 B
assets/useErrorHandling-CWef3VZn.js (removed) 1.34 kB 🟢 -1.34 kB 🟢 -555 B 🟢 -503 B
assets/useLoad3d-CenXb53G.js (new) 874 B 🔴 +874 B 🔴 +433 B 🔴 +389 B
assets/useLoad3d-D_NXVDCB.js (removed) 874 B 🟢 -874 B 🟢 -432 B 🟢 -390 B
assets/audioUtils-C5ijqRVU.js (removed) 858 B 🟢 -858 B 🟢 -501 B 🟢 -405 B
assets/audioUtils-SlVQ7HTR.js (new) 858 B 🔴 +858 B 🔴 +501 B 🔴 +406 B
assets/useLoad3dViewer-CSnrlO2U.js (removed) 853 B 🟢 -853 B 🟢 -415 B 🟢 -376 B
assets/useLoad3dViewer-DejNdrgT.js (new) 853 B 🔴 +853 B 🔴 +419 B 🔴 +378 B
assets/useCurrentUser-B-ZYcOaw.js (removed) 737 B 🟢 -737 B 🟢 -382 B 🟢 -337 B
assets/useCurrentUser-D47cNOB8.js (new) 737 B 🔴 +737 B 🔴 +383 B 🔴 +337 B
assets/_plugin-vue_export-helper-BYZQdlgo.js 315 B 315 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/colorUtil-C8II5OEy.js 7 kB 7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/envUtil-DiXnWsaz.js 466 B 466 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/markdownRendererUtil-CULTZH1z.js 1.56 kB 1.56 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/networkUtil-BSvcILBc.js 1.05 kB 1.05 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SkeletonUtils-BputJAFn.js 133 B 133 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useCopyToClipboard-JE-7X_Eb.js 1.57 kB 1.57 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useExternalLink-CBYd7PkX.js 1.66 kB 1.66 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 12 added / 12 removed

Vendor & Third-Party — 8.67 MB (baseline 8.67 MB) • ⚪ 0 B

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-axios-C4mPrLmU.js 70.3 kB 70.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-chart-BxkFiWzp.js 399 kB 399 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-firebase-BvMr43CG.js 836 kB 836 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-i18n-BxsQv-KC.js 131 kB 131 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-markdown-kbZC6x-r.js 102 kB 102 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-other-LLCBDOBp.js 1.52 MB 1.52 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-B2JBnlqj.js 1.73 MB 1.73 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-reka-ui-C2SvlJE-.js 240 kB 240 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-sentry-SQwstEKc.js 182 kB 182 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-LBLOE6BD.js 1.8 MB 1.8 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-BSO55ms7.js 625 kB 625 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-core-BjA-tjXK.js 311 kB 311 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vueuse-Bg1iMAgF.js 111 kB 111 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-BGMLTxLX.js 374 kB 374 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-yjs-CBmk8HiD.js 143 kB 143 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-zod-DcCUUPIi.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Other — 7.29 MB (baseline 7.29 MB) • ⚪ 0 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/core-_Y0zy3Xu.js (new) 72.4 kB 🔴 +72.4 kB 🔴 +18.6 kB 🔴 +16 kB
assets/core-OyCdPJ8d.js (removed) 72.4 kB 🟢 -72.4 kB 🟢 -18.6 kB 🟢 -16 kB
assets/groupNode-CJ3gqXTQ.js (new) 72.1 kB 🔴 +72.1 kB 🔴 +17.8 kB 🔴 +15.6 kB
assets/groupNode-Cp05H04Q.js (removed) 72.1 kB 🟢 -72.1 kB 🟢 -17.7 kB 🟢 -15.6 kB
assets/WidgetSelect-BEwHYRj6.js (new) 57.5 kB 🔴 +57.5 kB 🔴 +12.2 kB 🔴 +10.5 kB
assets/WidgetSelect-D33WlMZh.js (removed) 57.5 kB 🟢 -57.5 kB 🟢 -12.2 kB 🟢 -10.5 kB
assets/SubscriptionRequiredDialogContentWorkspace-D1fKCfiY.js (removed) 46 kB 🟢 -46 kB 🟢 -8.59 kB 🟢 -7.46 kB
assets/SubscriptionRequiredDialogContentWorkspace-Yxjeffhv.js (new) 46 kB 🔴 +46 kB 🔴 +8.6 kB 🔴 +7.43 kB
assets/SettingDialogContent-CNR4hCic.js (new) 31.9 kB 🔴 +31.9 kB 🔴 +8.33 kB 🔴 +7.33 kB
assets/SettingDialogContent-DClP_agK.js (removed) 31.9 kB 🟢 -31.9 kB 🟢 -8.33 kB 🟢 -7.31 kB
assets/Load3DControls-BOP5sXVL.js (removed) 30.9 kB 🟢 -30.9 kB 🟢 -5.34 kB 🟢 -4.64 kB
assets/Load3DControls-Ci8Hw7dN.js (new) 30.9 kB 🔴 +30.9 kB 🔴 +5.34 kB 🔴 +4.65 kB
assets/SubscriptionRequiredDialogContent-BWzGN1Qq.js (removed) 26.2 kB 🟢 -26.2 kB 🟢 -6.59 kB 🟢 -5.8 kB
assets/SubscriptionRequiredDialogContent-D-k9MzEY.js (new) 26.2 kB 🔴 +26.2 kB 🔴 +6.59 kB 🔴 +5.8 kB
assets/Load3dViewerContent-4BbK4m95.js (removed) 23.1 kB 🟢 -23.1 kB 🟢 -5.19 kB 🟢 -4.5 kB
assets/Load3dViewerContent-CpyZXg5P.js (new) 23.1 kB 🔴 +23.1 kB 🔴 +5.19 kB 🔴 +4.5 kB
assets/WidgetImageCrop-CvEplZnd.js (removed) 22.3 kB 🟢 -22.3 kB 🟢 -5.52 kB 🟢 -4.85 kB
assets/WidgetImageCrop-kJDSGgoz.js (new) 22.3 kB 🔴 +22.3 kB 🔴 +5.52 kB 🔴 +4.85 kB
assets/SubscriptionPanelContentWorkspace-D2KqdyH4.js (new) 22 kB 🔴 +22 kB 🔴 +5.18 kB 🔴 +4.58 kB
assets/SubscriptionPanelContentWorkspace-S0ofl0CQ.js (removed) 22 kB 🟢 -22 kB 🟢 -5.19 kB 🟢 -4.58 kB
assets/CurrentUserPopoverWorkspace-D9BUmbsM.js (new) 20.6 kB 🔴 +20.6 kB 🔴 +5.08 kB 🔴 +4.52 kB
assets/CurrentUserPopoverWorkspace-DhfUsqO9.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -5.09 kB 🟢 -4.52 kB
assets/FormItem-DkRi91W6.js (removed) 20.2 kB 🟢 -20.2 kB 🟢 -4.86 kB 🟢 -4.26 kB
assets/FormItem-DNvW8neZ.js (new) 20.2 kB 🔴 +20.2 kB 🔴 +4.86 kB 🔴 +4.25 kB
assets/SignInContent-DJyPxBwq.js (new) 19 kB 🔴 +19 kB 🔴 +4.82 kB 🔴 +4.22 kB
assets/SignInContent-jrfbwO3y.js (removed) 19 kB 🟢 -19 kB 🟢 -4.82 kB 🟢 -4.22 kB
assets/WidgetRecordAudio-BUtxDjDh.js (removed) 17.3 kB 🟢 -17.3 kB 🟢 -4.95 kB 🟢 -4.43 kB
assets/WidgetRecordAudio-HeAThXR2.js (new) 17.3 kB 🔴 +17.3 kB 🔴 +4.95 kB 🔴 +4.44 kB
assets/MissingModelsWarning-C-j0w_JO.js (removed) 17.2 kB 🟢 -17.2 kB 🟢 -4.7 kB 🟢 -4.17 kB
assets/MissingModelsWarning-Cr-0y409.js (new) 17.2 kB 🔴 +17.2 kB 🔴 +4.7 kB 🔴 +4.17 kB
assets/Load3D-CqM2lwy9.js (removed) 16.2 kB 🟢 -16.2 kB 🟢 -4.04 kB 🟢 -3.53 kB
assets/Load3D-CxwsDPqc.js (new) 16.2 kB 🔴 +16.2 kB 🔴 +4.04 kB 🔴 +3.52 kB
assets/WidgetInputNumber-BAjZlzPl.js (removed) 15.8 kB 🟢 -15.8 kB 🟢 -4.26 kB 🟢 -3.8 kB
assets/WidgetInputNumber-CK6DF7xh.js (new) 15.8 kB 🔴 +15.8 kB 🔴 +4.26 kB 🔴 +3.8 kB
assets/load3d-ClbiDeqR.js (removed) 14.8 kB 🟢 -14.8 kB 🟢 -4.2 kB 🟢 -3.63 kB
assets/load3d-D9ooEN4y.js (new) 14.8 kB 🔴 +14.8 kB 🔴 +4.2 kB 🔴 +3.64 kB
assets/AudioPreviewPlayer-B3gALkJX.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -3.21 kB 🟢 -2.86 kB
assets/AudioPreviewPlayer-BwBZWqw8.js (new) 10.9 kB 🔴 +10.9 kB 🔴 +3.21 kB 🔴 +2.87 kB
assets/NodeConflictDialogContent-BDV3_p4Q.js (removed) 10.5 kB 🟢 -10.5 kB 🟢 -2.35 kB 🟢 -2.07 kB
assets/NodeConflictDialogContent-DdKcyuTv.js (new) 10.5 kB 🔴 +10.5 kB 🔴 +2.35 kB 🔴 +2.06 kB
assets/changeTracker-C-_DU7Kf.js (removed) 9.38 kB 🟢 -9.38 kB 🟢 -2.89 kB 🟢 -2.54 kB
assets/changeTracker-DLWI4Zxg.js (new) 9.38 kB 🔴 +9.38 kB 🔴 +2.89 kB 🔴 +2.55 kB
assets/nodeTemplates-CHY74qKn.js (new) 9.31 kB 🔴 +9.31 kB 🔴 +3.27 kB 🔴 +2.87 kB
assets/nodeTemplates-CKwvBB8I.js (removed) 9.31 kB 🟢 -9.31 kB 🟢 -3.27 kB 🟢 -2.87 kB
assets/InviteMemberDialogContent-5DyqAh9s.js (removed) 7.41 kB 🟢 -7.41 kB 🟢 -2.3 kB 🟢 -2.01 kB
assets/InviteMemberDialogContent-SHicyw_-.js (new) 7.41 kB 🔴 +7.41 kB 🔴 +2.3 kB 🔴 +2 kB
assets/WidgetWithControl-BJhfke4I.js (new) 7.04 kB 🔴 +7.04 kB 🔴 +2.64 kB 🔴 +2.34 kB
assets/WidgetWithControl-DAj1Lnkm.js (removed) 7.04 kB 🟢 -7.04 kB 🟢 -2.63 kB 🟢 -2.35 kB
assets/MissingNodesFooter-b1RPueH8.js (removed) 6.73 kB 🟢 -6.73 kB 🟢 -2.29 kB 🟢 -2.08 kB
assets/MissingNodesFooter-Bp5Ylq8u.js (new) 6.73 kB 🔴 +6.73 kB 🔴 +2.29 kB 🔴 +2.04 kB
assets/Load3DConfiguration-Ci2OsvpM.js (new) 6.27 kB 🔴 +6.27 kB 🔴 +1.91 kB 🔴 +1.68 kB
assets/Load3DConfiguration-Cv-5MS5J.js (removed) 6.27 kB 🟢 -6.27 kB 🟢 -1.91 kB 🟢 -1.67 kB
assets/MissingNodesContent-CIKbj5MP.js (removed) 6.15 kB 🟢 -6.15 kB 🟢 -2.09 kB 🟢 -1.86 kB
assets/MissingNodesContent-CMOjv99c.js (new) 6.15 kB 🔴 +6.15 kB 🔴 +2.09 kB 🔴 +1.86 kB
assets/CreateWorkspaceDialogContent-CBA08Eq0.js (removed) 5.55 kB 🟢 -5.55 kB 🟢 -2 kB 🟢 -1.74 kB
assets/CreateWorkspaceDialogContent-DHBj1-5S.js (new) 5.55 kB 🔴 +5.55 kB 🔴 +2 kB 🔴 +1.75 kB
assets/EditWorkspaceDialogContent-B5MaB_gY.js (new) 5.35 kB 🔴 +5.35 kB 🔴 +1.95 kB 🔴 +1.7 kB
assets/EditWorkspaceDialogContent-BOBGHqD3.js (removed) 5.35 kB 🟢 -5.35 kB 🟢 -1.96 kB 🟢 -1.7 kB
assets/ValueControlPopover-H6mMKHJN.js (new) 4.93 kB 🔴 +4.93 kB 🔴 +1.78 kB 🔴 +1.59 kB
assets/ValueControlPopover-rARE_bnZ.js (removed) 4.93 kB 🟢 -4.93 kB 🟢 -1.78 kB 🟢 -1.59 kB
assets/Preview3d-CimZvSYu.js (new) 4.83 kB 🔴 +4.83 kB 🔴 +1.58 kB 🔴 +1.38 kB
assets/Preview3d-ha0wT-2h.js (removed) 4.83 kB 🟢 -4.83 kB 🟢 -1.58 kB 🟢 -1.38 kB
assets/CancelSubscriptionDialogContent-CzGGCP3g.js (removed) 4.81 kB 🟢 -4.81 kB 🟢 -1.79 kB 🟢 -1.57 kB
assets/CancelSubscriptionDialogContent-DZHnXrzN.js (new) 4.81 kB 🔴 +4.81 kB 🔴 +1.79 kB 🔴 +1.57 kB
assets/DeleteWorkspaceDialogContent-C1kLhbCO.js (new) 4.25 kB 🔴 +4.25 kB 🔴 +1.64 kB 🔴 +1.43 kB
assets/DeleteWorkspaceDialogContent-D0HyzoQu.js (removed) 4.25 kB 🟢 -4.25 kB 🟢 -1.64 kB 🟢 -1.43 kB
assets/LeaveWorkspaceDialogContent-656gibGX.js (new) 4.08 kB 🔴 +4.08 kB 🔴 +1.59 kB 🔴 +1.38 kB
assets/LeaveWorkspaceDialogContent-DzSYsu8r.js (removed) 4.08 kB 🟢 -4.08 kB 🟢 -1.58 kB 🟢 -1.38 kB
assets/RemoveMemberDialogContent-C7UtbkA7.js (removed) 4.06 kB 🟢 -4.06 kB 🟢 -1.53 kB 🟢 -1.34 kB
assets/RemoveMemberDialogContent-COQMqpGi.js (new) 4.06 kB 🔴 +4.06 kB 🔴 +1.54 kB 🔴 +1.34 kB
assets/RevokeInviteDialogContent-DFRod1qv.js (removed) 3.98 kB 🟢 -3.98 kB 🟢 -1.55 kB 🟢 -1.36 kB
assets/RevokeInviteDialogContent-DGvB14M7.js (new) 3.98 kB 🔴 +3.98 kB 🔴 +1.55 kB 🔴 +1.36 kB
assets/saveMesh-C0NFcf8v.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.47 kB 🔴 +1.31 kB
assets/saveMesh-CFgGsQnj.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.47 kB 🟢 -1.3 kB
assets/cloudSessionCookie-CjablQoZ.js (removed) 3.12 kB 🟢 -3.12 kB 🟢 -1.1 kB 🟢 -953 B
assets/cloudSessionCookie-CuMw76E4.js (new) 3.12 kB 🔴 +3.12 kB 🔴 +1.1 kB 🔴 +998 B
assets/GlobalToast-BPFh2wLE.js (new) 2.91 kB 🔴 +2.91 kB 🔴 +1.21 kB 🔴 +1.03 kB
assets/GlobalToast-V2JBg-Wl.js (removed) 2.91 kB 🟢 -2.91 kB 🟢 -1.21 kB 🟢 -1.03 kB
assets/SubscribeToRun-BHKhf-Ul.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +1.01 kB 🔴 +891 B
assets/SubscribeToRun-CfEKvqK5.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -1.01 kB 🟢 -894 B
assets/SettingDialogHeader-BhNb9hyI.js (new) 1.8 kB 🔴 +1.8 kB 🔴 +894 B 🔴 +806 B
assets/SettingDialogHeader-DJDrQHoH.js (removed) 1.8 kB 🟢 -1.8 kB 🟢 -893 B 🟢 -805 B
assets/CloudRunButtonWrapper-CktmLp69.js (new) 1.69 kB 🔴 +1.69 kB 🔴 +795 B 🔴 +729 B
assets/CloudRunButtonWrapper-DV5VpB6Z.js (removed) 1.69 kB 🟢 -1.69 kB 🟢 -796 B 🟢 -731 B
assets/cloudBadges-BOFnQmxL.js (removed) 1.38 kB 🟢 -1.38 kB 🟢 -716 B 🟢 -622 B
assets/cloudBadges-BUST_Lew.js (new) 1.38 kB 🔴 +1.38 kB 🔴 +716 B 🔴 +621 B
assets/cloudSubscription-BnUvmzVv.js (removed) 1.34 kB 🟢 -1.34 kB 🟢 -669 B 🟢 -578 B
assets/cloudSubscription-D9C8Spi6.js (new) 1.34 kB 🔴 +1.34 kB 🔴 +670 B 🔴 +576 B
assets/Load3D-BTyb2c0V.js (new) 1.09 kB 🔴 +1.09 kB 🔴 +509 B 🔴 +452 B
assets/Load3D-CgW_SRzj.js (removed) 1.09 kB 🟢 -1.09 kB 🟢 -506 B 🟢 -452 B
assets/nightlyBadges-BQFcOT-V.js (new) 1.02 kB 🔴 +1.02 kB 🔴 +543 B 🔴 +481 B
assets/nightlyBadges-DX75FzDJ.js (removed) 1.02 kB 🟢 -1.02 kB 🟢 -544 B 🟢 -480 B
assets/Load3dViewerContent-AXYF1Y8R.js (new) 1.01 kB 🔴 +1.01 kB 🔴 +479 B 🔴 +430 B
assets/Load3dViewerContent-CLjvQ1hz.js (removed) 1.01 kB 🟢 -1.01 kB 🟢 -477 B 🟢 -420 B
assets/SubscriptionPanelContentWorkspace-BI5pAszY.js (removed) 945 B 🟢 -945 B 🟢 -443 B 🟢 -389 B
assets/SubscriptionPanelContentWorkspace-CaHr_VFi.js (new) 945 B 🔴 +945 B 🔴 +448 B 🔴 +391 B
assets/SettingDialogContent-D9rYOD33.js (new) 887 B 🔴 +887 B 🔴 +431 B 🔴 +381 B
assets/SettingDialogContent-XB4cSKrg.js (removed) 887 B 🟢 -887 B 🟢 -430 B 🟢 -379 B
assets/changeTracker-CbraHWQr.js (new) 772 B 🔴 +772 B 🔴 +394 B 🔴 +345 B
assets/changeTracker-DByerB9u.js (removed) 772 B 🟢 -772 B 🟢 -393 B 🟢 -345 B
assets/graphHasMissingNodes--Me-MKsF.js (new) 761 B 🔴 +761 B 🔴 +371 B 🔴 +315 B
assets/graphHasMissingNodes-NBvLNSe1.js (removed) 761 B 🟢 -761 B 🟢 -372 B 🟢 -321 B
assets/WidgetLegacy-DZq0IAQ0.js (new) 760 B 🔴 +760 B 🔴 +393 B 🔴 +343 B
assets/WidgetLegacy-STkzivH6.js (removed) 760 B 🟢 -760 B 🟢 -393 B 🟢 -343 B
assets/WidgetInputNumber-2-ol0G2F.js (removed) 392 B 🟢 -392 B 🟢 -231 B 🟢 -212 B
assets/WidgetInputNumber-YNesxzKK.js (new) 392 B 🔴 +392 B 🔴 +231 B 🔴 +212 B
assets/SettingDialogHeader-BrL99orv.js (new) 345 B 🔴 +345 B 🔴 +209 B 🔴 +188 B
assets/SettingDialogHeader-Dgk6s9Fx.js (removed) 345 B 🟢 -345 B 🟢 -206 B 🟢 -187 B
assets/AnimationControls-BsWySN5_.js 4.61 kB 4.61 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ApiNodesSignInContent-DTyiF6u-.js 2.69 kB 2.69 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/auto-BTnZwrs2.js 1.7 kB 1.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/BaseViewTemplate-BhZHTUKb.js 1.78 kB 1.78 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/comfy-logo-single-CzGozBag.js 198 B 198 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ComfyOrgHeader-Gbby8E71.js 910 B 910 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BaWekgk-.js 14.7 kB 14.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BDDnqSnY.js 15.8 kB 15.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BoYLZfP6.js 15.7 kB 15.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BQBGh0Ya.js 15.5 kB 15.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BRoxhQgK.js 15.8 kB 15.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-C_sqX4RY.js 14.9 kB 14.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Cd2uuEbd.js 17.1 kB 17.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CXPUqoOz.js 16.6 kB 16.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-ijoJFfEv.js 16.3 kB 16.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-UTYbUnOi.js 17.2 kB 17.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-YFdvkJDc.js 18.4 kB 18.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/constants-BQ60oUwg.js 579 B 579 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/i18n-BBmGB05k.js 492 kB 492 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/i18n-BT4gcSgP.js 199 B 199 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ImportFailedNodeContent-CuQpbxoK.js 2.48 kB 2.48 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ImportFailedNodeFooter-BVBaLbVz.js 1.88 kB 1.88 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ImportFailedNodeHeader-C5wjxnXc.js 1.08 kB 1.08 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/LazyImage-V1y3sy9h.js 12.3 kB 12.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Bk7Ph3VS.js 140 kB 140 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BsU_fTOy.js 118 kB 118 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BYY1tCjz.js 153 kB 153 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BzI-1UKY.js 117 kB 117 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-ciwZVtD5.js 133 kB 133 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CjTKnSQT.js 135 kB 135 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-ClVfAHiD.js 185 kB 185 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DtZZaQoT.js 137 kB 137 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DY5snELF.js 160 kB 160 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Q_yKaq1U.js 166 kB 166 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-XVEzvvBB.js 132 kB 132 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Media3DTop-5HQboIyx.js 1.82 kB 1.82 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-Di0bN8lA.js 1.43 kB 1.43 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-ByvcQ9C2.js 1.75 kB 1.75 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-D1667gDz.js 2.23 kB 2.23 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MissingNodesHeader-BAZcszup.js 1.09 kB 1.09 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/NodeConflictFooter-C7WLy5Sh.js 2.37 kB 2.37 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/NodeConflictHeader-CQeNaRiZ.js 1.09 kB 1.09 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BbE7kmki.js 413 kB 413 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-C4Vr6-Ih.js 367 kB 367 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CeGNv9ZW.js 450 kB 450 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CgbjMWnR.js 360 kB 360 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Cj0eoGwS.js 371 kB 371 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CjZ27bLt.js 412 kB 412 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CPZbmaZd.js 367 kB 367 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Cz-81naW.js 335 kB 335 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DknKGYI5.js 364 kB 364 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-elNKIbDk.js 381 kB 381 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-VAK4vMLf.js 338 kB 338 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/OBJLoader2WorkerModule-DTMpvldF.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/PanelTemplate-B9lPSLJe.js 1.2 kB 1.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/previousFullPath-B7BRzEeG.js 665 B 665 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/rolldown-runtime-DLICfi3-.js 1.97 kB 1.97 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SelectValue-DBHUo1Qx.js 8.94 kB 8.94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/signInSchema-Bqlb_LYM.js 1.53 kB 1.53 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Slider-eqGfZlVo.js 3.52 kB 3.52 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/src-C3JCjcCo.js 251 B 251 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/telemetry-Db2yG1o2.js 226 B 226 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/types-DT3N7am7.js 204 B 204 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widget-BhHc6T04.js 445 B 445 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-05_iDuzU.js 131 B 131 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-JezhrbLj.js 3.91 kB 3.91 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-BlGCEirp.js 2.21 kB 2.21 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetColorPicker-B6bpqk2C.js 2.9 kB 2.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetGalleria-BTV9zowW.js 3.61 kB 3.61 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-DTyqdFue.js 3.1 kB 3.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetInputText-DN2pTx0v.js 1.86 kB 1.86 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetLayoutField-1P4YwNzh.js 1.95 kB 1.95 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetMarkdown-DaTQe8EX.js 2.88 kB 2.88 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-C6ZYch5M.js 1.1 kB 1.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetTextarea-BGDTDBYo.js 3.14 kB 3.14 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetToggleSwitch-TeVzKTow.js 2.5 kB 2.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetTypes-Cp8f93Pk.js 393 B 393 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 54 added / 54 removed

for (const item of items) {
if (item.type.startsWith('image/')) {
pasteImageNode(canvas as LGraphCanvas, items, imageNode)
await pasteImageNode(canvas as LGraphCanvas, items, imageNode)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I know it's not introduced here, but can we clean up the type assertion?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was planning on cleaning up all the type assertion when I got to the audio/video story as it's the last drag and drop / copy & paste task. Unless there is some other type beyond that I should add to that task. I already have another task waiting with the text drag/drop/copy/paste

batchNode.pos = [ x + width + 100, y + 30 ]

// Retrieving Node Height is inconsistent
let height = nodeHeight;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see where the difficulty comes from...

Node image previews is some super mucky code. useLitegraphService().updatePreview has an optional callback modifier that's triggered after the preview image finishes loading, but it's mostly intended for use inside subgraphs and wouldn't be reliable enough to use here.

For litegraph, image previews have a fixed height and you can calc the positions in advance
My personal recommendation would be to always use 344 for height and skip the measurement entirely. This would also allow you to set the node position prior to node creation.

Nodes 2.0 makes things a good bit more difficult.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AustinMroz Updated to use just the fixed height. Sorry about the delay. I saw an approval and assumed I was done.

DrJKL
DrJKL previously approved these changes Jan 24, 2026
@DrJKL DrJKL assigned AustinMroz and unassigned DrJKL Jan 24, 2026
@DrJKL DrJKL self-requested a review January 31, 2026 00:15
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/utils/litegraphUtil.ts`:
- Around line 51-55: The code calls graph.change() even when graph.add(newNode)
may return undefined; modify the logic in the block handling newNode to capture
the result of graph.add via the variable addedNode, check if addedNode is falsy,
and if so show an alert (e.g., alert("Failed to add node")) and return null
without calling graph.change(); only call graph.change() and return addedNode
when addedNode is truthy. Ensure you reference newNode, graph.add, addedNode and
graph.change in the updated flow so the add-failure path is handled cleanly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/scripts/app.ts`:
- Around line 1463-1464: createNode returns Promise<LGraphNode | null> but
imageNode is used unguarded; add a null-check after awaiting createNode in the
block that calls pasteImageNode to bail out or handle the error when imageNode
is null. Specifically, after const imageNode = await createNode(this.canvas,
'LoadImage') verify imageNode !== null (or throw/log and return) before calling
pasteImageNode(this.canvas, transfer.items, imageNode) so pasteImageNode never
receives a null node.
- Around line 1568-1576: positionBatchNodes currently assumes nodes is non-empty
and uses a hardcoded height for LoadImage; update it to first guard against an
empty nodes array (return early or no-op if nodes.length === 0) and then compute
node height dynamically instead of the magic 344: for example read
nodes[0].size[1] or call nodes[0].computeSize()[1] (fallback to a sensible
default if those are undefined) and use that value when positioning batchNode;
references: positionBatchNodes, nodes, batchNode, and the 'LoadImage' node type.

AustinMroz
AustinMroz previously approved these changes Feb 6, 2026
Copy link
Collaborator

@AustinMroz AustinMroz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must thoroughly apologize. I want to give feedback that is both directed and helpful. That I struggle with doing so has placed unfair burden on you.
The quality of the code looks sufficient to me, and I will give approval as such.

However there's a lot litegraph specific quirks at play here that I could not expect others to either be aware of or to work on fixes for.

  • Positioning of nodes in vue mode after initialization is not currently functional. #7591 was recently reverted in #8619
    • This means that the current arrangement process causes nodes to stack up on the origin point.
    • I've been working on a way to clean this up for a while now, but in the meantime, the safe way to position a newly created node is to pass the desired position for the node as an option for node creation
      • The newly introduced createNode does not include a way to pass such additional options.
    • Vue nodes currently scale height proportionally to the aspect ratio of the contained image preview. This makes programatically determining the height prior to adding nodes to the graph impossible.
      • This has caused frustration in other places as well. I've opened a separate PR to fix this, so no action is required here: #8702
  • I am conflicted about the addition of a new node creation function. I should have directed you towards litegraphService:addNodeOnGraph, but became a little too caught up in the addressing the pertinent technical complications.
  • app.ts is an old part of the code base. While the code changes to it are fine, introducing an app.test.ts feels a little misleading when its only being used to test drag and drop functionality. Perhaps a more targeted app.dropHandler.test.ts would be more appropriate.

# Conflicts:
#	src/lib/litegraph/src/LGraph.ts
@AustinMroz AustinMroz merged commit a80f6d7 into Comfy-Org:main Feb 12, 2026
27 of 28 checks passed
pythongosssss added a commit that referenced this pull request Feb 12, 2026
Resolve conflicts between batch image drag-and-drop (#8282) and
multi-file workflow import. When all dropped files are images,
handleFileList creates a BatchImagesNode; otherwise each file is
loaded as a workflow with deferred warnings.

- Unify extractFilesFromDragEvent to always return File[]
- Update pasteImageNodes/handleFileList to accept File[]
- Fix tests for new File[] return type
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants