Skip to content

Recently used sections #4346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c5970bb
chore: add ii8n and keywords
Myestery Jul 4, 2025
c252d56
chore: add workflow and model sidebar sections for recently used/added
Myestery Jul 4, 2025
411eba8
settings: add relevant sidebar settings for recently used/added
Myestery Jul 4, 2025
a7be5c4
api: add relevant fields to track creation/modified time on stores
Myestery Jul 4, 2025
04b674b
feature: implement recentItems store
Myestery Jul 4, 2025
db1a24e
Merge remote-tracking branch 'upstream/main' into recently-used-sections
Myestery Jul 4, 2025
beb62a1
Merge branch 'main' into recently-used-sections
Myestery Jul 4, 2025
571d27f
refactor: update UserFile class to require created timestamp and adju…
Myestery Jul 4, 2025
0ea60d7
test: add unit tests for useRecentItemsStore functionality
Myestery Jul 4, 2025
2838231
feat(sidebar): add RecentItemsSection component with functionality fo…
Myestery Jul 6, 2025
45ad7b1
refactor(sidebar): remove RecentModelsSection and RecentWorkflowsSect…
Myestery Jul 6, 2025
df43689
feat(sidebar): replace RecentModelsSection and RecentWorkflowsSection…
Myestery Jul 6, 2025
417e8df
feat(preview): implement useModelPreview composable for model preview…
Myestery Jul 6, 2025
c227c43
fix(recentItemsStore): update sorting logic to use maxRecentItemCount…
Myestery Jul 6, 2025
ee8a7ec
Merge branch 'main' into recently-used-sections
Myestery Jul 6, 2025
6ba712d
Merge branch 'main' into recently-used-sections
Myestery Jul 7, 2025
0ef5fc5
fix(useModelPreview): improve type safety for previewRef
Myestery Jul 8, 2025
f4d520e
fix(recentItemsStore): update maxRecentItemCount to be a computed pro…
Myestery Jul 8, 2025
4414dbf
leave image load duties to model preview
Myestery Jul 8, 2025
36d9f1b
fix(RecentItemsSection): refine RecentItem interface for improved typ…
Myestery Jul 8, 2025
7d07302
refactor(RecentItemsSection): simplify model item handling
Myestery Jul 8, 2025
124d03a
feat(ModelLibrarySidebarTab): log model usage and load recent models …
Myestery Jul 9, 2025
5d53d19
feat(RecentItemsStore): integrate ComfyModelLog for tracking model usage
Myestery Jul 9, 2025
b1cc078
test(RecentItemsStore): ensure tests for recentlyUsedModels use model…
Myestery Jul 10, 2025
b3c1898
refactor(RecentItemsStore, ComfyModelLog): streamline model logging a…
Myestery Jul 10, 2025
96b324b
feat(userFileStore, workflowStore): add 'created' property to file ob…
Myestery Jul 10, 2025
c43969e
feat(recentItemsStore): enhance model log service mock and add model …
Myestery Jul 10, 2025
0548845
feat(RecentItemsSection, ModelLibrarySidebarTab): add isComfyModelDef…
Myestery Jul 10, 2025
88d7198
feat( recentItemsStore): improve recentlyUsedModels computation
Myestery Jul 10, 2025
929be0e
Merge branch 'main' into recently-used-sections
Myestery Jul 10, 2025
4768e8a
Merge branch 'main' into recently-used-sections
Myestery Jul 11, 2025
be394ff
Merge branch 'main' into recently-used-sections
Myestery Jul 11, 2025
631f301
Merge branch 'main' into recently-used-sections
Myestery Jul 11, 2025
a6725a6
Merge branch 'main' into recently-used-sections
Myestery Aug 4, 2025
4bb7377
[feat] Add loading state for recently used items in sidebar
Myestery Aug 4, 2025
44b5110
[feat] Enhance loading states for model log and recent items
Myestery Aug 4, 2025
260c6c7
Merge branch 'main' into recently-used-sections
Myestery Aug 11, 2025
b64880d
fix widget type
Myestery Aug 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 91 additions & 10 deletions src/components/sidebar/tabs/ModelLibrarySidebarTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,33 @@
<template #body>
<ElectronDownloadItems v-if="isElectron()" />

<div v-if="!searchQuery" class="model-library-content">
<RecentItemsSection
:recently-added-items="recentItemsStore.recentlyAddedModels"
:recently-used-items="recentItemsStore.recentlyUsedModels"
:show-recently-added="showRecentlyAddedModels"
:show-recently-used="showRecentlyUsedModels"
:recently-added-title="
$t('sideToolbar.modelLibraryTab.recentlyAddedModels')
"
:recently-used-title="
$t('sideToolbar.modelLibraryTab.recentlyUsedModels')
"
:get-item-icon="getModelIcon"
:get-item-label="getModelLabel"
:get-item-preview-url="getModelPreviewUrl"
:on-item-click="handleModelClick"
:enable-preview="true"
:is-comfy-model-def="(_item: ComfyModelDef) => true"
:is-loading-recently-used="!recentItemsStore.areModelsReady"
preview-target-id="#model-library-model-preview-container"
>
<template #preview="{ modelDef, previewRef }">
<ModelPreview :ref="previewRef" :model-def="modelDef" />
</template>
</RecentItemsSection>
</div>

