From e8b45204f2922fe46d2b25c0f0b0894f13e926a8 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Tue, 20 Jan 2026 14:22:25 -0800 Subject: [PATCH 01/49] feat(panel): add collapsible Advanced Inputs section for widgets marked advanced (#8146) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a collapsible 'Advanced Inputs' section to the right-side panel that displays widgets marked with `options.advanced = true`. image ## Changes - Filters normal widgets to exclude advanced ones - Adds new `advancedWidgetsSectionDataList` computed for advanced widgets - Renders a collapsible section (collapsed by default) for advanced widgets ## Related - Backend PR that adds `advanced` flag: comfyanonymous/ComfyUI#11939 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8146-feat-panel-add-collapsible-Advanced-Inputs-section-for-widgets-marked-advanced-2ec6d73d36508120af1af27110a6fb96) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action Co-authored-by: Rizumu Ayaka --- .../parameters/TabNormalInputs.vue | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/components/rightSidePanel/parameters/TabNormalInputs.vue b/src/components/rightSidePanel/parameters/TabNormalInputs.vue index 30689f1a4..add128876 100644 --- a/src/components/rightSidePanel/parameters/TabNormalInputs.vue +++ b/src/components/rightSidePanel/parameters/TabNormalInputs.vue @@ -25,13 +25,31 @@ const widgetsSectionDataList = computed((): NodeWidgetsListList => { return nodes.map((node) => { const { widgets = [] } = node const shownWidgets = widgets - .filter((w) => !(w.options?.canvasOnly || w.options?.hidden)) + .filter( + (w) => + !(w.options?.canvasOnly || w.options?.hidden || w.options?.advanced) + ) .map((widget) => ({ node, widget })) return { widgets: shownWidgets, node } }) }) +const advancedWidgetsSectionDataList = computed((): NodeWidgetsListList => { + return nodes + .map((node) => { + const { widgets = [] } = node + const advancedWidgets = widgets + .filter( + (w) => + !(w.options?.canvasOnly || w.options?.hidden) && w.options?.advanced + ) + .map((widget) => ({ node, widget })) + return { widgets: advancedWidgets, node } + }) + .filter(({ widgets }) => widgets.length > 0) +}) + const isMultipleNodesSelected = computed( () => widgetsSectionDataList.value.length > 1 ) @@ -56,6 +74,12 @@ const label = computed(() => { : t('rightSidePanel.inputsNone') : undefined // SectionWidgets display node titles by default }) + +const advancedLabel = computed(() => { + return !mustShowNodeTitle && !isMultipleNodesSelected.value + ? t('rightSidePanel.advancedInputs') + : undefined // SectionWidgets display node titles by default +}) From f5a784e5619dda3e81ca1771650a3edf1e1520c3 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Tue, 20 Jan 2026 15:52:40 -0800 Subject: [PATCH 02/49] fix: add plurilization to node pack count in custom node manager dialog (#8191) --- src/locales/en/main.json | 1 + .../manager/packCard/PackCard.test.ts | 25 ++++++++++++++++--- .../components/manager/packCard/PackCard.vue | 9 ++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/locales/en/main.json b/src/locales/en/main.json index fa557ee96..e87121414 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -158,6 +158,7 @@ "choose_file_to_upload": "choose file to upload", "capture": "capture", "nodes": "Nodes", + "nodesCount": "{count} nodes | {count} node | {count} nodes", "community": "Community", "all": "All", "versionMismatchWarning": "Version Compatibility Warning", diff --git a/src/workbench/extensions/manager/components/manager/packCard/PackCard.test.ts b/src/workbench/extensions/manager/components/manager/packCard/PackCard.test.ts index 3e5116739..b3a92e5a3 100644 --- a/src/workbench/extensions/manager/components/manager/packCard/PackCard.test.ts +++ b/src/workbench/extensions/manager/components/manager/packCard/PackCard.test.ts @@ -10,15 +10,22 @@ import type { RegistryPack } from '@/workbench/extensions/manager/types/comfyManagerTypes' +const translateMock = vi.hoisted(() => + vi.fn((key: string, choice?: number) => + typeof choice === 'number' ? `${key}-${choice}` : key + ) +) +const dateMock = vi.hoisted(() => vi.fn(() => '2024. 1. 1.')) + // Mock dependencies vi.mock('vue-i18n', () => ({ useI18n: vi.fn(() => ({ - d: vi.fn(() => '2024. 1. 1.'), - t: vi.fn((key: string) => key) + d: dateMock, + t: translateMock })), createI18n: vi.fn(() => ({ global: { - t: vi.fn((key: string) => key), + t: translateMock, te: vi.fn(() => true) } })) @@ -187,6 +194,18 @@ describe('PackCard', () => { // Should still render without errors expect(wrapper.exists()).toBe(true) }) + + it('should use localized singular/plural nodes label', () => { + const packWithNodes = { + ...mockNodePack, + comfy_nodes: ['node-a'] + } as MergedNodePack + + const wrapper = createWrapper({ nodePack: packWithNodes }) + + expect(wrapper.text()).toContain('g.nodesCount-1') + expect(translateMock).toHaveBeenCalledWith('g.nodesCount', 1) + }) }) describe('component structure', () => { diff --git a/src/workbench/extensions/manager/components/manager/packCard/PackCard.vue b/src/workbench/extensions/manager/components/manager/packCard/PackCard.vue index 6900e71df..17ffdd102 100644 --- a/src/workbench/extensions/manager/components/manager/packCard/PackCard.vue +++ b/src/workbench/extensions/manager/components/manager/packCard/PackCard.vue @@ -36,8 +36,8 @@

-
- {{ nodesCount }} {{ $t('g.nodes') }} +
+ {{ nodesLabel }}
() -const { d } = useI18n() +const { d, t } = useI18n() const colorPaletteStore = useColorPaletteStore() const isLightTheme = computed( @@ -115,6 +115,9 @@ const isDisabled = computed( const nodesCount = computed(() => isMergedNodePack(nodePack) ? nodePack.comfy_nodes?.length : undefined ) +const nodesLabel = computed(() => + nodesCount.value ? t('g.nodesCount', nodesCount.value) : '' +) const publisherName = computed(() => { if (!nodePack) return null From e6ef99e92ca446bbd869190e725ae2f219ce1a88 Mon Sep 17 00:00:00 2001 From: Simula_r <18093452+simula-r@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:13:54 -0800 Subject: [PATCH 03/49] feat: add isCloud guard to team workspaces feature flag (#8192) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensures the team_workspaces_enabled feature flag only returns true when running in cloud environment, preventing the feature from activating in local/desktop installations. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8192-feat-add-isCloud-guard-to-team-workspaces-feature-flag-2ee6d73d3650810bb1d7c1721ebcdd44) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude Opus 4.5 Co-authored-by: GitHub Action --- src/composables/useFeatureFlags.ts | 3 +++ .../assets/components/MediaAssetFilterBar.vue | 26 +++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/composables/useFeatureFlags.ts b/src/composables/useFeatureFlags.ts index 136b7ccd1..ca54bb9c6 100644 --- a/src/composables/useFeatureFlags.ts +++ b/src/composables/useFeatureFlags.ts @@ -1,5 +1,6 @@ import { computed, reactive, readonly } from 'vue' +import { isCloud } from '@/platform/distribution/types' import { remoteConfig } from '@/platform/remoteConfig/remoteConfig' import { api } from '@/scripts/api' @@ -95,6 +96,8 @@ export function useFeatureFlags() { ) }, get teamWorkspacesEnabled() { + if (!isCloud) return false + return ( remoteConfig.value.team_workspaces_enabled ?? api.getServerFeature(ServerFeatureFlag.TEAM_WORKSPACES_ENABLED, false) diff --git a/src/platform/assets/components/MediaAssetFilterBar.vue b/src/platform/assets/components/MediaAssetFilterBar.vue index 0442f5f56..6e4ec5e4c 100644 --- a/src/platform/assets/components/MediaAssetFilterBar.vue +++ b/src/platform/assets/components/MediaAssetFilterBar.vue @@ -6,20 +6,36 @@ @update:model-value="handleSearchChange" />
- + - + - +
From b1dfbfaa09cd5f76ca8c11715a913283dfd4b3c3 Mon Sep 17 00:00:00 2001 From: Alexander Brown Date: Tue, 20 Jan 2026 16:44:08 -0800 Subject: [PATCH 04/49] chore: Replace prettier with oxfmt (#8177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configure oxfmt ignorePatterns to exclude non-JS/TS files (md, json, css, yaml, etc.) to match previous Prettier behavior. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8177-chore-configure-oxfmt-to-format-only-JS-TS-Vue-files-2ee6d73d3650815080f3cc8a4a932109) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp --- .claude/commands/setup_repo.md | 2 +- .github/workflows/ci-lint-format.yaml | 6 +- .i18nrc.cjs | 18 +- .oxfmtrc.json | 20 ++ .prettierignore | 2 - .prettierrc | 11 - .vscode/extensions.json | 15 +- AGENTS.md | 8 +- eslint.config.ts | 6 +- lint-staged.config.mjs | 25 -- lint-staged.config.ts | 5 +- package.json | 10 +- pnpm-lock.yaml | 323 ++++++------------- pnpm-workspace.yaml | 4 +- src/composables/useContextMenuTranslation.ts | 3 +- vite.config.mts | 3 +- 16 files changed, 158 insertions(+), 303 deletions(-) create mode 100644 .oxfmtrc.json delete mode 100644 .prettierignore delete mode 100644 .prettierrc delete mode 100644 lint-staged.config.mjs diff --git a/.claude/commands/setup_repo.md b/.claude/commands/setup_repo.md index d82e22ec6..71dee96a5 100644 --- a/.claude/commands/setup_repo.md +++ b/.claude/commands/setup_repo.md @@ -122,7 +122,7 @@ echo " pnpm build - Build for production" echo " pnpm test:unit - Run unit tests" echo " pnpm typecheck - Run TypeScript checks" echo " pnpm lint - Run ESLint" -echo " pnpm format - Format code with Prettier" +echo " pnpm format - Format code with oxfmt" echo "" echo "Next steps:" echo "1. Run 'pnpm dev' to start developing" diff --git a/.github/workflows/ci-lint-format.yaml b/.github/workflows/ci-lint-format.yaml index 3ce6d6aa9..c97f6255c 100644 --- a/.github/workflows/ci-lint-format.yaml +++ b/.github/workflows/ci-lint-format.yaml @@ -42,7 +42,7 @@ jobs: - name: Run Stylelint with auto-fix run: pnpm stylelint:fix - - name: Run Prettier with auto-format + - name: Run oxfmt with auto-format run: pnpm format - name: Check for changes @@ -60,7 +60,7 @@ jobs: git config --local user.email "action@github.com" git config --local user.name "GitHub Action" git add . - git commit -m "[automated] Apply ESLint and Prettier fixes" + git commit -m "[automated] Apply ESLint and Oxfmt fixes" git push - name: Final validation @@ -80,7 +80,7 @@ jobs: issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, - body: '## 🔧 Auto-fixes Applied\n\nThis PR has been automatically updated to fix linting and formatting issues.\n\n**⚠️ Important**: Your local branch is now behind. Run `git pull` before making additional changes to avoid conflicts.\n\n### Changes made:\n- ESLint auto-fixes\n- Prettier formatting' + body: '## 🔧 Auto-fixes Applied\n\nThis PR has been automatically updated to fix linting and formatting issues.\n\n**⚠️ Important**: Your local branch is now behind. Run `git pull` before making additional changes to avoid conflicts.\n\n### Changes made:\n- ESLint auto-fixes\n- Oxfmt formatting' }) - name: Comment on PR about manual fix needed diff --git a/.i18nrc.cjs b/.i18nrc.cjs index 86ce06eaa..4369f0a70 100644 --- a/.i18nrc.cjs +++ b/.i18nrc.cjs @@ -1,7 +1,7 @@ // This file is intentionally kept in CommonJS format (.cjs) // to resolve compatibility issues with dependencies that require CommonJS. // Do not convert this file to ESModule format unless all dependencies support it. -const { defineConfig } = require('@lobehub/i18n-cli'); +const { defineConfig } = require('@lobehub/i18n-cli') module.exports = defineConfig({ modelName: 'gpt-4.1', @@ -10,7 +10,19 @@ module.exports = defineConfig({ entry: 'src/locales/en', entryLocale: 'en', output: 'src/locales', - outputLocales: ['zh', 'zh-TW', 'ru', 'ja', 'ko', 'fr', 'es', 'ar', 'tr', 'pt-BR', 'fa'], + outputLocales: [ + 'zh', + 'zh-TW', + 'ru', + 'ja', + 'ko', + 'fr', + 'es', + 'ar', + 'tr', + 'pt-BR', + 'fa' + ], reference: `Special names to keep untranslated: flux, photomaker, clip, vae, cfg, stable audio, stable cascade, stable zero, controlnet, lora, HiDream, Civitai, Hugging Face. 'latent' is the short form of 'latent space'. 'mask' is in the context of image processing. @@ -26,4 +38,4 @@ module.exports = defineConfig({ - Use Arabic-Indic numerals (۰-۹) for numbers where appropriate. - Maintain consistency with terminology used in Persian software and design applications. ` -}); +}) diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 000000000..5da4febe2 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,20 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "singleQuote": true, + "tabWidth": 2, + "semi": false, + "trailingComma": "none", + "printWidth": 80, + "ignorePatterns": [ + "packages/registry-types/src/comfyRegistryTypes.ts", + "src/types/generatedManagerTypes.ts", + "**/*.md", + "**/*.json", + "**/*.css", + "**/*.yaml", + "**/*.yml", + "**/*.html", + "**/*.svg", + "**/*.xml" + ] +} diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 4403edd8e..000000000 --- a/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -packages/registry-types/src/comfyRegistryTypes.ts -src/types/generatedManagerTypes.ts diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index aa43a43ac..000000000 --- a/.prettierrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "singleQuote": true, - "tabWidth": 2, - "semi": false, - "trailingComma": "none", - "printWidth": 80, - "importOrder": ["^@core/(.*)$", "", "^@/(.*)$", "^[./]"], - "importOrderSeparation": true, - "importOrderSortSpecifiers": true, - "plugins": ["@prettier/plugin-oxc", "@trivago/prettier-plugin-sort-imports"] -} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 54f28d400..9cbac42d7 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,25 +1,22 @@ { "recommendations": [ + "antfu.vite", "austenc.tailwind-docs", "bradlc.vscode-tailwindcss", "davidanson.vscode-markdownlint", "dbaeumer.vscode-eslint", + "donjayamanne.githistory", "eamodio.gitlens", - "esbenp.prettier-vscode", - "figma.figma-vscode-extension", "github.vscode-github-actions", "github.vscode-pull-request-github", "hbenl.vscode-test-explorer", + "kisstkondoros.vscode-codemetrics", "lokalise.i18n-ally", "ms-playwright.playwright", + "oxc.oxc-vscode", + "sonarsource.sonarlint-vscode", "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" + "wix.vscode-import-cost" ] } diff --git a/AGENTS.md b/AGENTS.md index da2953783..9938865a9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,10 +27,10 @@ See @docs/guidance/*.md for file-type-specific conventions (auto-loaded by glob) - Build output: `dist/` - Configs - `vite.config.mts` - - `vitest.config.ts` - `playwright.config.ts` - `eslint.config.ts` - - `.prettierrc` + - `.oxfmtrc.json` + - `.oxlintrc.json` - etc. ## Monorepo Architecture @@ -46,7 +46,7 @@ The project uses **Nx** for build orchestration and task management - `pnpm test:unit`: Run Vitest unit tests - `pnpm test:browser`: Run Playwright E2E tests (`browser_tests/`) - `pnpm lint` / `pnpm lint:fix`: Lint (ESLint) -- `pnpm format` / `pnpm format:check`: Prettier +- `pnpm format` / `pnpm format:check`: oxfmt - `pnpm typecheck`: Vue TSC type checking - `pnpm storybook`: Start Storybook development server @@ -72,7 +72,7 @@ The project uses **Nx** for build orchestration and task management - Composition API only - Tailwind 4 styling - Avoid ` diff --git a/src/components/sidebar/SidebarIcon.test.ts b/src/components/sidebar/SidebarIcon.test.ts index 7564e7bcd..284a29825 100644 --- a/src/components/sidebar/SidebarIcon.test.ts +++ b/src/components/sidebar/SidebarIcon.test.ts @@ -1,6 +1,5 @@ import { mount } from '@vue/test-utils' import PrimeVue from 'primevue/config' -import OverlayBadge from 'primevue/overlaybadge' import Tooltip from 'primevue/tooltip' import { describe, expect, it } from 'vitest' import { createI18n } from 'vue-i18n' @@ -33,8 +32,7 @@ describe('SidebarIcon', () => { return mount(SidebarIcon, { global: { plugins: [PrimeVue, i18n], - directives: { tooltip: Tooltip }, - components: { OverlayBadge } + directives: { tooltip: Tooltip } }, props: { ...exampleProps, ...props }, ...options @@ -54,9 +52,9 @@ describe('SidebarIcon', () => { it('creates badge when iconBadge prop is set', () => { const badge = '2' const wrapper = mountSidebarIcon({ iconBadge: badge }) - const badgeEl = wrapper.findComponent(OverlayBadge) + const badgeEl = wrapper.find('.sidebar-icon-badge') expect(badgeEl.exists()).toBe(true) - expect(badgeEl.find('.p-badge').text()).toEqual(badge) + expect(badgeEl.text()).toEqual(badge) }) it('shows tooltip on hover', async () => { diff --git a/src/components/sidebar/SidebarIcon.vue b/src/components/sidebar/SidebarIcon.vue index 88900c1a7..10dfca8f8 100644 --- a/src/components/sidebar/SidebarIcon.vue +++ b/src/components/sidebar/SidebarIcon.vue @@ -17,22 +17,28 @@ >