mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-25 06:22:14 -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 */
|
/* Możesz też zmienić kolor istniejącej ramki, ale box-shadow jest bardziej wyrazisty */
|
||||||
/* border-color: white; */
|
/* 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);
|
document.head.appendChild(style);
|
||||||
|
|
||||||
@@ -560,13 +593,18 @@ async function createCanvasWidget(node, widget, app) {
|
|||||||
$el("button.painter-button.requires-selection.matting-button", {
|
$el("button.painter-button.requires-selection.matting-button", {
|
||||||
textContent: "Matting",
|
textContent: "Matting",
|
||||||
onclick: async (e) => {
|
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 {
|
try {
|
||||||
if (canvas.selectedLayers.length !== 1) {
|
if (canvas.selectedLayers.length !== 1) {
|
||||||
throw new Error("Please select exactly one image layer for matting.");
|
throw new Error("Please select exactly one image layer for matting.");
|
||||||
}
|
}
|
||||||
statusIndicator.setStatus('processing');
|
|
||||||
|
|
||||||
const selectedLayer = canvas.selectedLayers[0];
|
const selectedLayer = canvas.selectedLayers[0];
|
||||||
const imageData = await canvas.getLayerImageData(selectedLayer);
|
const imageData = await canvas.getLayerImageData(selectedLayer);
|
||||||
@@ -606,7 +644,6 @@ async function createCanvasWidget(node, widget, app) {
|
|||||||
|
|
||||||
await canvas.saveToServer(widget.value);
|
await canvas.saveToServer(widget.value);
|
||||||
app.graph.runStep();
|
app.graph.runStep();
|
||||||
statusIndicator.setStatus('completed');
|
|
||||||
};
|
};
|
||||||
newImage.src = result.matted_image;
|
newImage.src = result.matted_image;
|
||||||
};
|
};
|
||||||
@@ -618,7 +655,10 @@ async function createCanvasWidget(node, widget, app) {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Matting error:", error);
|
console.error("Matting error:", error);
|
||||||
alert(`Error during matting process: ${error.message}`);
|
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;
|
btn.disabled = !hasSelection;
|
||||||
});
|
});
|
||||||
const mattingBtn = controlPanel.querySelector('.matting-button');
|
const mattingBtn = controlPanel.querySelector('.matting-button');
|
||||||
if (mattingBtn) {
|
if (mattingBtn && !mattingBtn.classList.contains('loading')) {
|
||||||
mattingBtn.disabled = selectionCount !== 1;
|
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) {
|
function validateImageData(data) {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user