<TreeExplorer
v-model:expandedKeys="expandedKeys"
class="model-lib-tree-explorer"
Expand All @@ -46,14 +73,16 @@

<script setup lang="ts">
import Button from 'primevue/button'
import { computed, nextTick, onMounted, ref, toRef, watch } from 'vue'
import { computed, nextTick, ref, toRef, watch, watchEffect } from 'vue'

import SearchBox from '@/components/common/SearchBox.vue'
import TreeExplorer from '@/components/common/TreeExplorer.vue'
import RecentItemsSection from '@/components/sidebar/tabs/RecentItemsSection.vue'
import SidebarTabTemplate from '@/components/sidebar/tabs/SidebarTabTemplate.vue'
import ElectronDownloadItems from '@/components/sidebar/tabs/modelLibrary/ElectronDownloadItems.vue'
import ModelTreeLeaf from '@/components/sidebar/tabs/modelLibrary/ModelTreeLeaf.vue'
import { useTreeExpansion } from '@/composables/useTreeExpansion'
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
import { useLitegraphService } from '@/services/litegraphService'
import {
ComfyModelDef,
Expand All @@ -62,6 +91,7 @@ import {
useModelStore
} from '@/stores/modelStore'
import { useModelToNodeStore } from '@/stores/modelToNodeStore'
import { useRecentItemsStore } from '@/stores/recentItemsStore'
import { useSettingStore } from '@/stores/settingStore'
import type { TreeNode } from '@/types/treeExplorerTypes'
import type { TreeExplorerNode } from '@/types/treeExplorerTypes'
Expand All @@ -70,6 +100,7 @@ import { buildTree } from '@/utils/treeUtil'

const modelStore = useModelStore()
const modelToNodeStore = useModelToNodeStore()
const recentItemsStore = useRecentItemsStore()
const settingStore = useSettingStore()
const searchQuery = ref<string>('')
const expandedKeys = ref<Record<string, boolean>>({})
Expand Down Expand Up @@ -145,17 +176,17 @@ const renderedRoot = computed<TreeExplorerNode<ModelOrFolder>>(() => {
draggable: node.leaf,
handleClick(e: MouseEvent) {
if (this.leaf) {
// @ts-expect-error fixme ts strict error
const provider = modelToNodeStore.getNodeProvider(model.directory)
const provider = modelToNodeStore.getNodeProvider(model!.directory)
if (provider) {
const node = useLitegraphService().addNodeOnGraph(provider.nodeDef)
// @ts-expect-error fixme ts strict error
const widget = node.widgets.find(
(widget) => widget.name === provider.key
recentItemsStore.logModelUsage(model!).catch((error) => {
console.error('Error logging model usage:', error)
})
const widget = node.widgets?.find(
(widget: IBaseWidget) => widget.name === provider.key
)
if (widget) {
// @ts-expect-error fixme ts strict error
widget.value = model.file_name
widget.value = model!.file_name
}
}
} else {
Expand All @@ -168,6 +199,50 @@ const renderedRoot = computed<TreeExplorerNode<ModelOrFolder>>(() => {
return fillNodeInfo(root.value)
})

const showRecentlyAddedModels = computed(() =>
settingStore.get('Comfy.Sidebar.RecentItems.ShowRecentlyAdded')
)
const showRecentlyUsedModels = computed(() =>
settingStore.get('Comfy.Sidebar.RecentItems.ShowRecentlyUsed')
)

const getModelIcon = (model: ComfyModelDef): string => {
return model.image ? 'pi pi-image' : 'pi pi-file'
}

const getModelLabel = (model: ComfyModelDef): string => {
const nameFormat = settingStore.get('Comfy.ModelLibrary.NameFormat')
return nameFormat === 'title' ? model.title : model.simplified_file_name
}

const getModelPreviewUrl = (model: ComfyModelDef): string | null => {
if (model.image) {
return model.image
}
const folder = model.directory
const path_index = model.path_index
const extension = model.file_name.split('.').pop()
const filename = model.file_name.replace(`.${extension}`, '.webp')
const encodedFilename = encodeURIComponent(filename).replace(/%2F/g, '/')
return `/api/experiment/models/preview/${folder}/${path_index}/${encodedFilename}`
}

const handleModelClick = (model: ComfyModelDef): void => {
const provider = modelToNodeStore.getNodeProvider(model.directory)
if (provider) {
const node = useLitegraphService().addNodeOnGraph(provider.nodeDef)
recentItemsStore.logModelUsage(model).catch((error) => {
console.error('Error logging model usage:', error)
})
const widget = node.widgets?.find(
(widget: IBaseWidget) => widget.name === provider.key
)
if (widget) {
widget.value = model.file_name
}
}
}

watch(
toRef(expandedKeys, 'value'),
(newExpandedKeys) => {
Expand All @@ -184,9 +259,15 @@ watch(
{ deep: true }
)

onMounted(async () => {
if (settingStore.get('Comfy.ModelLibrary.AutoLoadAll')) {
watchEffect(async () => {
if (
settingStore.get('Comfy.ModelLibrary.AutoLoadAll') ||
// if we don't load all, we can't filter the recent items
settingStore.get('Comfy.Sidebar.RecentItems.ShowRecentlyAdded') ||
settingStore.get('Comfy.Sidebar.RecentItems.ShowRecentlyUsed')
) {
await modelStore.loadModels()
await recentItemsStore.loadRecentModels()
}
})
</script>
Expand Down
Loading