From abf2b3b98049e8b104a97be3b60f788a746f9af6 Mon Sep 17 00:00:00 2001 From: Arjan Singh <1598641+arjansingh@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:34:59 -0700 Subject: [PATCH] Full Asset Selection Experience (Assets API) (#5900) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Full Integration of Asset Browsing and Selection when Assets API is enabled. ## Changes 1. Replace Model Left Side Tab with experience 2. Configurable titles for the Asset Browser Modal 3. Refactors to simplify callback code 4. Refactor to make modal filters reactive (they change their values based on assets displayed) 5. Add `browse()` mode with ability to create node directly from the Asset Browser Modal (in `browse()` mode) ## Screenshots Demo of many different types of Nodes getting configured by the Modal https://github.com/user-attachments/assets/34f9c964-cdf2-4c5d-86a9-a8e7126a7de9 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5900-Feat-asset-selection-cloud-integration-2816d73d365081ccb4aeecdc14b0e5d3) by [Unito](https://www.unito.io) --- src/components/sidebar/SideToolbar.vue | 11 +- .../widget/layout/BaseModalLayout.vue | 5 +- src/composables/useCoreCommands.ts | 26 ++ src/locales/en/main.json | 2 + .../assets/components/AssetBrowserModal.vue | 26 +- .../components/AssetFilterBar.stories.ts | 198 +++++++-- .../assets/components/AssetFilterBar.vue | 5 +- .../assets/composables/useAssetBrowser.ts | 45 +- .../composables/useAssetBrowserDialog.ts | 109 +++-- .../composables/useAssetFilterOptions.ts | 10 +- src/platform/assets/schemas/assetSchema.ts | 1 + src/platform/assets/services/assetService.ts | 46 +- .../assets/utils/createModelNodeFromAsset.ts | 211 +++++++++ .../widgets/composables/useComboWidget.ts | 47 +- src/stores/workspace/sidebarTabStore.ts | 16 +- .../components/AssetBrowserModal.test.ts | 176 ++++---- .../composables/useAssetBrowser.test.ts | 218 ++-------- .../composables/useAssetBrowserDialog.test.ts | 261 +++++++++--- .../composables/useAssetFilterOptions.test.ts | 21 +- .../utils/createModelNodeFromAsset.test.ts | 403 ++++++++++++++++++ .../composables/useComboWidget.test.ts | 46 +- tests-ui/tests/services/assetService.test.ts | 123 ++++-- 22 files changed, 1452 insertions(+), 554 deletions(-) create mode 100644 src/platform/assets/utils/createModelNodeFromAsset.ts create mode 100644 tests-ui/platform/assets/utils/createModelNodeFromAsset.test.ts diff --git a/src/components/sidebar/SideToolbar.vue b/src/components/sidebar/SideToolbar.vue index 288deade8..73f306cb6 100644 --- a/src/components/sidebar/SideToolbar.vue +++ b/src/components/sidebar/SideToolbar.vue @@ -38,6 +38,7 @@ import ExtensionSlot from '@/components/common/ExtensionSlot.vue' import SidebarBottomPanelToggleButton from '@/components/sidebar/SidebarBottomPanelToggleButton.vue' import SidebarShortcutsToggleButton from '@/components/sidebar/SidebarShortcutsToggleButton.vue' import { useSettingStore } from '@/platform/settings/settingStore' +import { useCommandStore } from '@/stores/commandStore' import { useKeybindingStore } from '@/stores/keybindingStore' import { useUserStore } from '@/stores/userStore' import { useWorkspaceStore } from '@/stores/workspaceStore' @@ -51,6 +52,7 @@ import SidebarTemplatesButton from './SidebarTemplatesButton.vue' const workspaceStore = useWorkspaceStore() const settingStore = useSettingStore() const userStore = useUserStore() +const commandStore = useCommandStore() const teleportTarget = computed(() => settingStore.get('Comfy.Sidebar.Location') === 'left' @@ -64,9 +66,12 @@ const isSmall = computed( const tabs = computed(() => workspaceStore.getSidebarTabs()) const selectedTab = computed(() => workspaceStore.sidebarTab.activeSidebarTab) -const onTabClick = (item: SidebarTabExtension) => { - workspaceStore.sidebarTab.toggleSidebarTab(item.id) -} + +const onTabClick = async (item: SidebarTabExtension) => + await commandStore.commands + .find((cmd) => cmd.id === `Workspace.ToggleSidebarTab.${item.id}`) + ?.function?.() + const keybindingStore = useKeybindingStore() const getTabTooltipSuffix = (tab: SidebarTabExtension) => { const keybinding = keybindingStore.getKeybindingByCommandId( diff --git a/src/components/widget/layout/BaseModalLayout.vue b/src/components/widget/layout/BaseModalLayout.vue index 6c30d7dde..023e3be43 100644 --- a/src/components/widget/layout/BaseModalLayout.vue +++ b/src/components/widget/layout/BaseModalLayout.vue @@ -48,7 +48,10 @@
-

+

{{ contentTitle }}

diff --git a/src/composables/useCoreCommands.ts b/src/composables/useCoreCommands.ts index baaff11b2..38c470852 100644 --- a/src/composables/useCoreCommands.ts +++ b/src/composables/useCoreCommands.ts @@ -15,6 +15,8 @@ import { SubgraphNode } from '@/lib/litegraph/src/litegraph' import type { Point } from '@/lib/litegraph/src/litegraph' +import { useAssetBrowserDialog } from '@/platform/assets/composables/useAssetBrowserDialog' +import { createModelNodeFromAsset } from '@/platform/assets/utils/createModelNodeFromAsset' import { useSettingStore } from '@/platform/settings/settingStore' import { useToastStore } from '@/platform/updates/common/toastStore' import { useWorkflowService } from '@/platform/workflow/core/services/workflowService' @@ -1062,6 +1064,30 @@ export function useCoreCommands(): ComfyCommand[] { } await api.freeMemory({ freeExecutionCache: true }) } + }, + { + id: 'Comfy.BrowseModelAssets', + icon: 'pi pi-folder-open', + label: 'Browse Model Assets', + versionAdded: '1.28.3', + function: async () => { + const assetBrowserDialog = useAssetBrowserDialog() + await assetBrowserDialog.browse({ + assetType: 'models', + title: t('sideToolbar.modelLibrary'), + onAssetSelected: (asset) => { + const result = createModelNodeFromAsset(asset) + if (!result.success) { + toastStore.add({ + severity: 'error', + summary: t('g.error'), + detail: t('assetBrowser.failedToCreateNode') + }) + console.error('Node creation failed:', result.error) + } + } + }) + } } ] diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 2f2a2fec1..c5103b9fa 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -1942,9 +1942,11 @@ "tryAdjustingFilters": "Try adjusting your search or filters", "loadingModels": "Loading {type}...", "connectionError": "Please check your connection and try again", + "failedToCreateNode": "Failed to create node. Please try again or check console for details.", "noModelsInFolder": "No {type} available in this folder", "searchAssetsPlaceholder": "Search assets...", "allModels": "All Models", + "allCategory": "All {category}", "unknown": "Unknown", "fileFormats": "File formats", "baseModels": "Base models", diff --git a/src/platform/assets/components/AssetBrowserModal.vue b/src/platform/assets/components/AssetBrowserModal.vue index 1182fdfa9..fe4e91531 100644 --- a/src/platform/assets/components/AssetBrowserModal.vue +++ b/src/platform/assets/components/AssetBrowserModal.vue @@ -2,7 +2,7 @@ @@ -28,7 +30,10 @@