Files
ausboss-ComfyUI-AusBoss/js/notify/index.js
T
ausboss faf0462067 Stitch Inpaint: say when an outpaint comes back unpainted
An outpaint whose new area still shows the plain fill color used to come
back as a finished-looking picture with bars. Stitch Inpaint now measures
how much of the new area is still flat at the fill color, beyond what the
source picture itself has, and when a quarter of it (or half of any
checked frame) is left, says so in the console and in a toast.

The check lives in its own helper, works for images and video and for any
fill color, and stays quiet on dark scenes that are painted.
2026-09-29 17:51:01 -05:00

70 lines
2.8 KiB
JavaScript

// Notifications 🆎 — a soft two-note chime when the queue finishes, and a
// toast for the notices nodes send with their results.
//
// The chime is off by default (a sound nobody asked for is a surprise); one boolean
// setting turns it on. The chime is built once as a small WAV in memory
// and played through an ordinary audio element, so the pack ships no sound
// file and nothing is built until the first chime plays.
import { api } from "/scripts/api.js";
import { app } from "/scripts/app.js";
import { showToast } from "../shared/index.mjs";
import { noticesFromExecuted, queueRemaining, shouldChime } from "../shared/notify.mjs";
import { chimeSamples, wavBytes } from "./chime.mjs";
const SETTING_ID = "AusBoss.Notifications.CompletionSound";
let enabled = false;
// Start at 0 so a page opened onto an idle queue never chimes; the first
// queued prompt raises it and the run's final 0 triggers the chime.
let lastRemaining = 0;
let chimeUrl = null;
function playChime() {
try {
chimeUrl ??= URL.createObjectURL(new Blob([wavBytes(chimeSamples())], { type: "audio/wav" }));
// Queuing a prompt was a click, so the page may play sound by the time
// a run finishes; a refusal is swallowed like any other failure.
new Audio(chimeUrl).play()?.catch?.(() => {});
} catch (_error) {
// No audio device or playback blocked: the chime is advice, not a
// feature — never let it break the status stream.
}
}
app.registerExtension({
name: "AusBoss.Notify",
settings: [
{
id: SETTING_ID,
name: "Completion sound",
type: "boolean",
defaultValue: false,
tooltip:
"Plays a soft two-note chime when the prompt queue empties, so a "
+ "long video render can run in another window without being "
+ "watched. Off keeps ComfyUI silent.",
category: ["🆎 AusBoss", "Notifications", "Completion sound"],
onChange(value) {
enabled = !!value;
},
},
],
setup() {
// onChange only fires on later edits, so seed from the stored value here.
enabled = !!app.ui?.settings?.getSettingValue?.(SETTING_ID);
// Notices a node sends with its result (an outpaint that came back
// unpainted) show as a toast, so they are not lost in the console.
api.addEventListener("executed", (event) => {
for (const { source, text } of noticesFromExecuted(event?.detail)) {
showToast({ severity: "warn", summary: source ? `${source} \u{1F18E}` : "AusBoss", detail: text, life: 20000 });
}
});
api.addEventListener("status", (event) => {
const next = queueRemaining(event?.detail);
if (next === null) return; // disconnects and unknown shapes stay silent
if (shouldChime(enabled, lastRemaining, next)) playChime();
lastRemaining = next;
});
},
});