mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-03 14:54:37 +00:00
Add notifications via websocket.
This commit is contained in:
committed by
Jennifer Weber
parent
23e881e220
commit
c27edb7e94
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import { debounce } from 'lodash'
|
||||
|
||||
import defaultClientFeatureFlags from '@/config/clientFeatureFlags.json'
|
||||
import type {
|
||||
@@ -16,6 +17,7 @@ import type {
|
||||
HistoryTaskItem,
|
||||
LogsRawResponse,
|
||||
LogsWsMessage,
|
||||
NotificationWsMessage,
|
||||
PendingTaskItem,
|
||||
ProgressStateWsMessage,
|
||||
ProgressTextWsMessage,
|
||||
@@ -37,6 +39,7 @@ import type {
|
||||
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
|
||||
import type { NodeExecutionId } from '@/types/nodeIdentification'
|
||||
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
|
||||
import { useToastStore } from '@/stores/toastStore'
|
||||
import { WorkflowTemplates } from '@/types/workflowTemplateTypes'
|
||||
|
||||
interface QueuePromptRequestBody {
|
||||
@@ -131,6 +134,7 @@ interface BackendApiCalls {
|
||||
progress_state: ProgressStateWsMessage
|
||||
display_component: DisplayComponentWsMessage
|
||||
feature_flags: FeatureFlagsWsMessage
|
||||
notification: NotificationWsMessage
|
||||
}
|
||||
|
||||
/** Dictionary of all api calls */
|
||||
@@ -272,6 +276,81 @@ export class ComfyApi extends EventTarget {
|
||||
* Feature flags received from the backend server.
|
||||
*/
|
||||
serverFeatureFlags: Record<string, unknown> = {}
|
||||
|
||||
/**
|
||||
* Map of notification toasts by ID
|
||||
*/
|
||||
#notificationToasts = new Map<string, any>()
|
||||
|
||||
/**
|
||||
* Map of timers for auto-hiding notifications by ID
|
||||
*/
|
||||
#notificationTimers = new Map<string, number>()
|
||||
|
||||
/**
|
||||
* Handle notification messages (with optional ID for multiple parallel notifications)
|
||||
*/
|
||||
#handleNotification(value: string, id?: string) {
|
||||
try {
|
||||
const toastStore = useToastStore()
|
||||
const notificationId = id || 'default'
|
||||
|
||||
console.log(`Updating notification (${notificationId}):`, value)
|
||||
|
||||
// Get existing toast for this ID
|
||||
const existingToast = this.#notificationToasts.get(notificationId)
|
||||
|
||||
if (existingToast) {
|
||||
// Update existing toast by removing and re-adding with new content
|
||||
console.log(`Updating existing notification toast: ${notificationId}`)
|
||||
toastStore.remove(existingToast)
|
||||
|
||||
// Update the detail text
|
||||
existingToast.detail = value
|
||||
toastStore.add(existingToast)
|
||||
} else {
|
||||
// Create new persistent notification toast
|
||||
console.log(`Creating new notification toast: ${notificationId}`)
|
||||
const newToast = {
|
||||
severity: 'info' as const,
|
||||
summary: 'Notification',
|
||||
detail: value,
|
||||
closable: true
|
||||
// No 'life' property means it won't auto-hide
|
||||
}
|
||||
this.#notificationToasts.set(notificationId, newToast)
|
||||
toastStore.add(newToast)
|
||||
}
|
||||
|
||||
// Clear existing timer for this ID and set new one
|
||||
const existingTimer = this.#notificationTimers.get(notificationId)
|
||||
if (existingTimer) {
|
||||
clearTimeout(existingTimer)
|
||||
}
|
||||
|
||||
const timer = window.setTimeout(() => {
|
||||
const toast = this.#notificationToasts.get(notificationId)
|
||||
if (toast) {
|
||||
console.log(`Auto-hiding notification toast: ${notificationId}`)
|
||||
toastStore.remove(toast)
|
||||
this.#notificationToasts.delete(notificationId)
|
||||
this.#notificationTimers.delete(notificationId)
|
||||
}
|
||||
}, 3000)
|
||||
|
||||
this.#notificationTimers.set(notificationId, timer)
|
||||
console.log('Toast updated successfully')
|
||||
} catch (error) {
|
||||
console.error('Error handling notification:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debounced notification handler to avoid rapid toast updates
|
||||
*/
|
||||
#debouncedNotificationHandler = debounce((value: string, id?: string) => {
|
||||
this.#handleNotification(value, id)
|
||||
}, 300) // 300ms debounce delay
|
||||
|
||||
/**
|
||||
* The auth token for the comfy org account if the user is logged in.
|
||||
@@ -596,6 +675,16 @@ export class ComfyApi extends EventTarget {
|
||||
this.serverFeatureFlags
|
||||
)
|
||||
break
|
||||
case 'notification':
|
||||
// Display notification in toast with debouncing
|
||||
console.log(
|
||||
'Received notification message:',
|
||||
msg.data.value,
|
||||
msg.data.id ? `(ID: ${msg.data.id})` : ''
|
||||
)
|
||||
this.#debouncedNotificationHandler(msg.data.value, msg.data.id)
|
||||
this.dispatchCustomEvent(msg.type, msg.data)
|
||||
break
|
||||
default:
|
||||
if (this.#registered.has(msg.type)) {
|
||||
// Fallback for custom types - calls super direct.
|
||||
@@ -621,6 +710,35 @@ export class ComfyApi extends EventTarget {
|
||||
this.#createSocket()
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method to simulate a notification message (for development/testing)
|
||||
*/
|
||||
testNotification(message: string = 'Test notification message', id?: string) {
|
||||
console.log(
|
||||
'Testing notification with message:',
|
||||
message,
|
||||
id ? `(ID: ${id})` : ''
|
||||
)
|
||||
const mockEvent = {
|
||||
data: JSON.stringify({
|
||||
type: 'notification',
|
||||
data: { value: message, id }
|
||||
})
|
||||
}
|
||||
|
||||
// Simulate the websocket message handler
|
||||
const msg = JSON.parse(mockEvent.data)
|
||||
if (msg.type === 'notification') {
|
||||
console.log(
|
||||
'Received notification message:',
|
||||
msg.data.value,
|
||||
msg.data.id ? `(ID: ${msg.data.id})` : ''
|
||||
)
|
||||
this.#debouncedNotificationHandler(msg.data.value, msg.data.id)
|
||||
this.dispatchCustomEvent(msg.type, msg.data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of extension urls
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user