API-Endpoint /audiocraft/delete im Backend. Löscht die Datei und die zugehörige upsampled Version. Gelöschte Zeilen werden ausgegraut. Stoppt Wiedergabe falls die Datei gerade spielt. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
173 lines
6.7 KiB
JavaScript
173 lines
6.7 KiB
JavaScript
import { app } from "../../../scripts/app.js";
|
|
import { api } from "../../../scripts/api.js";
|
|
|
|
let loopEnabled = false;
|
|
|
|
app.registerExtension({
|
|
name: "AudioCraft.AudioManager",
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
if (nodeData.name === "AudioManager") {
|
|
const onExecuted = nodeType.prototype.onExecuted;
|
|
nodeType.prototype.onExecuted = function (message) {
|
|
onExecuted?.apply(this, arguments);
|
|
|
|
if (!message?.text) return;
|
|
|
|
const summary = message.text[0]?.content || "";
|
|
const files = message.files || [];
|
|
|
|
if (this._managerWidget) {
|
|
this._managerContainer.innerHTML = "";
|
|
buildContent(this._managerContainer, summary, files);
|
|
} else {
|
|
const container = document.createElement("div");
|
|
container.style.cssText = "padding:4px;overflow-y:auto;";
|
|
buildContent(container, summary, files);
|
|
|
|
this._managerContainer = container;
|
|
this._managerWidget = this.addDOMWidget("audio_manager", "dom", container, {
|
|
serialize: false,
|
|
hideOnZoom: false,
|
|
});
|
|
}
|
|
|
|
const listHeight = Math.min(40 + files.length * 26, 800);
|
|
this._managerWidget.computeSize = () => [this.size[0], listHeight];
|
|
this.setSize([Math.max(this.size[0], 500), listHeight + 80]);
|
|
app.graph.setDirtyCanvas(true);
|
|
};
|
|
}
|
|
},
|
|
});
|
|
|
|
// Track currently playing audio globally so only one plays at a time
|
|
let activeAudio = null;
|
|
let activeBtn = null;
|
|
|
|
function stopActive() {
|
|
if (activeAudio) {
|
|
activeAudio.pause();
|
|
activeAudio = null;
|
|
}
|
|
if (activeBtn) {
|
|
activeBtn.textContent = "\u25B6";
|
|
activeBtn.style.color = "#8f8";
|
|
activeBtn = null;
|
|
}
|
|
}
|
|
|
|
function buildContent(container, summary, files) {
|
|
// Header with summary + loop toggle
|
|
const headerRow = document.createElement("div");
|
|
headerRow.style.cssText = "display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;padding:4px;background:#333;border-radius:4px;";
|
|
|
|
const headerText = document.createElement("span");
|
|
headerText.textContent = summary;
|
|
headerText.style.cssText = "font-weight:bold;color:#fff;font-size:13px;";
|
|
|
|
const loopBtn = document.createElement("button");
|
|
loopBtn.textContent = loopEnabled ? "\uD83D\uDD01 Loop AN" : "\uD83D\uDD01 Loop AUS";
|
|
loopBtn.style.cssText = `background:${loopEnabled ? "#2a5a2a" : "#444"};border:none;color:${loopEnabled ? "#8f8" : "#888"};cursor:pointer;padding:3px 8px;border-radius:3px;font-size:11px;`;
|
|
loopBtn.onclick = () => {
|
|
loopEnabled = !loopEnabled;
|
|
loopBtn.textContent = loopEnabled ? "\uD83D\uDD01 Loop AN" : "\uD83D\uDD01 Loop AUS";
|
|
loopBtn.style.background = loopEnabled ? "#2a5a2a" : "#444";
|
|
loopBtn.style.color = loopEnabled ? "#8f8" : "#888";
|
|
if (activeAudio) {
|
|
activeAudio.loop = loopEnabled;
|
|
}
|
|
};
|
|
|
|
headerRow.appendChild(headerText);
|
|
headerRow.appendChild(loopBtn);
|
|
container.appendChild(headerRow);
|
|
|
|
if (files.length === 0) return;
|
|
|
|
for (const f of files) {
|
|
const row = document.createElement("div");
|
|
row.style.cssText = "display:flex;align-items:center;padding:3px 2px;font-size:11px;color:#ccc;border-bottom:1px solid #333;min-height:22px;";
|
|
|
|
const name = document.createElement("span");
|
|
name.textContent = f.name;
|
|
name.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;margin-right:6px;";
|
|
|
|
const size = document.createElement("span");
|
|
size.textContent = f.size_mb + " MB";
|
|
size.style.cssText = "color:#8cf;min-width:55px;text-align:right;margin-right:6px;font-size:10px;";
|
|
|
|
const playBtn = document.createElement("button");
|
|
playBtn.textContent = "\u25B6";
|
|
playBtn.title = "Abspielen";
|
|
playBtn.style.cssText = "background:#444;border:none;color:#8f8;cursor:pointer;padding:2px 8px;border-radius:3px;font-size:11px;margin-right:4px;";
|
|
|
|
const audioSrc = api.apiURL(
|
|
`/view?filename=${encodeURIComponent(f.name)}&subfolder=audio&type=output`
|
|
);
|
|
|
|
const dlBtn = document.createElement("a");
|
|
dlBtn.href = audioSrc;
|
|
dlBtn.download = f.name;
|
|
dlBtn.textContent = "\u2B07";
|
|
dlBtn.title = "Download";
|
|
dlBtn.style.cssText = "color:#8cf;text-decoration:none;font-size:13px;padding:0 4px;";
|
|
|
|
playBtn.onclick = () => {
|
|
// If clicking the same button that's playing, stop it
|
|
if (activeBtn === playBtn) {
|
|
stopActive();
|
|
return;
|
|
}
|
|
// Stop any other playing audio first
|
|
stopActive();
|
|
|
|
const audio = new Audio(audioSrc);
|
|
audio.loop = loopEnabled;
|
|
audio.play();
|
|
activeAudio = audio;
|
|
activeBtn = playBtn;
|
|
playBtn.textContent = "\u25A0";
|
|
playBtn.style.color = "#f88";
|
|
|
|
audio.onended = () => {
|
|
if (!audio.loop) {
|
|
playBtn.textContent = "\u25B6";
|
|
playBtn.style.color = "#8f8";
|
|
activeAudio = null;
|
|
activeBtn = null;
|
|
}
|
|
};
|
|
};
|
|
|
|
const delBtn = document.createElement("button");
|
|
delBtn.textContent = "\u2716";
|
|
delBtn.title = "Loeschen";
|
|
delBtn.style.cssText = "background:#533;border:none;color:#f66;cursor:pointer;padding:2px 6px;border-radius:3px;font-size:11px;margin-left:4px;";
|
|
delBtn.onclick = async () => {
|
|
// Stop if this file is playing
|
|
if (activeBtn === playBtn) stopActive();
|
|
try {
|
|
const resp = await api.fetchApi("/audiocraft/delete", {
|
|
method: "POST",
|
|
headers: {"Content-Type": "application/json"},
|
|
body: JSON.stringify({filename: f.name}),
|
|
});
|
|
if (resp.ok) {
|
|
row.style.opacity = "0.3";
|
|
row.style.pointerEvents = "none";
|
|
delBtn.textContent = "\u2714";
|
|
delBtn.style.color = "#888";
|
|
}
|
|
} catch (e) {
|
|
console.error("Delete failed:", e);
|
|
}
|
|
};
|
|
|
|
row.appendChild(name);
|
|
row.appendChild(size);
|
|
row.appendChild(playBtn);
|
|
row.appendChild(dlBtn);
|
|
row.appendChild(delBtn);
|
|
container.appendChild(row);
|
|
}
|
|
}
|