mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 19:09:52 +00:00
Show node by frequency on empty query (#878)
This commit is contained in:
1
public/assets/CREDIT.txt
Normal file
1
public/assets/CREDIT.txt
Normal file
@@ -0,0 +1 @@
|
||||
Thanks to OpenArt (https://openart.ai) for providing the sorted-custom-node-map data, captured in September 2024.
|
||||
2602
public/assets/sorted-custom-node-map.json
Normal file
2602
public/assets/sorted-custom-node-map.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,11 @@ import { ref, computed, onUnmounted, onMounted, watchEffect } from 'vue'
|
||||
import { app as comfyApp } from '@/scripts/app'
|
||||
import { useSettingStore } from '@/stores/settingStore'
|
||||
import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'
|
||||
import { ComfyNodeDefImpl, useNodeDefStore } from '@/stores/nodeDefStore'
|
||||
import {
|
||||
ComfyNodeDefImpl,
|
||||
useNodeDefStore,
|
||||
useNodeFrequencyStore
|
||||
} from '@/stores/nodeDefStore'
|
||||
import { useWorkspaceStore } from '@/stores/workspaceStateStore'
|
||||
import {
|
||||
LiteGraph,
|
||||
@@ -140,6 +144,8 @@ onMounted(async () => {
|
||||
// node search is triggered
|
||||
useNodeDefStore().nodeSearchService.endsWithFilterStartSequence('')
|
||||
|
||||
// Non-blocking load of node frequencies
|
||||
useNodeFrequencyStore().loadNodeFrequencies()
|
||||
emit('ready')
|
||||
})
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
:suggestions="suggestions"
|
||||
:min-length="0"
|
||||
:delay="100"
|
||||
:loading="!nodeFrequencyStore.isLoaded"
|
||||
@complete="search($event.query)"
|
||||
@option-select="emit('addNode', $event.value)"
|
||||
@focused-option-changed="setHoverSuggestion($event)"
|
||||
@@ -67,7 +68,11 @@ import NodeSearchFilter from '@/components/searchbox/NodeSearchFilter.vue'
|
||||
import NodeSearchItem from '@/components/searchbox/NodeSearchItem.vue'
|
||||
import { type FilterAndValue } from '@/services/nodeSearchService'
|
||||
import NodePreview from '@/components/node/NodePreview.vue'
|
||||
import { ComfyNodeDefImpl, useNodeDefStore } from '@/stores/nodeDefStore'
|
||||
import {
|
||||
ComfyNodeDefImpl,
|
||||
useNodeDefStore,
|
||||
useNodeFrequencyStore
|
||||
} from '@/stores/nodeDefStore'
|
||||
import { useSettingStore } from '@/stores/settingStore'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import SearchFilterChip from '../common/SearchFilterChip.vue'
|
||||
@@ -98,13 +103,18 @@ const placeholder = computed(() => {
|
||||
return props.filters.length === 0 ? t('searchNodes') + '...' : ''
|
||||
})
|
||||
|
||||
const nodeDefStore = useNodeDefStore()
|
||||
const nodeFrequencyStore = useNodeFrequencyStore()
|
||||
const search = (query: string) => {
|
||||
currentQuery.value = query
|
||||
suggestions.value = [
|
||||
...useNodeDefStore().nodeSearchService.searchNode(query, props.filters, {
|
||||
limit: props.searchLimit
|
||||
})
|
||||
]
|
||||
suggestions.value =
|
||||
query === ''
|
||||
? nodeFrequencyStore.topNodeDefs
|
||||
: [
|
||||
...nodeDefStore.nodeSearchService.searchNode(query, props.filters, {
|
||||
limit: props.searchLimit
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
const emit = defineEmits(['addFilter', 'removeFilter', 'addNode'])
|
||||
|
||||
@@ -33,6 +33,11 @@
|
||||
:value="$t('deprecated')"
|
||||
severity="danger"
|
||||
/>
|
||||
<Tag
|
||||
v-if="showNodeFrequency && nodeFrequency > 0"
|
||||
:value="formatNumberWithSuffix(nodeFrequency, { roundToInt: true })"
|
||||
severity="secondary"
|
||||
/>
|
||||
<NodeSourceChip
|
||||
v-if="nodeDef.python_module !== undefined"
|
||||
:python_module="nodeDef.python_module"
|
||||
@@ -44,11 +49,12 @@
|
||||
<script setup lang="ts">
|
||||
import Tag from 'primevue/tag'
|
||||
import NodeSourceChip from '@/components/node/NodeSourceChip.vue'
|
||||
import { ComfyNodeDefImpl } from '@/stores/nodeDefStore'
|
||||
import { ComfyNodeDefImpl, useNodeFrequencyStore } from '@/stores/nodeDefStore'
|
||||
import { highlightQuery } from '@/utils/formatUtil'
|
||||
import { computed } from 'vue'
|
||||
import { useSettingStore } from '@/stores/settingStore'
|
||||
import { useNodeBookmarkStore } from '@/stores/nodeBookmarkStore'
|
||||
import { formatNumberWithSuffix } from '@/utils/formatUtil'
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
const showCategory = computed(() =>
|
||||
@@ -57,6 +63,13 @@ const showCategory = computed(() =>
|
||||
const showIdName = computed(() =>
|
||||
settingStore.get('Comfy.NodeSearchBoxImpl.ShowIdName')
|
||||
)
|
||||
const showNodeFrequency = computed(() =>
|
||||
settingStore.get('Comfy.NodeSearchBoxImpl.ShowNodeFrequency')
|
||||
)
|
||||
const nodeFrequencyStore = useNodeFrequencyStore()
|
||||
const nodeFrequency = computed(() =>
|
||||
nodeFrequencyStore.getNodeFrequency(props.nodeDef)
|
||||
)
|
||||
|
||||
const nodeBookmarkStore = useNodeBookmarkStore()
|
||||
const isBookmarked = computed(() =>
|
||||
|
||||
@@ -69,6 +69,14 @@ export const CORE_SETTINGS: SettingParams[] = [
|
||||
type: 'boolean',
|
||||
defaultValue: false
|
||||
},
|
||||
{
|
||||
id: 'Comfy.NodeSearchBoxImpl.ShowNodeFrequency',
|
||||
category: ['Comfy', 'Node Search Box', 'ShowNodeFrequency'],
|
||||
name: 'Show node frequency in search results',
|
||||
tooltip: 'Only applies to the default implementation',
|
||||
type: 'boolean',
|
||||
defaultValue: false
|
||||
},
|
||||
{
|
||||
id: 'Comfy.Sidebar.Location',
|
||||
category: ['Comfy', 'Sidebar', 'Location'],
|
||||
|
||||
@@ -5,6 +5,8 @@ import { Type, Transform, plainToClass, Expose } from 'class-transformer'
|
||||
import { ComfyWidgetConstructor } from '@/scripts/widgets'
|
||||
import { TreeNode } from 'primevue/treenode'
|
||||
import { buildTree } from '@/utils/treeUtil'
|
||||
import { computed, ref } from 'vue'
|
||||
import axios from 'axios'
|
||||
|
||||
export class BaseInputSpec<T = any> {
|
||||
name: string
|
||||
@@ -338,3 +340,44 @@ export const useNodeDefStore = defineStore('nodeDef', {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const useNodeFrequencyStore = defineStore('nodeFrequency', () => {
|
||||
const topNodeDefLimit = ref(64)
|
||||
const nodeFrequencyLookup = ref<Record<string, number>>({})
|
||||
const nodeNamesByFrequency = computed(() =>
|
||||
Object.keys(nodeFrequencyLookup.value)
|
||||
)
|
||||
const isLoaded = ref(false)
|
||||
|
||||
const loadNodeFrequencies = async () => {
|
||||
if (!isLoaded.value) {
|
||||
try {
|
||||
const response = await axios.get('/assets/sorted-custom-node-map.json')
|
||||
nodeFrequencyLookup.value = response.data
|
||||
isLoaded.value = true
|
||||
} catch (error) {
|
||||
console.error('Error loading node frequencies:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getNodeFrequency = (nodeDef: ComfyNodeDefImpl) => {
|
||||
return nodeFrequencyLookup.value[nodeDef.name] ?? 0
|
||||
}
|
||||
|
||||
const nodeDefStore = useNodeDefStore()
|
||||
const topNodeDefs = computed<ComfyNodeDefImpl[]>(() => {
|
||||
return nodeNamesByFrequency.value
|
||||
.map((nodeName: string) => nodeDefStore.nodeDefsByName[nodeName])
|
||||
.filter((nodeDef: ComfyNodeDefImpl) => nodeDef !== undefined)
|
||||
.slice(0, topNodeDefLimit.value)
|
||||
})
|
||||
|
||||
return {
|
||||
nodeNamesByFrequency,
|
||||
topNodeDefs,
|
||||
isLoaded,
|
||||
loadNodeFrequencies,
|
||||
getNodeFrequency
|
||||
}
|
||||
})
|
||||
|
||||
@@ -39,3 +39,23 @@ export function highlightQuery(text: string, query: string) {
|
||||
const regex = new RegExp(`(${query})`, 'gi')
|
||||
return text.replace(regex, '<span class="highlight">$1</span>')
|
||||
}
|
||||
|
||||
export function formatNumberWithSuffix(
|
||||
num: number,
|
||||
{
|
||||
precision = 1,
|
||||
roundToInt = false
|
||||
}: { precision?: number; roundToInt?: boolean } = {}
|
||||
): string {
|
||||
const suffixes = ['', 'k', 'm', 'b', 't']
|
||||
const absNum = Math.abs(num)
|
||||
|
||||
if (absNum < 1000) {
|
||||
return roundToInt ? Math.round(num).toString() : num.toFixed(precision)
|
||||
}
|
||||
|
||||
const exp = Math.min(Math.floor(Math.log10(absNum) / 3), suffixes.length - 1)
|
||||
const formattedNum = (num / Math.pow(1000, exp)).toFixed(precision)
|
||||
|
||||
return `${formattedNum}${suffixes[exp]}`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user