Adds unified notification to send all types of notifications in the same node.

This commit is contained in:
Royce Schultz
2024-05-16 15:27:48 -06:00
parent 5f01d9bdac
commit 3eccfd82e8
4 changed files with 120 additions and 0 deletions
+3
View File
@@ -1,14 +1,17 @@
from .nodes.play_sound import PlaySound
from .nodes.system_notification import SystemNotification
from .nodes.unified_notification import UnifiedNotification
NODE_CLASS_MAPPINGS = {
"Notif-PlaySound": PlaySound,
"Notif-SystemNotification": SystemNotification,
"Notif-UnifiedNotification": UnifiedNotification,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"Notif-PlaySound": "Play Sound",
"Notif-SystemNotification": "System Notification",
"Notif-UnifiedNotification": "Unified Notification",
}
WEB_DIRECTORY = "./web"
+29
View File
@@ -0,0 +1,29 @@
from .util import ComfyAnyType
import json
class UnifiedNotification:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"any": (ComfyAnyType("*"), {}),
"mode": (["always", "on empty queue"], {}),
"system_notification": ("BOOLEAN", {"default": True}),
"notification_text": ('STRING', {'default': 'Your notification has triggered.'}),
"play_sound": ("BOOLEAN", {"default": True}),
"volume": ("FLOAT", {"min": 0, "max": 1, "step": 0.1, "default": 0.5}),
"file": ("STRING", { "default": "notify.mp3" }),
},
}
FUNCTION = "nop"
OUTPUT_NODE = True
RETURN_TYPES = tuple()
CATEGORY = "notifications"
def nop(self, *args, **kwargs):
for k, v in kwargs.items():
kwargs[k] = [v] # UI expects an iterable for some reason
del kwargs['any'] # Avoid passing large objects
kwargs['args'] = args
return {"ui": kwargs, "result": (0, )}
+36
View File
@@ -0,0 +1,36 @@
import { app } from '../../../scripts/app.js'
import {
notificationSetup, sendNotification, getNotificationTextFromArguments,
playSound,
appQueueIsEmpty,
} from './util.js'
app.registerExtension({
name: 'Notifications.UnifiedNotification',
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === 'Notif-UnifiedNotification') {
const onExecuted = nodeType.prototype.onExecuted
nodeType.prototype.onExecuted = async function () {
onExecuted?.apply(this, arguments)
const args = arguments[0] ?? {}
if (args.mode[0] === 'on empty queue') {
if(!await appQueueIsEmpty(app)) return
}
if (args.system_notification[0]) {
const notif_text = getNotificationTextFromArguments(arguments)
sendNotification('ComfyUI', notif_text)
}
if (args.play_sound[0]) {
playSound(args.file[0], args.volume[0] ?? 0.5)
}
}
const onNodeCreated = nodeType.prototype.onNodeCreated
nodeType.prototype.onNodeCreated = function () {
onNodeCreated?.apply(this, arguments)
notificationSetup()
}
}
},
})
+52
View File
@@ -0,0 +1,52 @@
export const notificationSetup = () => {
if (!('Notification' in window)) {
console.log('This browser does not support notifications.')
alert('This browser does not support notifications.')
return
}
if (Notification.permission === 'denied') {
console.log('Notifications are blocked. Please enable them in your browser settings.')
alert('Notifications are blocked. Please enable them in your browser settings.')
return
}
if (Notification.permission !== 'granted') {
Notification.requestPermission()
}
return true
}
export const sendNotification = (title, body) => {
if (!notificationSetup()) return
const notification = new Notification(title, { body })
return notification
}
export const getNotificationTextFromArguments = (args) => {
return args[0]?.notification_text[0] ?? 'Your notification has triggered.'
}
export const playSound = (file, volume) => {
if (!file) {
file = 'notify.mp3'
}
if (!file.startsWith('http')) {
if (!file.includes('/')) {
file = 'assets/' + file
}
file = new URL(file, import.meta.url)
}
const url = new URL(file)
const audio = new Audio(url)
audio.volume = volume
audio.play()
}
export const appQueueIsEmpty = async (app) => {
if (app.ui.lastQueueSize !== 0) {
await new Promise((r) => setTimeout(r, 500))
}
if (app.ui.lastQueueSize !== 0) {
return false
}
return true
}