mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-24 08:44:06 +00:00
wip2
This commit is contained in:
@@ -92,8 +92,8 @@ function applyFilenameMappingToWidget(
|
||||
const hashValue = widget.value
|
||||
if (typeof hashValue !== 'string') return String(hashValue)
|
||||
|
||||
// Try to get human-readable name from cache
|
||||
const mapping = fileNameMappingService.getCachedMapping('input')
|
||||
// Try to get human-readable name from cache (deduplicated for display)
|
||||
const mapping = fileNameMappingService.getCachedMapping('input', true)
|
||||
const humanName = mapping[hashValue]
|
||||
|
||||
// Return human name for display, fallback to hash
|
||||
@@ -117,8 +117,8 @@ function applyFilenameMappingToWidget(
|
||||
get() {
|
||||
if (!Array.isArray(rawValues)) return rawValues
|
||||
|
||||
// Map values to human-readable names
|
||||
const mapping = fileNameMappingService.getCachedMapping('input')
|
||||
// Map values to human-readable names (deduplicated for dropdown display)
|
||||
const mapping = fileNameMappingService.getCachedMapping('input', true)
|
||||
const mapped = rawValues.map((value: any) => {
|
||||
if (typeof value === 'string') {
|
||||
const humanName = mapping[value]
|
||||
@@ -165,8 +165,8 @@ function applyFilenameMappingToWidget(
|
||||
|
||||
// Override incrementValue and decrementValue for arrow key navigation
|
||||
;(widget as any).incrementValue = function (options: any) {
|
||||
// Get the current human-readable value
|
||||
const mapping = fileNameMappingService.getCachedMapping('input')
|
||||
// Get the current human-readable value (deduplicated)
|
||||
const mapping = fileNameMappingService.getCachedMapping('input', true)
|
||||
const currentHumanName = mapping[widget.value] || widget.value
|
||||
|
||||
// Get the values array (which contains human names through our proxy)
|
||||
@@ -185,8 +185,8 @@ function applyFilenameMappingToWidget(
|
||||
}
|
||||
}
|
||||
;(widget as any).decrementValue = function (options: any) {
|
||||
// Get the current human-readable value
|
||||
const mapping = fileNameMappingService.getCachedMapping('input')
|
||||
// Get the current human-readable value (deduplicated)
|
||||
const mapping = fileNameMappingService.getCachedMapping('input', true)
|
||||
const currentHumanName = mapping[widget.value] || widget.value
|
||||
|
||||
// Get the values array (which contains human names through our proxy)
|
||||
@@ -210,8 +210,11 @@ function applyFilenameMappingToWidget(
|
||||
;(widget as any).setValue = function (selectedValue: any, options?: any) {
|
||||
if (typeof selectedValue === 'string') {
|
||||
// Check if this is a human-readable name that needs reverse mapping
|
||||
const reverseMapping =
|
||||
fileNameMappingService.getCachedReverseMapping('input')
|
||||
// Use deduplicated reverse mapping to handle suffixed names
|
||||
const reverseMapping = fileNameMappingService.getCachedReverseMapping(
|
||||
'input',
|
||||
true
|
||||
)
|
||||
const hashValue = reverseMapping[selectedValue] || selectedValue
|
||||
|
||||
// Set the hash value
|
||||
@@ -242,8 +245,11 @@ function applyFilenameMappingToWidget(
|
||||
widget.callback = function (selectedValue: any) {
|
||||
if (typeof selectedValue === 'string') {
|
||||
// Check if this is a human-readable name that needs reverse mapping
|
||||
const reverseMapping =
|
||||
fileNameMappingService.getCachedReverseMapping('input')
|
||||
// Use deduplicated reverse mapping to handle suffixed names
|
||||
const reverseMapping = fileNameMappingService.getCachedReverseMapping(
|
||||
'input',
|
||||
true
|
||||
)
|
||||
const hashValue = reverseMapping[selectedValue] || selectedValue
|
||||
|
||||
// Set the hash value
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface FileNameMapping {
|
||||
|
||||
export interface CacheEntry {
|
||||
data: FileNameMapping
|
||||
dedupData?: FileNameMapping // Deduplicated mapping with unique display names
|
||||
timestamp: number
|
||||
error?: Error | null
|
||||
fetchPromise?: Promise<FileNameMapping>
|
||||
@@ -88,16 +89,25 @@ export class FileNameMappingService {
|
||||
/**
|
||||
* Get cached mapping synchronously (returns empty object if not cached).
|
||||
* @param fileType - The file type to get cached mapping for
|
||||
* @param deduplicated - Whether to return deduplicated names for display
|
||||
* @returns The cached mapping or empty object
|
||||
*/
|
||||
getCachedMapping(fileType: FileType = 'input'): FileNameMapping {
|
||||
getCachedMapping(
|
||||
fileType: FileType = 'input',
|
||||
deduplicated: boolean = false
|
||||
): FileNameMapping {
|
||||
const cached = this.cache.get(fileType)
|
||||
if (cached && !this.isExpired(cached) && !cached.failed) {
|
||||
// Return deduplicated mapping if requested and available
|
||||
if (deduplicated && cached.dedupData) {
|
||||
return cached.dedupData
|
||||
}
|
||||
const result = cached.data
|
||||
console.debug(
|
||||
`[FileNameMapping] getCachedMapping returning cached data:`,
|
||||
{
|
||||
fileType,
|
||||
deduplicated,
|
||||
mappingCount: Object.keys(result).length,
|
||||
sampleMappings: Object.entries(result).slice(0, 3)
|
||||
}
|
||||
@@ -113,12 +123,14 @@ export class FileNameMappingService {
|
||||
/**
|
||||
* Get reverse mapping (human-readable name to hash) synchronously.
|
||||
* @param fileType - The file type to get reverse mapping for
|
||||
* @param deduplicated - Whether to use deduplicated names
|
||||
* @returns The reverse mapping object
|
||||
*/
|
||||
getCachedReverseMapping(
|
||||
fileType: FileType = 'input'
|
||||
fileType: FileType = 'input',
|
||||
deduplicated: boolean = false
|
||||
): Record<string, string> {
|
||||
const mapping = this.getCachedMapping(fileType)
|
||||
const mapping = this.getCachedMapping(fileType, deduplicated)
|
||||
const reverseMapping: Record<string, string> = {}
|
||||
|
||||
// Build reverse mapping: humanName -> hashName
|
||||
@@ -212,6 +224,7 @@ export class FileNameMappingService {
|
||||
|
||||
// Update cache with successful result
|
||||
entry.data = data
|
||||
entry.dedupData = this.deduplicateMapping(data)
|
||||
entry.timestamp = Date.now()
|
||||
entry.error = null
|
||||
entry.failed = false
|
||||
@@ -315,6 +328,73 @@ export class FileNameMappingService {
|
||||
// Allow retry after 30 seconds for failed requests
|
||||
return entry.timestamp > 0 && Date.now() - entry.timestamp > 30000
|
||||
}
|
||||
|
||||
/**
|
||||
* Deduplicate human-readable names when multiple hashes map to the same name.
|
||||
* Adds a suffix to duplicate names to make them unique.
|
||||
* @param mapping - The original hash -> human name mapping
|
||||
* @returns A new mapping with deduplicated human names
|
||||
*/
|
||||
private deduplicateMapping(mapping: FileNameMapping): FileNameMapping {
|
||||
const dedupMapping: FileNameMapping = {}
|
||||
const nameCount = new Map<string, number>()
|
||||
const nameToHashes = new Map<string, string[]>()
|
||||
|
||||
// First pass: count occurrences of each human name
|
||||
for (const [hash, humanName] of Object.entries(mapping)) {
|
||||
const count = nameCount.get(humanName) || 0
|
||||
nameCount.set(humanName, count + 1)
|
||||
|
||||
// Track which hashes map to this human name
|
||||
const hashes = nameToHashes.get(humanName) || []
|
||||
hashes.push(hash)
|
||||
nameToHashes.set(humanName, hashes)
|
||||
}
|
||||
|
||||
// Second pass: create deduplicated names
|
||||
const nameIndex = new Map<string, number>()
|
||||
|
||||
for (const [hash, humanName] of Object.entries(mapping)) {
|
||||
const count = nameCount.get(humanName) || 1
|
||||
|
||||
if (count === 1) {
|
||||
// No duplicates, use original name
|
||||
dedupMapping[hash] = humanName
|
||||
} else {
|
||||
// Has duplicates, add suffix
|
||||
const currentIndex = (nameIndex.get(humanName) || 0) + 1
|
||||
nameIndex.set(humanName, currentIndex)
|
||||
|
||||
// Extract file extension if present
|
||||
const lastDotIndex = humanName.lastIndexOf('.')
|
||||
let baseName = humanName
|
||||
let extension = ''
|
||||
|
||||
if (lastDotIndex > 0 && lastDotIndex < humanName.length - 1) {
|
||||
baseName = humanName.substring(0, lastDotIndex)
|
||||
extension = humanName.substring(lastDotIndex)
|
||||
}
|
||||
|
||||
// Add suffix: use first 8 chars of hash (without extension)
|
||||
// Remove extension from hash if present
|
||||
const hashWithoutExt = hash.includes('.')
|
||||
? hash.substring(0, hash.lastIndexOf('.'))
|
||||
: hash
|
||||
const hashSuffix = hashWithoutExt.substring(0, 8)
|
||||
dedupMapping[hash] = `${baseName}_${hashSuffix}${extension}`
|
||||
}
|
||||
}
|
||||
|
||||
console.debug('[FileNameMappingService] Deduplicated mapping:', {
|
||||
original: Object.keys(mapping).length,
|
||||
duplicates: Array.from(nameCount.entries()).filter(
|
||||
([_, count]) => count > 1
|
||||
),
|
||||
sample: Object.entries(dedupMapping).slice(0, 5)
|
||||
})
|
||||
|
||||
return dedupMapping
|
||||
}
|
||||
}
|
||||
|
||||
// Singleton instance
|
||||
|
||||
Reference in New Issue
Block a user