From aa8bdde4f106561f3f66321224235a103464e3f6 Mon Sep 17 00:00:00 2001 From: Austin Mroz Date: Wed, 12 Nov 2025 12:38:00 -0800 Subject: [PATCH 1/8] Initial linear mode implementation --- .../LiteGraphCanvasSplitterOverlay.vue | 4 +- src/views/GraphView.vue | 5 ++ src/views/LinearView.vue | 70 +++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/views/LinearView.vue diff --git a/src/components/LiteGraphCanvasSplitterOverlay.vue b/src/components/LiteGraphCanvasSplitterOverlay.vue index 1bb9e89c75..eddcea1afb 100644 --- a/src/components/LiteGraphCanvasSplitterOverlay.vue +++ b/src/components/LiteGraphCanvasSplitterOverlay.vue @@ -21,7 +21,6 @@ state-storage="local" > + @@ -64,7 +64,6 @@ + diff --git a/src/views/GraphView.vue b/src/views/GraphView.vue index b7ffa19e14..7ead4f609a 100644 --- a/src/views/GraphView.vue +++ b/src/views/GraphView.vue @@ -5,12 +5,14 @@
+
@@ -76,6 +78,7 @@ import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore' import { useSidebarTabStore } from '@/stores/workspace/sidebarTabStore' import { useWorkspaceStore } from '@/stores/workspaceStore' import { electronAPI, isElectron } from '@/utils/envUtil' +import LinearView from '@/views/LinearView.vue' setupAutoQueueHandler() useProgressFavicon() @@ -93,6 +96,8 @@ const queueStore = useQueueStore() const assetsStore = useAssetsStore() const versionCompatibilityStore = useVersionCompatibilityStore() const graphCanvasContainerRef = ref(null) +//@ts-expect-error temporary duck violence +const linearMode = (app.linearMode = ref(false)) const telemetry = useTelemetry() const firebaseAuthStore = useFirebaseAuthStore() diff --git a/src/views/LinearView.vue b/src/views/LinearView.vue new file mode 100644 index 0000000000..c1e4c5ec07 --- /dev/null +++ b/src/views/LinearView.vue @@ -0,0 +1,70 @@ + + From 1bbfafdc8ad938631d8a1b42f2e78371893f491b Mon Sep 17 00:00:00 2001 From: Austin Mroz Date: Wed, 12 Nov 2025 20:09:53 -0800 Subject: [PATCH 2/8] Preview interleaving, add keybind --- src/composables/useCoreCommands.ts | 7 +++++++ src/stores/imagePreviewStore.ts | 12 +++++++++++- src/views/LinearView.vue | 18 +++++++----------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/composables/useCoreCommands.ts b/src/composables/useCoreCommands.ts index f691ff7f1e..8d55801200 100644 --- a/src/composables/useCoreCommands.ts +++ b/src/composables/useCoreCommands.ts @@ -1220,6 +1220,13 @@ export function useCoreCommands(): ComfyCommand[] { await settingStore.set('Comfy.Assets.UseAssetAPI', !current) await useWorkflowService().reloadCurrentWorkflow() // ensure changes take effect immediately } + }, + { + id: 'Comfy.ToggleLinear', + icon: 'pi pi-database', + label: 'toggle linear mode', + //@ts-expect-error temporary duck violence + function: () => (app.linearMode.value = !app.linearMode.value) } ] diff --git a/src/stores/imagePreviewStore.ts b/src/stores/imagePreviewStore.ts index 300c532c97..ee8ae759bd 100644 --- a/src/stores/imagePreviewStore.ts +++ b/src/stores/imagePreviewStore.ts @@ -40,6 +40,7 @@ export const useNodeOutputStore = defineStore('nodeOutput', () => { const { nodeIdToNodeLocatorId, nodeToNodeLocatorId } = useWorkflowStore() const { executionIdToNodeLocatorId } = useExecutionStore() const scheduledRevoke: Record void }> = {} + const latestOutput = ref([]) function scheduleRevoke(locator: NodeLocatorId, cb: () => void) { scheduledRevoke[locator]?.stop() @@ -146,6 +147,13 @@ export const useNodeOutputStore = defineStore('nodeOutput', () => { } } + //TODO:Preview params and deduplication + latestOutput.value = + (outputs as ExecutedWsMessage['output'])?.images?.map((image) => { + const imgUrlPart = new URLSearchParams(image) + const rand = app.getRandParam() + return api.apiURL(`/view?${imgUrlPart}${rand}`) + }) ?? [] app.nodeOutputs[nodeLocatorId] = outputs nodeOutputs.value[nodeLocatorId] = outputs } @@ -213,6 +221,7 @@ export const useNodeOutputStore = defineStore('nodeOutput', () => { scheduledRevoke[nodeLocatorId].stop() delete scheduledRevoke[nodeLocatorId] } + latestOutput.value = previewImages app.nodePreviewImages[nodeLocatorId] = previewImages nodePreviewImages.value[nodeLocatorId] = previewImages } @@ -381,6 +390,7 @@ export const useNodeOutputStore = defineStore('nodeOutput', () => { // State nodeOutputs, - nodePreviewImages + nodePreviewImages, + latestOutput } }) diff --git a/src/views/LinearView.vue b/src/views/LinearView.vue index c1e4c5ec07..a2e18a50f1 100644 --- a/src/views/LinearView.vue +++ b/src/views/LinearView.vue @@ -1,16 +1,19 @@