mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-21 20:52:12 -03:00
Replace matting status indicator with button spinner
Removed the MattingStatusIndicator class and replaced it with a spinner animation directly on the Matting button. The button now shows a loading spinner and disables itself during processing, improving user feedback and simplifying the UI.
This commit is contained in:
@@ -180,7 +180,40 @@ async function createCanvasWidget(node, widget, app) {
|
||||
/* Możesz też zmienić kolor istniejącej ramki, ale box-shadow jest bardziej wyrazisty */
|
||||
/* border-color: white; */
|
||||
}
|
||||
|
||||
|
||||
.painter-button.matting-button {
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.painter-button.matting-button.loading {
|
||||
padding-right: 36px; /* Make space for spinner */
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.painter-button.matting-button .matting-spinner {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
border-top-color: #fff;
|
||||
animation: matting-spin 1s linear infinite;
|
||||
}
|
||||
|
||||
.painter-button.matting-button.loading .matting-spinner {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@keyframes matting-spin {
|
||||
to {
|
||||
transform: translateY(-50%) rotate(360deg);
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
@@ -560,13 +593,18 @@ async function createCanvasWidget(node, widget, app) {
|
||||
$el("button.painter-button.requires-selection.matting-button", {
|
||||
textContent: "Matting",
|
||||
onclick: async (e) => {
|
||||
const statusIndicator = MattingStatusIndicator.getInstance(e.target.parentElement);
|
||||
const button = e.target;
|
||||
if (button.classList.contains('loading')) return;
|
||||
|
||||
const spinner = $el("div.matting-spinner");
|
||||
button.appendChild(spinner);
|
||||
button.classList.add('loading');
|
||||
button.disabled = true;
|
||||
|
||||
try {
|
||||
if (canvas.selectedLayers.length !== 1) {
|
||||
throw new Error("Please select exactly one image layer for matting.");
|
||||
}
|
||||
statusIndicator.setStatus('processing');
|
||||
|
||||
const selectedLayer = canvas.selectedLayers[0];
|
||||
const imageData = await canvas.getLayerImageData(selectedLayer);
|
||||
@@ -606,7 +644,6 @@ async function createCanvasWidget(node, widget, app) {
|
||||
|
||||
await canvas.saveToServer(widget.value);
|
||||
app.graph.runStep();
|
||||
statusIndicator.setStatus('completed');
|
||||
};
|
||||
newImage.src = result.matted_image;
|
||||
};
|
||||
@@ -618,7 +655,10 @@ async function createCanvasWidget(node, widget, app) {
|
||||
} catch (error) {
|
||||
console.error("Matting error:", error);
|
||||
alert(`Error during matting process: ${error.message}`);
|
||||
statusIndicator.setStatus('error');
|
||||
} finally {
|
||||
button.removeChild(spinner);
|
||||
button.classList.remove('loading');
|
||||
button.disabled = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -652,7 +692,7 @@ async function createCanvasWidget(node, widget, app) {
|
||||
btn.disabled = !hasSelection;
|
||||
});
|
||||
const mattingBtn = controlPanel.querySelector('.matting-button');
|
||||
if (mattingBtn) {
|
||||
if (mattingBtn && !mattingBtn.classList.contains('loading')) {
|
||||
mattingBtn.disabled = selectionCount !== 1;
|
||||
}
|
||||
};
|
||||
@@ -840,76 +880,6 @@ async function createCanvasWidget(node, widget, app) {
|
||||
};
|
||||
}
|
||||
|
||||
class MattingStatusIndicator {
|
||||
static instance = null;
|
||||
|
||||
static getInstance(container) {
|
||||
if (!MattingStatusIndicator.instance) {
|
||||
MattingStatusIndicator.instance = new MattingStatusIndicator(container);
|
||||
}
|
||||
if (container && !container.contains(MattingStatusIndicator.instance.indicator)) {
|
||||
container.appendChild(MattingStatusIndicator.instance.indicator);
|
||||
}
|
||||
return MattingStatusIndicator.instance;
|
||||
}
|
||||
|
||||
constructor(container) {
|
||||
this.statuses = ['processing', 'completed', 'error'];
|
||||
|
||||
this.indicator = document.createElement('div');
|
||||
this.indicator.className = 'matting-indicator';
|
||||
this.indicator.style.cssText = `
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
margin-left: 10px;
|
||||
display: inline-block;
|
||||
transition: background-color 0.3s ease;
|
||||
`;
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
/* Styl dla domyślnego stanu (szary) */
|
||||
.matting-indicator {
|
||||
background-color: #808080;
|
||||
}
|
||||
/* Style dla konkretnych statusów, które nadpiszą domyślny */
|
||||
.matting-indicator.processing {
|
||||
background-color: #FFC107; /* Żółty */
|
||||
animation: blink 1s infinite;
|
||||
}
|
||||
.matting-indicator.completed {
|
||||
background-color: #4CAF50; /* Zielony */
|
||||
}
|
||||
.matting-indicator.error {
|
||||
background-color: #f44336; /* Czerwony */
|
||||
}
|
||||
@keyframes blink {
|
||||
0% { opacity: 1; }
|
||||
50% { opacity: 0.4; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
if (container) {
|
||||
container.appendChild(this.indicator);
|
||||
}
|
||||
}
|
||||
|
||||
setStatus(status) {
|
||||
this.indicator.classList.remove(...this.statuses);
|
||||
if (status && this.statuses.includes(status)) {
|
||||
this.indicator.classList.add(status);
|
||||
}
|
||||
|
||||
if (status === 'completed' || status === 'error') {
|
||||
setTimeout(() => {
|
||||
this.indicator.classList.remove(status);
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateImageData(data) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user