From df85c4d463d3ad8c7399556b4c0c8722369461e7 Mon Sep 17 00:00:00 2001 From: Jin Yi Date: Fri, 23 Jan 2026 13:49:33 +0900 Subject: [PATCH 01/92] [refactor] Move ActiveJobCard to platform/assets and add ActiveMediaAssetCard story (#8242) --- .../sidebar/tabs/AssetsSidebarGridView.vue | 8 +- .../ActiveMediaAssetCard.stories.ts | 143 ++++++++++++++++++ .../components/ActiveMediaAssetCard.test.ts} | 2 +- .../components/ActiveMediaAssetCard.vue} | 0 4 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 src/platform/assets/components/ActiveMediaAssetCard.stories.ts rename src/{components/sidebar/tabs/assets/ActiveJobCard.test.ts => platform/assets/components/ActiveMediaAssetCard.test.ts} (98%) rename src/{components/sidebar/tabs/assets/ActiveJobCard.vue => platform/assets/components/ActiveMediaAssetCard.vue} (100%) diff --git a/src/components/sidebar/tabs/AssetsSidebarGridView.vue b/src/components/sidebar/tabs/AssetsSidebarGridView.vue index ac0bfcf39..f57f0b1f8 100644 --- a/src/components/sidebar/tabs/AssetsSidebarGridView.vue +++ b/src/components/sidebar/tabs/AssetsSidebarGridView.vue @@ -6,7 +6,11 @@ class="grid max-h-[50%] scrollbar-custom overflow-y-auto" :style="gridStyle" > - + @@ -55,7 +59,7 @@ import { computed } from 'vue' import { useI18n } from 'vue-i18n' import VirtualGrid from '@/components/common/VirtualGrid.vue' -import ActiveJobCard from '@/components/sidebar/tabs/assets/ActiveJobCard.vue' +import ActiveMediaAssetCard from '@/platform/assets/components/ActiveMediaAssetCard.vue' import { useJobList } from '@/composables/queue/useJobList' import MediaAssetCard from '@/platform/assets/components/MediaAssetCard.vue' import type { AssetItem } from '@/platform/assets/schemas/assetSchema' diff --git a/src/platform/assets/components/ActiveMediaAssetCard.stories.ts b/src/platform/assets/components/ActiveMediaAssetCard.stories.ts new file mode 100644 index 000000000..1e32e96b2 --- /dev/null +++ b/src/platform/assets/components/ActiveMediaAssetCard.stories.ts @@ -0,0 +1,143 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import type { JobListItem } from '@/composables/queue/useJobList' + +import ActiveMediaAssetCard from './ActiveMediaAssetCard.vue' + +const meta: Meta = { + title: 'Platform/Assets/ActiveMediaAssetCard', + component: ActiveMediaAssetCard +} + +export default meta +type Story = StoryObj + +const SAMPLE_PREVIEW = + 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg' + +function createJob(overrides: Partial = {}): JobListItem { + return { + id: 'job-1', + title: 'Running...', + meta: 'Step 5/10', + state: 'running', + progressTotalPercent: 50, + progressCurrentPercent: 75, + ...overrides + } +} + +export const Running: Story = { + decorators: [ + () => ({ + template: '
' + }) + ], + args: { + job: createJob({ + state: 'running', + progressTotalPercent: 65, + iconImageUrl: SAMPLE_PREVIEW + }) + } +} + +export const RunningWithoutPreview: Story = { + decorators: [ + () => ({ + template: '
' + }) + ], + args: { + job: createJob({ + state: 'running', + progressTotalPercent: 30 + }) + } +} + +export const Pending: Story = { + decorators: [ + () => ({ + template: '
' + }) + ], + args: { + job: createJob({ + state: 'pending', + title: 'In queue...', + progressTotalPercent: undefined + }) + } +} + +export const Initialization: Story = { + decorators: [ + () => ({ + template: '
' + }) + ], + args: { + job: createJob({ + state: 'initialization', + title: 'Initializing...', + progressTotalPercent: undefined + }) + } +} + +export const Failed: Story = { + decorators: [ + () => ({ + template: '
' + }) + ], + args: { + job: createJob({ + state: 'failed', + title: 'Failed' + }) + } +} + +export const GridLayout: Story = { + render: () => ({ + components: { ActiveMediaAssetCard }, + setup() { + const jobs: JobListItem[] = [ + createJob({ + id: 'job-1', + state: 'running', + progressTotalPercent: 75, + iconImageUrl: SAMPLE_PREVIEW + }), + createJob({ + id: 'job-2', + state: 'running', + progressTotalPercent: 45 + }), + createJob({ + id: 'job-3', + state: 'pending', + title: 'In queue...', + progressTotalPercent: undefined + }), + createJob({ + id: 'job-4', + state: 'failed', + title: 'Failed' + }) + ] + return { jobs } + }, + template: ` +
+ +
+ ` + }) +} diff --git a/src/components/sidebar/tabs/assets/ActiveJobCard.test.ts b/src/platform/assets/components/ActiveMediaAssetCard.test.ts similarity index 98% rename from src/components/sidebar/tabs/assets/ActiveJobCard.test.ts rename to src/platform/assets/components/ActiveMediaAssetCard.test.ts index 59846bb5e..c653ae0be 100644 --- a/src/components/sidebar/tabs/assets/ActiveJobCard.test.ts +++ b/src/platform/assets/components/ActiveMediaAssetCard.test.ts @@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils' import { describe, expect, it, vi } from 'vitest' import { createI18n } from 'vue-i18n' -import ActiveJobCard from './ActiveJobCard.vue' +import ActiveJobCard from './ActiveMediaAssetCard.vue' import type { JobListItem } from '@/composables/queue/useJobList' diff --git a/src/components/sidebar/tabs/assets/ActiveJobCard.vue b/src/platform/assets/components/ActiveMediaAssetCard.vue similarity index 100% rename from src/components/sidebar/tabs/assets/ActiveJobCard.vue rename to src/platform/assets/components/ActiveMediaAssetCard.vue From 7952eb477e67e4b0402d51d33ef05a346775d965 Mon Sep 17 00:00:00 2001 From: AustinMroz Date: Thu, 22 Jan 2026 21:28:41 -0800 Subject: [PATCH 02/92] Add telemetry for entering linear mode (#8263) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Standard disclaimer: Telemetry only applies on cloud builds ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8263-Add-telemetry-for-entering-linear-mode-2f16d73d3650819ea53efeeb562ea095) by [Unito](https://www.unito.io) --- src/components/sidebar/ModeToggle.vue | 9 +++++++-- src/composables/useCoreCommands.ts | 5 ++++- .../providers/cloud/MixpanelTelemetryProvider.ts | 5 +++++ src/platform/telemetry/types.ts | 7 +++++++ src/platform/workflow/core/services/workflowService.ts | 6 +++++- 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/components/sidebar/ModeToggle.vue b/src/components/sidebar/ModeToggle.vue index ca94be771..1d909f4cd 100644 --- a/src/components/sidebar/ModeToggle.vue +++ b/src/components/sidebar/ModeToggle.vue @@ -5,6 +5,11 @@ import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { useCommandStore } from '@/stores/commandStore' const canvasStore = useCanvasStore() +function toggleLinearMode() { + useCommandStore().execute('Comfy.ToggleLinear', { + metadata: { source: 'button' } + }) +} -
+
+ Loading ComfyUI... + +
From bcb4d6e403ca5ed37892e9023eef9b8147b1f06a Mon Sep 17 00:00:00 2001 From: Alexander Brown Date: Tue, 27 Jan 2026 14:04:35 -0800 Subject: [PATCH 45/92] fix: await needsLogin (#8340) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Add additional protection for bootstrap order issues. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8340-fix-await-needsLogin-2f56d73d365081c9b3c6d5a091c1eb8d) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp --- src/stores/bootstrapStore.test.ts | 4 +++- src/stores/bootstrapStore.ts | 25 +++++++++++++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/stores/bootstrapStore.test.ts b/src/stores/bootstrapStore.test.ts index ad85a4eaf..1fb36413c 100644 --- a/src/stores/bootstrapStore.test.ts +++ b/src/stores/bootstrapStore.test.ts @@ -42,10 +42,11 @@ vi.mock('@/platform/workflow/management/stores/workflowStore', () => ({ })) })) +const mockNeedsLogin = ref(false) vi.mock('@/stores/userStore', () => ({ useUserStore: vi.fn(() => ({ initialize: vi.fn().mockResolvedValue(undefined), - needsLogin: false + needsLogin: mockNeedsLogin })) })) @@ -65,6 +66,7 @@ describe('bootstrapStore', () => { beforeEach(() => { mockIsSettingsReady.value = false mockIsFirebaseInitialized.value = false + mockNeedsLogin.value = false mockDistributionTypes.isCloud = false setActivePinia(createTestingPinia({ stubActions: false })) vi.clearAllMocks() diff --git a/src/stores/bootstrapStore.ts b/src/stores/bootstrapStore.ts index 63eb00715..5b27f2ead 100644 --- a/src/stores/bootstrapStore.ts +++ b/src/stores/bootstrapStore.ts @@ -1,12 +1,12 @@ import { until, useAsyncState } from '@vueuse/core' import { defineStore, storeToRefs } from 'pinia' +import { isCloud } from '@/platform/distribution/types' import { useSettingStore } from '@/platform/settings/settingStore' import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore' import { api } from '@/scripts/api' -import { useUserStore } from '@/stores/userStore' -import { isCloud } from '@/platform/distribution/types' import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore' +import { useUserStore } from '@/stores/userStore' export const useBootstrapStore = defineStore('bootstrap', () => { const settingStore = useSettingStore() @@ -26,9 +26,16 @@ export const useBootstrapStore = defineStore('bootstrap', () => { { immediate: false } ) + let storesLoaded = false + + function loadAuthenticatedStores() { + if (storesLoaded) return + storesLoaded = true + void settingStore.load() + void workflowStore.loadWorkflows() + } + async function startStoreBootstrap() { - // Defer settings and workflows if multi-user login is required - // (settings API requires authentication in multi-user mode) const userStore = useUserStore() await userStore.initialize() @@ -37,13 +44,11 @@ export const useBootstrapStore = defineStore('bootstrap', () => { await until(isInitialized).toBe(true) } - // i18n can load without authentication - void loadI18n() + const { needsLogin } = storeToRefs(userStore) + await until(needsLogin).toBe(false) - if (!userStore.needsLogin) { - void settingStore.load() - void workflowStore.loadWorkflows() - } + void loadI18n() + loadAuthenticatedStores() } return { From 68f3f2f537ff478ee5009a3149f9d5925d2bff78 Mon Sep 17 00:00:00 2001 From: Zhiqi Yao Date: Wed, 28 Jan 2026 08:43:31 +0800 Subject: [PATCH 46/92] Fix Chinese translation "paste" misspelling (#8316) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Fixed the `站贴` misspelling. The original translation is a common misspelling using Pinyin IME because they are pronounced the same in Chinese. ## Changes - Change translation: `站贴` to `粘贴` ## Review Focus Check the fact that `粘贴` is correct in Chinese. If you're not a Chinese speaker, copy `粘贴` to Google Translate, and it should be `paste` exactly. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8316-Fix-Chinese-translation-paste-misspelling-2f46d73d3650814884e3e4adf8edeb5d) by [Unito](https://www.unito.io) --- src/locales/zh/main.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/locales/zh/main.json b/src/locales/zh/main.json index 726ea9400..c7d5ab939 100644 --- a/src/locales/zh/main.json +++ b/src/locales/zh/main.json @@ -142,7 +142,7 @@ "uploadFailed": "导入失败", "uploadModel": "导入模型", "uploadModelDescription1": "粘贴 Civitai 模型下载链接,将其添加到库中。", - "uploadModelDescription1Generic": "站贴模型下载链接,将其添加到模型库中。", + "uploadModelDescription1Generic": "粘贴模型下载链接,将其添加到模型库中。", "uploadModelDescription2": "目前仅支持 https://civitai.com 链接。", "uploadModelDescription2Generic": "仅支持来自以下提供服务的 URL :", "uploadModelDescription2Link": "https://civitai.com/models", @@ -482,7 +482,7 @@ "Open Image": "打开图像", "Open in Mask Editor": "用遮罩编辑器打开", "Outputs": "输出", - "Paste": "站贴", + "Paste": "粘贴", "Pin": "固定", "Properties": "属性", "Properties Panel": "属性面板", @@ -2809,4 +2809,4 @@ "showMinimap": "显示小地图", "zoomToFit": "适合画面" } -} +} \ No newline at end of file From f0eecdfdfa2d5641a529b69323a2e3861b3b5a37 Mon Sep 17 00:00:00 2001 From: Kelly Yang <124ykl@gmail.com> Date: Tue, 27 Jan 2026 17:25:58 -0800 Subject: [PATCH 47/92] Refactor DropZone to use VueUse useDropZone (#8174) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Refactor DropZone to use VueUse useDropZone. (#7971, #7734) ## Changes - **What**: Replaced `@dragover`, `@dragleave`, and `@drop` bindings with `useDropZone`. ## Review Focus ## Screenshots ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8174-Refactor-DropZone-to-use-VueUse-useDropZone-2ee6d73d365081ed9d31d68f7cf42263) by [Unito](https://www.unito.io) --- .../extensions/linearMode/DropZone.vue | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/renderer/extensions/linearMode/DropZone.vue b/src/renderer/extensions/linearMode/DropZone.vue index ca6330aef..c8fd3b9c1 100644 --- a/src/renderer/extensions/linearMode/DropZone.vue +++ b/src/renderer/extensions/linearMode/DropZone.vue @@ -1,9 +1,10 @@