Option to control how notifications are shown
This commit is contained in:
@@ -990,7 +990,7 @@ export default class ComfyApp {
|
||||
tag = null;
|
||||
|
||||
if (targetWorkflow.attrs.showDefaultNotifications) {
|
||||
notify("Prompt queued.", { type: "info" });
|
||||
notify("Prompt queued.", { type: "info", showOn: "web" });
|
||||
}
|
||||
|
||||
this.processingQueue = true;
|
||||
|
||||
@@ -3,17 +3,20 @@ import notify from "$lib/notify";
|
||||
import { convertComfyOutputToGradio, type SerializedPromptOutput } from "$lib/utils";
|
||||
import { BuiltInSlotType, LiteGraph, type SlotLayout } from "@litegraph-ts/core";
|
||||
import ComfyGraphNode, { type ComfyGraphNodeProperties } from "../ComfyGraphNode";
|
||||
import configState from "$lib/stores/configState";
|
||||
|
||||
export interface ComfyNotifyActionProperties extends ComfyGraphNodeProperties {
|
||||
message: string,
|
||||
type: string
|
||||
type: string,
|
||||
alwaysShow: boolean
|
||||
}
|
||||
|
||||
export default class ComfyNotifyAction extends ComfyGraphNode {
|
||||
override properties: ComfyNotifyActionProperties = {
|
||||
tags: [],
|
||||
message: "Nya.",
|
||||
type: "info"
|
||||
type: "info",
|
||||
alwaysShow: false
|
||||
}
|
||||
|
||||
static slotLayout: SlotLayout = {
|
||||
@@ -24,6 +27,9 @@ export default class ComfyNotifyAction extends ComfyGraphNode {
|
||||
}
|
||||
|
||||
override onAction(action: any, param: any) {
|
||||
if (!configState.canShowNotificationText() && !this.properties.alwaysShow)
|
||||
return;
|
||||
|
||||
const message = this.getInputData(0) || this.properties.message;
|
||||
if (!message)
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { BuiltInSlotType, LiteGraph, type SlotLayout } from "@litegraph-ts/core";
|
||||
import ComfyGraphNode, { type ComfyGraphNodeProperties } from "../ComfyGraphNode";
|
||||
import { playSound } from "$lib/utils";
|
||||
import configState from "$lib/stores/configState";
|
||||
|
||||
export interface ComfyPlaySoundActionProperties extends ComfyGraphNodeProperties {
|
||||
sound: string,
|
||||
@@ -20,6 +21,9 @@ export default class ComfyPlaySoundAction extends ComfyGraphNode {
|
||||
}
|
||||
|
||||
override onAction(action: any, param: any) {
|
||||
if (!configState.canPlayNotificationSound())
|
||||
return;
|
||||
|
||||
const sound = this.getInputData(0) || this.properties.sound;
|
||||
if (sound) {
|
||||
playSound(sound)
|
||||
|
||||
@@ -84,6 +84,41 @@ const defComfyUIPort: ConfigDefNumber<"comfyUIPort"> = {
|
||||
}
|
||||
};
|
||||
|
||||
export enum NotificationState {
|
||||
MessageAndSound,
|
||||
MessageOnly,
|
||||
SoundOnly,
|
||||
None
|
||||
}
|
||||
|
||||
const defNotifications: ConfigDefEnum<"notifications", NotificationState> = {
|
||||
name: "notifications",
|
||||
type: "enum",
|
||||
defaultValue: NotificationState.MessageAndSound,
|
||||
category: "ui",
|
||||
description: "Controls how notifications are shown",
|
||||
options: {
|
||||
values: [
|
||||
{
|
||||
value: NotificationState.MessageAndSound,
|
||||
label: "Message & sound"
|
||||
},
|
||||
{
|
||||
value: NotificationState.MessageOnly,
|
||||
label: "Message only"
|
||||
},
|
||||
{
|
||||
value: NotificationState.SoundOnly,
|
||||
label: "Sound only"
|
||||
},
|
||||
{
|
||||
value: NotificationState.None,
|
||||
label: "None"
|
||||
},
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const defAlwaysStripUserState: ConfigDefBoolean<"alwaysStripUserState"> = {
|
||||
name: "alwaysStripUserState",
|
||||
type: "boolean",
|
||||
@@ -158,6 +193,7 @@ const defBuiltInTemplates: ConfigDefStringArray<"builtInTemplates"> = {
|
||||
export const CONFIG_DEFS = [
|
||||
defComfyUIHostname,
|
||||
defComfyUIPort,
|
||||
defNotifications,
|
||||
defAlwaysStripUserState,
|
||||
defPromptForWorkflowName,
|
||||
defConfirmWhenUnloadingUnsavedChanges,
|
||||
|
||||
@@ -2,10 +2,12 @@ import { debounce } from '$lib/utils';
|
||||
import { toHashMap } from '@litegraph-ts/core';
|
||||
import { get, writable } from 'svelte/store';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import { defaultConfig, type ConfigState, type ConfigDefAny, CONFIG_DEFS_BY_NAME, validateConfigOption } from './configDefs';
|
||||
import { defaultConfig, type ConfigState, type ConfigDefAny, CONFIG_DEFS_BY_NAME, validateConfigOption, NotificationState } from './configDefs';
|
||||
|
||||
type ConfigStateOps = {
|
||||
getBackendURL: () => string,
|
||||
canShowNotificationText: () => boolean,
|
||||
canPlayNotificationSound: () => boolean,
|
||||
|
||||
load: (data: any, runOnChanged?: boolean) => ConfigState
|
||||
loadDefault: (runOnChanged?: boolean) => ConfigState
|
||||
@@ -25,6 +27,17 @@ function getBackendURL(): string {
|
||||
return `${window.location.protocol}//${state.comfyUIHostname}:${state.comfyUIPort}`
|
||||
}
|
||||
|
||||
function canShowNotificationText(): boolean {
|
||||
const state = get(store).notifications;
|
||||
return state === NotificationState.MessageAndSound || state === NotificationState.MessageOnly;
|
||||
}
|
||||
|
||||
function canPlayNotificationSound(): boolean {
|
||||
const state = get(store).notifications;
|
||||
return state === NotificationState.MessageAndSound || state === NotificationState.SoundOnly;
|
||||
}
|
||||
|
||||
|
||||
function setConfigOption(def: ConfigDefAny, v: any, runOnChanged: boolean): boolean {
|
||||
let valid = false;
|
||||
store.update(state => {
|
||||
@@ -112,6 +125,9 @@ const configStateStore: WritableConfigStateStore =
|
||||
{
|
||||
...store,
|
||||
getBackendURL,
|
||||
canShowNotificationText,
|
||||
canPlayNotificationSound,
|
||||
|
||||
validateConfigOption,
|
||||
setConfigOption,
|
||||
load,
|
||||
|
||||
@@ -7,6 +7,7 @@ import { playSound } from "$lib/utils";
|
||||
import { get, writable, type Writable } from "svelte/store";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import workflowState, { type WorkflowError, type WorkflowExecutionError, type WorkflowInstID, type WorkflowValidationError } from "./workflowState";
|
||||
import configState from "./configState";
|
||||
|
||||
export type QueueEntryStatus = "success" | "validation_failed" | "error" | "interrupted" | "all_cached" | "unknown";
|
||||
|
||||
@@ -283,14 +284,18 @@ function executingUpdated(promptID: PromptID, runningNodeID: ComfyNodeID | null)
|
||||
if (entry != null) {
|
||||
const totalNodesInPrompt = Object.keys(entry.prompt).length
|
||||
if (entry.cachedNodes.size >= Object.keys(entry.prompt).length) {
|
||||
notify("Prompt was cached, nothing to run.", { type: "warning" })
|
||||
notify("Prompt was cached, nothing to run.", { type: "warning", showOn: "web" })
|
||||
moveToCompleted(index, queue, "all_cached", "(Execution was cached)");
|
||||
}
|
||||
else if (entry.nodesRan.size >= totalNodesInPrompt) {
|
||||
const workflow = workflowState.getWorkflow(entry.extraData.workflowID);
|
||||
if (workflow?.attrs.showDefaultNotifications) {
|
||||
notify("Prompt finished!", { type: "success" });
|
||||
playSound("notification.mp3")
|
||||
if (configState.canShowNotificationText()) {
|
||||
notify("Prompt finished!", { type: "success" });
|
||||
}
|
||||
if (configState.canPlayNotificationSound()) {
|
||||
playSound("notification.mp3")
|
||||
}
|
||||
}
|
||||
moveToCompleted(index, queue, "success")
|
||||
}
|
||||
|
||||
@@ -635,6 +635,9 @@ export function nextLetter(s: string): string {
|
||||
}
|
||||
|
||||
export function playSound(sound: string) {
|
||||
if (!configState.canPlayNotificationSound())
|
||||
return;
|
||||
|
||||
const url = `${location.origin}/sound/${sound}`;
|
||||
const audio = new Audio(url);
|
||||
audio.play();
|
||||
|
||||
Reference in New Issue
Block a user