Add clipboard source toggle for paste operations

Introduces a clipboardPreference setting to choose between system clipboard and ComfyUI Clipspace as the source for paste operations in CanvasLayers. Adds a UI button in CanvasView to toggle the clipboard source, improving user control over paste behavior.
This commit is contained in:
Dariusz L
2025-06-30 01:14:13 +02:00
parent 6718198a27
commit 2624cf02a2
2 changed files with 80 additions and 36 deletions

View File

@@ -27,6 +27,7 @@ export class CanvasLayers {
this.blendOpacity = 100; this.blendOpacity = 100;
this.isAdjustingOpacity = false; this.isAdjustingOpacity = false;
this.internalClipboard = []; this.internalClipboard = [];
this.clipboardPreference = 'system'; // 'system', 'clipspace'
} }
async copySelectedLayers() { async copySelectedLayers() {
@@ -86,46 +87,66 @@ export class CanvasLayers {
async handlePaste(addMode = 'mouse') { async handlePaste(addMode = 'mouse') {
try { try {
// 1. FIRST: Check Internal Clipboard log.info(`Paste operation started with preference: ${this.clipboardPreference}`);
// ALWAYS FIRST: Check Internal Clipboard
if (this.internalClipboard.length > 0) { if (this.internalClipboard.length > 0) {
log.info("Pasting from internal clipboard"); log.info("Pasting from internal clipboard");
this.pasteLayers(); this.pasteLayers();
return; return;
} }
// 2. SECOND: Try ComfyUI Clipspace // SECOND: Use preference setting
try { if (this.clipboardPreference === 'clipspace') {
log.info("Attempting to paste from ComfyUI Clipspace"); log.info("Attempting paste from ComfyUI Clipspace");
const clipspaceResult = ComfyApp.pasteFromClipspace(this.canvas.node); if (!await this.tryClipspacePaste(addMode)) {
log.info("No image found in ComfyUI Clipspace");
// Check if clipspace operation was successful and node has images
if (this.canvas.node.imgs && this.canvas.node.imgs.length > 0) {
const clipspaceImage = this.canvas.node.imgs[0];
if (clipspaceImage && clipspaceImage.src) {
log.info("Successfully got image from ComfyUI Clipspace");
const img = new Image();
img.onload = async () => {
await this.addLayerWithImage(img, {}, addMode);
};
img.src = clipspaceImage.src;
return;
}
} }
log.info("No image found in ComfyUI Clipspace, trying system clipboard"); } else if (this.clipboardPreference === 'system') {
} catch (clipspaceError) { log.info("Attempting paste from system clipboard");
log.warn("ComfyUI Clipspace paste failed:", clipspaceError); await this.trySystemClipboardPaste(addMode);
} }
// 3. THIRD: Try System Clipboard } catch (err) {
if (!navigator.clipboard?.read) { log.error("Paste operation failed:", err);
log.info("Browser does not support clipboard read API. No more options available."); }
return; }
}
async tryClipspacePaste(addMode) {
try {
log.info("Attempting to paste from ComfyUI Clipspace");
const clipspaceResult = ComfyApp.pasteFromClipspace(this.canvas.node);
// Check if clipspace operation was successful and node has images
if (this.canvas.node.imgs && this.canvas.node.imgs.length > 0) {
const clipspaceImage = this.canvas.node.imgs[0];
if (clipspaceImage && clipspaceImage.src) {
log.info("Successfully got image from ComfyUI Clipspace");
const img = new Image();
img.onload = async () => {
await this.addLayerWithImage(img, {}, addMode);
};
img.src = clipspaceImage.src;
return true;
}
}
return false;
} catch (clipspaceError) {
log.warn("ComfyUI Clipspace paste failed:", clipspaceError);
return false;
}
}
async trySystemClipboardPaste(addMode) {
if (!navigator.clipboard?.read) {
log.info("Browser does not support clipboard read API");
return false;
}
try {
log.info("Attempting to paste from system clipboard"); log.info("Attempting to paste from system clipboard");
const clipboardItems = await navigator.clipboard.read(); const clipboardItems = await navigator.clipboard.read();
let imagePasted = false;
for (const item of clipboardItems) { for (const item of clipboardItems) {
const imageType = item.types.find(type => type.startsWith('image/')); const imageType = item.types.find(type => type.startsWith('image/'));
@@ -140,18 +161,16 @@ export class CanvasLayers {
img.src = event.target.result; img.src = event.target.result;
}; };
reader.readAsDataURL(blob); reader.readAsDataURL(blob);
imagePasted = true;
log.info("Successfully pasted image from system clipboard"); log.info("Successfully pasted image from system clipboard");
break; return true;
} }
} }
if (!imagePasted) { log.info("No image found in system clipboard");
log.info("No image found in system clipboard. Paste operation completed with no result."); return false;
} } catch (error) {
log.warn("System clipboard paste failed:", error);
} catch (err) { return false;
log.error("Paste operation failed:", err);
} }
} }

View File

@@ -563,6 +563,31 @@ async function createCanvasWidget(node, widget, app) {
canvas.canvasLayers.handlePaste(addMode); canvas.canvasLayers.handlePaste(addMode);
} }
}), }),
$el("button.painter-button", {
id: `clipboard-toggle-${node.id}`,
textContent: "📋 System",
title: "Toggle clipboard source: System Clipboard",
style: {
minWidth: "100px",
fontSize: "11px",
backgroundColor: "#4a4a4a"
},
onclick: (e) => {
const button = e.target;
if (canvas.canvasLayers.clipboardPreference === 'system') {
canvas.canvasLayers.clipboardPreference = 'clipspace';
button.textContent = "📋 Clipspace";
button.title = "Toggle clipboard source: ComfyUI Clipspace";
button.style.backgroundColor = "#4a6cd4";
} else {
canvas.canvasLayers.clipboardPreference = 'system';
button.textContent = "📋 System";
button.title = "Toggle clipboard source: System Clipboard";
button.style.backgroundColor = "#4a4a4a";
}
log.info(`Clipboard preference toggled to: ${canvas.canvasLayers.clipboardPreference}`);
}
}),
]), ]),
$el("div.painter-separator"), $el("div.painter-separator"),