mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-25 14:25:44 -03:00
Replace alert with notification utilities and refactor canvas creation
Replaces all uses of alert() with showErrorNotification or showSuccessNotification for improved user experience and consistency. Refactors canvas creation to use the createCanvas utility function across multiple files, reducing code duplication and improving maintainability. Also updates layer ID generation to use generateUUID.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { createCanvas } from "./utils/CommonUtils.js";
|
import { createCanvas } from "./utils/CommonUtils.js";
|
||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
|
import { showErrorNotification } from "./utils/NotificationUtils.js";
|
||||||
import { webSocketManager } from "./utils/WebSocketManager.js";
|
import { webSocketManager } from "./utils/WebSocketManager.js";
|
||||||
const log = createModuleLogger('CanvasIO');
|
const log = createModuleLogger('CanvasIO');
|
||||||
export class CanvasIO {
|
export class CanvasIO {
|
||||||
@@ -525,7 +526,7 @@ export class CanvasIO {
|
|||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
log.error("Error importing latest image:", error);
|
log.error("Error importing latest image:", error);
|
||||||
alert(`Failed to import latest image: ${error.message}`);
|
showErrorNotification(`Failed to import latest image: ${error.message}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -565,7 +566,7 @@ export class CanvasIO {
|
|||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
log.error("Error importing latest images:", error);
|
log.error("Error importing latest images:", error);
|
||||||
alert(`Failed to import latest images: ${error.message}`);
|
showErrorNotification(`Failed to import latest images: ${error.message}`);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { saveImage } from "./db.js";
|
import { saveImage } from "./db.js";
|
||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
import { generateUUID, generateUniqueFileName } from "./utils/CommonUtils.js";
|
import { generateUUID, generateUniqueFileName, createCanvas } from "./utils/CommonUtils.js";
|
||||||
import { withErrorHandling, createValidationError } from "./ErrorHandler.js";
|
import { withErrorHandling, createValidationError } from "./ErrorHandler.js";
|
||||||
|
import { showErrorNotification } from "./utils/NotificationUtils.js";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { app } from "../../scripts/app.js";
|
import { app } from "../../scripts/app.js";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -63,17 +64,11 @@ export class CanvasLayers {
|
|||||||
...layerProps
|
...layerProps
|
||||||
};
|
};
|
||||||
if (layer.mask) {
|
if (layer.mask) {
|
||||||
const tempCanvas = document.createElement('canvas');
|
const { canvas: tempCanvas, ctx: tempCtx } = createCanvas(layer.width, layer.height);
|
||||||
const tempCtx = tempCanvas.getContext('2d');
|
|
||||||
if (tempCtx) {
|
if (tempCtx) {
|
||||||
tempCanvas.width = layer.width;
|
|
||||||
tempCanvas.height = layer.height;
|
|
||||||
tempCtx.drawImage(layer.image, 0, 0, layer.width, layer.height);
|
tempCtx.drawImage(layer.image, 0, 0, layer.width, layer.height);
|
||||||
const maskCanvas = document.createElement('canvas');
|
const { canvas: maskCanvas, ctx: maskCtx } = createCanvas(layer.width, layer.height);
|
||||||
const maskCtx = maskCanvas.getContext('2d');
|
|
||||||
if (maskCtx) {
|
if (maskCtx) {
|
||||||
maskCanvas.width = layer.width;
|
|
||||||
maskCanvas.height = layer.height;
|
|
||||||
const maskImageData = maskCtx.createImageData(layer.width, layer.height);
|
const maskImageData = maskCtx.createImageData(layer.width, layer.height);
|
||||||
for (let i = 0; i < layer.mask.length; i++) {
|
for (let i = 0; i < layer.mask.length; i++) {
|
||||||
maskImageData.data[i * 4] = 255;
|
maskImageData.data[i * 4] = 255;
|
||||||
@@ -371,10 +366,7 @@ export class CanvasLayers {
|
|||||||
let maskCanvas = this.getDistanceFieldMask(layer.image, blendArea);
|
let maskCanvas = this.getDistanceFieldMask(layer.image, blendArea);
|
||||||
if (maskCanvas) {
|
if (maskCanvas) {
|
||||||
// Create a temporary canvas for the masked layer
|
// Create a temporary canvas for the masked layer
|
||||||
const tempCanvas = document.createElement('canvas');
|
const { canvas: tempCanvas, ctx: tempCtx } = createCanvas(layer.width, layer.height);
|
||||||
tempCanvas.width = layer.width;
|
|
||||||
tempCanvas.height = layer.height;
|
|
||||||
const tempCtx = tempCanvas.getContext('2d');
|
|
||||||
if (tempCtx) {
|
if (tempCtx) {
|
||||||
// Draw the original image
|
// Draw the original image
|
||||||
tempCtx.drawImage(layer.image, 0, 0, layer.width, layer.height);
|
tempCtx.drawImage(layer.image, 0, 0, layer.width, layer.height);
|
||||||
@@ -978,7 +970,7 @@ export class CanvasLayers {
|
|||||||
}
|
}
|
||||||
async fuseLayers() {
|
async fuseLayers() {
|
||||||
if (this.canvas.canvasSelection.selectedLayers.length < 2) {
|
if (this.canvas.canvasSelection.selectedLayers.length < 2) {
|
||||||
alert("Please select at least 2 layers to fuse.");
|
showErrorNotification("Please select at least 2 layers to fuse.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.info(`Fusing ${this.canvas.canvasSelection.selectedLayers.length} selected layers`);
|
log.info(`Fusing ${this.canvas.canvasSelection.selectedLayers.length} selected layers`);
|
||||||
@@ -1012,7 +1004,7 @@ export class CanvasLayers {
|
|||||||
const fusedHeight = Math.ceil(maxY - minY);
|
const fusedHeight = Math.ceil(maxY - minY);
|
||||||
if (fusedWidth <= 0 || fusedHeight <= 0) {
|
if (fusedWidth <= 0 || fusedHeight <= 0) {
|
||||||
log.warn("Calculated fused layer dimensions are invalid");
|
log.warn("Calculated fused layer dimensions are invalid");
|
||||||
alert("Cannot fuse layers: invalid dimensions calculated.");
|
showErrorNotification("Cannot fuse layers: invalid dimensions calculated.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const tempCanvas = document.createElement('canvas');
|
const tempCanvas = document.createElement('canvas');
|
||||||
@@ -1070,7 +1062,7 @@ export class CanvasLayers {
|
|||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
log.error("Error during layer fusion:", error);
|
log.error("Error during layer fusion:", error);
|
||||||
alert(`Error fusing layers: ${error.message}`);
|
showErrorNotification(`Error fusing layers: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
|
import { generateUUID } from "./utils/CommonUtils.js";
|
||||||
const log = createModuleLogger('CanvasSelection');
|
const log = createModuleLogger('CanvasSelection');
|
||||||
export class CanvasSelection {
|
export class CanvasSelection {
|
||||||
constructor(canvas) {
|
constructor(canvas) {
|
||||||
@@ -18,7 +19,7 @@ export class CanvasSelection {
|
|||||||
sortedLayers.forEach(layer => {
|
sortedLayers.forEach(layer => {
|
||||||
const newLayer = {
|
const newLayer = {
|
||||||
...layer,
|
...layer,
|
||||||
id: `layer_${+new Date()}_${Math.random().toString(36).substr(2, 9)}`,
|
id: generateUUID(),
|
||||||
zIndex: this.canvas.layers.length, // Nowa warstwa zawsze na wierzchu
|
zIndex: this.canvas.layers.length, // Nowa warstwa zawsze na wierzchu
|
||||||
};
|
};
|
||||||
this.canvas.layers.push(newLayer);
|
this.canvas.layers.push(newLayer);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Canvas } from "./Canvas.js";
|
|||||||
import { clearAllCanvasStates } from "./db.js";
|
import { clearAllCanvasStates } from "./db.js";
|
||||||
import { ImageCache } from "./ImageCache.js";
|
import { ImageCache } from "./ImageCache.js";
|
||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
|
import { showErrorNotification, showSuccessNotification } from "./utils/NotificationUtils.js";
|
||||||
import { iconLoader, LAYERFORGE_TOOLS } from "./utils/IconLoader.js";
|
import { iconLoader, LAYERFORGE_TOOLS } from "./utils/IconLoader.js";
|
||||||
import { setupSAMDetectorHook } from "./SAMDetectorIntegration.js";
|
import { setupSAMDetectorHook } from "./SAMDetectorIntegration.js";
|
||||||
const log = createModuleLogger('Canvas_view');
|
const log = createModuleLogger('Canvas_view');
|
||||||
@@ -488,11 +489,11 @@ async function createCanvasWidget(node, widget, app) {
|
|||||||
await canvas.imageReferenceManager.manualGarbageCollection();
|
await canvas.imageReferenceManager.manualGarbageCollection();
|
||||||
const newStats = canvas.imageReferenceManager.getStats();
|
const newStats = canvas.imageReferenceManager.getStats();
|
||||||
log.info("GC Stats after cleanup:", newStats);
|
log.info("GC Stats after cleanup:", newStats);
|
||||||
alert(`Garbage collection completed!\nTracked images: ${newStats.trackedImages}\nTotal references: ${newStats.totalReferences}\nOperations: ${canvas.imageReferenceManager.operationCount}/${canvas.imageReferenceManager.operationThreshold}`);
|
showSuccessNotification(`Garbage collection completed!\nTracked images: ${newStats.trackedImages}\nTotal references: ${newStats.totalReferences}\nOperations: ${canvas.imageReferenceManager.operationCount}/${canvas.imageReferenceManager.operationThreshold}`);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log.error("Failed to run garbage collection:", e);
|
log.error("Failed to run garbage collection:", e);
|
||||||
alert("Error running garbage collection. Check the console for details.");
|
showErrorNotification("Error running garbage collection. Check the console for details.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -504,11 +505,11 @@ async function createCanvasWidget(node, widget, app) {
|
|||||||
if (confirm("Are you sure you want to clear all saved canvas states? This action cannot be undone.")) {
|
if (confirm("Are you sure you want to clear all saved canvas states? This action cannot be undone.")) {
|
||||||
try {
|
try {
|
||||||
await clearAllCanvasStates();
|
await clearAllCanvasStates();
|
||||||
alert("Canvas cache cleared successfully!");
|
showSuccessNotification("Canvas cache cleared successfully!");
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log.error("Failed to clear canvas cache:", e);
|
log.error("Failed to clear canvas cache:", e);
|
||||||
alert("Error clearing canvas cache. Check the console for details.");
|
showErrorNotification("Error clearing canvas cache. Check the console for details.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -845,8 +846,8 @@ function showErrorDialog(message, details) {
|
|||||||
textContent: "Copy Details",
|
textContent: "Copy Details",
|
||||||
onclick: () => {
|
onclick: () => {
|
||||||
navigator.clipboard.writeText(details)
|
navigator.clipboard.writeText(details)
|
||||||
.then(() => alert("Error details copied to clipboard!"))
|
.then(() => showSuccessNotification("Error details copied to clipboard!"))
|
||||||
.catch(err => alert("Failed to copy details: " + err));
|
.catch(err => showErrorNotification("Failed to copy details: " + err));
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
$el("button", {
|
$el("button", {
|
||||||
@@ -885,7 +886,7 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
log.error("Failed to send canvas data for one or more nodes. Aborting prompt.", error);
|
log.error("Failed to send canvas data for one or more nodes. Aborting prompt.", error);
|
||||||
alert(`CanvasNode Error: ${error.message}`);
|
showErrorNotification(`CanvasNode Error: ${error.message}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1043,12 +1044,12 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.error("Canvas widget not available");
|
log.error("Canvas widget not available");
|
||||||
alert("Canvas not ready. Please try again.");
|
showErrorNotification("Canvas not ready. Please try again.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log.error("Error opening MaskEditor:", e);
|
log.error("Error opening MaskEditor:", e);
|
||||||
alert(`Failed to open MaskEditor: ${e.message}`);
|
showErrorNotification(`Failed to open MaskEditor: ${e.message}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1103,7 +1104,7 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log.error("Error copying image:", e);
|
log.error("Error copying image:", e);
|
||||||
alert("Failed to copy image to clipboard.");
|
showErrorNotification("Failed to copy image to clipboard.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1122,7 +1123,7 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log.error("Error copying image with mask:", e);
|
log.error("Error copying image with mask:", e);
|
||||||
alert("Failed to copy image with mask to clipboard.");
|
showErrorNotification("Failed to copy image with mask to clipboard.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { app } from "../../scripts/app.js";
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { ComfyApp } from "../../scripts/app.js";
|
import { ComfyApp } from "../../scripts/app.js";
|
||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
|
import { showErrorNotification } from "./utils/NotificationUtils.js";
|
||||||
import { uploadImageBlob } from "./utils/ImageUploadUtils.js";
|
import { uploadImageBlob } from "./utils/ImageUploadUtils.js";
|
||||||
import { processImageToMask, processMaskForViewport } from "./utils/MaskProcessingUtils.js";
|
import { processImageToMask, processMaskForViewport } from "./utils/MaskProcessingUtils.js";
|
||||||
import { convertToImage } from "./utils/ImageUtils.js";
|
import { convertToImage } from "./utils/ImageUtils.js";
|
||||||
@@ -77,7 +78,7 @@ export class MaskEditorIntegration {
|
|||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
log.error("Error preparing image for mask editor:", error);
|
log.error("Error preparing image for mask editor:", error);
|
||||||
alert(`Error: ${error.message}`);
|
showErrorNotification(`Error: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
|
import { createCanvas } from "./utils/CommonUtils.js";
|
||||||
const log = createModuleLogger('Mask_tool');
|
const log = createModuleLogger('Mask_tool');
|
||||||
export class MaskTool {
|
export class MaskTool {
|
||||||
constructor(canvasInstance, callbacks = {}) {
|
constructor(canvasInstance, callbacks = {}) {
|
||||||
@@ -396,10 +397,7 @@ export class MaskTool {
|
|||||||
* Creates a canvas with specified dimensions and returns both canvas and context
|
* Creates a canvas with specified dimensions and returns both canvas and context
|
||||||
*/
|
*/
|
||||||
createCanvas(width, height) {
|
createCanvas(width, height) {
|
||||||
const canvas = document.createElement('canvas');
|
const { canvas, ctx } = createCanvas(width, height, '2d', { willReadFrequently: true });
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
const ctx = canvas.getContext('2d', { willReadFrequently: true });
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
throw new Error("Failed to get 2D context for canvas");
|
throw new Error("Failed to get 2D context for canvas");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createCanvas } from "./utils/CommonUtils.js";
|
import { createCanvas } from "./utils/CommonUtils.js";
|
||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
|
import { showErrorNotification } from "./utils/NotificationUtils.js";
|
||||||
import { webSocketManager } from "./utils/WebSocketManager.js";
|
import { webSocketManager } from "./utils/WebSocketManager.js";
|
||||||
import type { Canvas } from './Canvas';
|
import type { Canvas } from './Canvas';
|
||||||
import type { Layer, Shape } from './types';
|
import type { Layer, Shape } from './types';
|
||||||
@@ -611,7 +612,7 @@ export class CanvasIO {
|
|||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
log.error("Error importing latest image:", error);
|
log.error("Error importing latest image:", error);
|
||||||
alert(`Failed to import latest image: ${error.message}`);
|
showErrorNotification(`Failed to import latest image: ${error.message}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -655,7 +656,7 @@ export class CanvasIO {
|
|||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
log.error("Error importing latest images:", error);
|
log.error("Error importing latest images:", error);
|
||||||
alert(`Failed to import latest images: ${error.message}`);
|
showErrorNotification(`Failed to import latest images: ${error.message}`);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import {saveImage, removeImage} from "./db.js";
|
import {saveImage, removeImage} from "./db.js";
|
||||||
import {createModuleLogger} from "./utils/LoggerUtils.js";
|
import {createModuleLogger} from "./utils/LoggerUtils.js";
|
||||||
import {generateUUID, generateUniqueFileName} from "./utils/CommonUtils.js";
|
import {generateUUID, generateUniqueFileName, createCanvas} from "./utils/CommonUtils.js";
|
||||||
import {withErrorHandling, createValidationError} from "./ErrorHandler.js";
|
import {withErrorHandling, createValidationError} from "./ErrorHandler.js";
|
||||||
|
import {showErrorNotification, showSuccessNotification} from "./utils/NotificationUtils.js";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {app} from "../../scripts/app.js";
|
import {app} from "../../scripts/app.js";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -223,18 +224,12 @@ export class CanvasLayers {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (layer.mask) {
|
if (layer.mask) {
|
||||||
const tempCanvas = document.createElement('canvas');
|
const { canvas: tempCanvas, ctx: tempCtx } = createCanvas(layer.width, layer.height);
|
||||||
const tempCtx = tempCanvas.getContext('2d');
|
|
||||||
if(tempCtx) {
|
if(tempCtx) {
|
||||||
tempCanvas.width = layer.width;
|
|
||||||
tempCanvas.height = layer.height;
|
|
||||||
tempCtx.drawImage(layer.image, 0, 0, layer.width, layer.height);
|
tempCtx.drawImage(layer.image, 0, 0, layer.width, layer.height);
|
||||||
|
|
||||||
const maskCanvas = document.createElement('canvas');
|
const { canvas: maskCanvas, ctx: maskCtx } = createCanvas(layer.width, layer.height);
|
||||||
const maskCtx = maskCanvas.getContext('2d');
|
|
||||||
if(maskCtx) {
|
if(maskCtx) {
|
||||||
maskCanvas.width = layer.width;
|
|
||||||
maskCanvas.height = layer.height;
|
|
||||||
const maskImageData = maskCtx.createImageData(layer.width, layer.height);
|
const maskImageData = maskCtx.createImageData(layer.width, layer.height);
|
||||||
for (let i = 0; i < layer.mask.length; i++) {
|
for (let i = 0; i < layer.mask.length; i++) {
|
||||||
maskImageData.data[i * 4] = 255;
|
maskImageData.data[i * 4] = 255;
|
||||||
@@ -432,10 +427,7 @@ export class CanvasLayers {
|
|||||||
|
|
||||||
if (maskCanvas) {
|
if (maskCanvas) {
|
||||||
// Create a temporary canvas for the masked layer
|
// Create a temporary canvas for the masked layer
|
||||||
const tempCanvas = document.createElement('canvas');
|
const { canvas: tempCanvas, ctx: tempCtx } = createCanvas(layer.width, layer.height);
|
||||||
tempCanvas.width = layer.width;
|
|
||||||
tempCanvas.height = layer.height;
|
|
||||||
const tempCtx = tempCanvas.getContext('2d');
|
|
||||||
|
|
||||||
if (tempCtx) {
|
if (tempCtx) {
|
||||||
// Draw the original image
|
// Draw the original image
|
||||||
@@ -1136,7 +1128,7 @@ export class CanvasLayers {
|
|||||||
|
|
||||||
async fuseLayers(): Promise<void> {
|
async fuseLayers(): Promise<void> {
|
||||||
if (this.canvas.canvasSelection.selectedLayers.length < 2) {
|
if (this.canvas.canvasSelection.selectedLayers.length < 2) {
|
||||||
alert("Please select at least 2 layers to fuse.");
|
showErrorNotification("Please select at least 2 layers to fuse.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1178,7 +1170,7 @@ export class CanvasLayers {
|
|||||||
|
|
||||||
if (fusedWidth <= 0 || fusedHeight <= 0) {
|
if (fusedWidth <= 0 || fusedHeight <= 0) {
|
||||||
log.warn("Calculated fused layer dimensions are invalid");
|
log.warn("Calculated fused layer dimensions are invalid");
|
||||||
alert("Cannot fuse layers: invalid dimensions calculated.");
|
showErrorNotification("Cannot fuse layers: invalid dimensions calculated.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1245,7 +1237,7 @@ export class CanvasLayers {
|
|||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
log.error("Error during layer fusion:", error);
|
log.error("Error during layer fusion:", error);
|
||||||
alert(`Error fusing layers: ${error.message}`);
|
showErrorNotification(`Error fusing layers: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
|
import { generateUUID } from "./utils/CommonUtils.js";
|
||||||
|
|
||||||
const log = createModuleLogger('CanvasSelection');
|
const log = createModuleLogger('CanvasSelection');
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ export class CanvasSelection {
|
|||||||
sortedLayers.forEach(layer => {
|
sortedLayers.forEach(layer => {
|
||||||
const newLayer = {
|
const newLayer = {
|
||||||
...layer,
|
...layer,
|
||||||
id: `layer_${+new Date()}_${Math.random().toString(36).substr(2, 9)}`,
|
id: generateUUID(),
|
||||||
zIndex: this.canvas.layers.length, // Nowa warstwa zawsze na wierzchu
|
zIndex: this.canvas.layers.length, // Nowa warstwa zawsze na wierzchu
|
||||||
};
|
};
|
||||||
this.canvas.layers.push(newLayer);
|
this.canvas.layers.push(newLayer);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {clearAllCanvasStates} from "./db.js";
|
|||||||
import {ImageCache} from "./ImageCache.js";
|
import {ImageCache} from "./ImageCache.js";
|
||||||
import {generateUniqueFileName} from "./utils/CommonUtils.js";
|
import {generateUniqueFileName} from "./utils/CommonUtils.js";
|
||||||
import {createModuleLogger} from "./utils/LoggerUtils.js";
|
import {createModuleLogger} from "./utils/LoggerUtils.js";
|
||||||
|
import {showErrorNotification, showSuccessNotification} from "./utils/NotificationUtils.js";
|
||||||
import { iconLoader, LAYERFORGE_TOOLS } from "./utils/IconLoader.js";
|
import { iconLoader, LAYERFORGE_TOOLS } from "./utils/IconLoader.js";
|
||||||
import { registerImageInClipspace, startSAMDetectorMonitoring, setupSAMDetectorHook } from "./SAMDetectorIntegration.js";
|
import { registerImageInClipspace, startSAMDetectorMonitoring, setupSAMDetectorHook } from "./SAMDetectorIntegration.js";
|
||||||
import type { ComfyNode, Layer, AddMode } from './types';
|
import type { ComfyNode, Layer, AddMode } from './types';
|
||||||
@@ -524,10 +525,10 @@ async function createCanvasWidget(node: ComfyNode, widget: any, app: ComfyApp):
|
|||||||
const newStats = canvas.imageReferenceManager.getStats();
|
const newStats = canvas.imageReferenceManager.getStats();
|
||||||
log.info("GC Stats after cleanup:", newStats);
|
log.info("GC Stats after cleanup:", newStats);
|
||||||
|
|
||||||
alert(`Garbage collection completed!\nTracked images: ${newStats.trackedImages}\nTotal references: ${newStats.totalReferences}\nOperations: ${canvas.imageReferenceManager.operationCount}/${canvas.imageReferenceManager.operationThreshold}`);
|
showSuccessNotification(`Garbage collection completed!\nTracked images: ${newStats.trackedImages}\nTotal references: ${newStats.totalReferences}\nOperations: ${canvas.imageReferenceManager.operationCount}/${canvas.imageReferenceManager.operationThreshold}`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error("Failed to run garbage collection:", e);
|
log.error("Failed to run garbage collection:", e);
|
||||||
alert("Error running garbage collection. Check the console for details.");
|
showErrorNotification("Error running garbage collection. Check the console for details.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -539,10 +540,10 @@ async function createCanvasWidget(node: ComfyNode, widget: any, app: ComfyApp):
|
|||||||
if (confirm("Are you sure you want to clear all saved canvas states? This action cannot be undone.")) {
|
if (confirm("Are you sure you want to clear all saved canvas states? This action cannot be undone.")) {
|
||||||
try {
|
try {
|
||||||
await clearAllCanvasStates();
|
await clearAllCanvasStates();
|
||||||
alert("Canvas cache cleared successfully!");
|
showSuccessNotification("Canvas cache cleared successfully!");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error("Failed to clear canvas cache:", e);
|
log.error("Failed to clear canvas cache:", e);
|
||||||
alert("Error clearing canvas cache. Check the console for details.");
|
showErrorNotification("Error clearing canvas cache. Check the console for details.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -918,8 +919,8 @@ function showErrorDialog(message: string, details: string) {
|
|||||||
textContent: "Copy Details",
|
textContent: "Copy Details",
|
||||||
onclick: () => {
|
onclick: () => {
|
||||||
navigator.clipboard.writeText(details)
|
navigator.clipboard.writeText(details)
|
||||||
.then(() => alert("Error details copied to clipboard!"))
|
.then(() => showSuccessNotification("Error details copied to clipboard!"))
|
||||||
.catch(err => alert("Failed to copy details: " + err));
|
.catch(err => showErrorNotification("Failed to copy details: " + err));
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
$el("button", {
|
$el("button", {
|
||||||
@@ -964,7 +965,7 @@ app.registerExtension({
|
|||||||
log.info("All canvas data has been sent and acknowledged by the server.");
|
log.info("All canvas data has been sent and acknowledged by the server.");
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
log.error("Failed to send canvas data for one or more nodes. Aborting prompt.", error);
|
log.error("Failed to send canvas data for one or more nodes. Aborting prompt.", error);
|
||||||
alert(`CanvasNode Error: ${error.message}`);
|
showErrorNotification(`CanvasNode Error: ${error.message}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1152,11 +1153,11 @@ app.registerExtension({
|
|||||||
await (self as any).canvasWidget.startMaskEditor(null, true);
|
await (self as any).canvasWidget.startMaskEditor(null, true);
|
||||||
} else {
|
} else {
|
||||||
log.error("Canvas widget not available");
|
log.error("Canvas widget not available");
|
||||||
alert("Canvas not ready. Please try again.");
|
showErrorNotification("Canvas not ready. Please try again.");
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
log.error("Error opening MaskEditor:", e);
|
log.error("Error opening MaskEditor:", e);
|
||||||
alert(`Failed to open MaskEditor: ${e.message}`);
|
showErrorNotification(`Failed to open MaskEditor: ${e.message}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1202,7 +1203,7 @@ app.registerExtension({
|
|||||||
log.info("Image copied to clipboard.");
|
log.info("Image copied to clipboard.");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error("Error copying image:", e);
|
log.error("Error copying image:", e);
|
||||||
alert("Failed to copy image to clipboard.");
|
showErrorNotification("Failed to copy image to clipboard.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1218,7 +1219,7 @@ app.registerExtension({
|
|||||||
log.info("Image with mask alpha copied to clipboard.");
|
log.info("Image with mask alpha copied to clipboard.");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error("Error copying image with mask:", e);
|
log.error("Error copying image with mask:", e);
|
||||||
alert("Failed to copy image with mask to clipboard.");
|
showErrorNotification("Failed to copy image with mask to clipboard.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {ComfyApp} from "../../scripts/app.js";
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {api} from "../../scripts/api.js";
|
import {api} from "../../scripts/api.js";
|
||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
|
import { showErrorNotification } from "./utils/NotificationUtils.js";
|
||||||
import { uploadCanvasAsImage, uploadCanvasWithMaskAsImage, uploadImageBlob } from "./utils/ImageUploadUtils.js";
|
import { uploadCanvasAsImage, uploadCanvasWithMaskAsImage, uploadImageBlob } from "./utils/ImageUploadUtils.js";
|
||||||
import { processImageToMask, processMaskForViewport } from "./utils/MaskProcessingUtils.js";
|
import { processImageToMask, processMaskForViewport } from "./utils/MaskProcessingUtils.js";
|
||||||
import { convertToImage } from "./utils/ImageUtils.js";
|
import { convertToImage } from "./utils/ImageUtils.js";
|
||||||
@@ -100,7 +101,7 @@ export class MaskEditorIntegration {
|
|||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error("Error preparing image for mask editor:", error);
|
log.error("Error preparing image for mask editor:", error);
|
||||||
alert(`Error: ${(error as Error).message}`);
|
showErrorNotification(`Error: ${(error as Error).message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {createModuleLogger} from "./utils/LoggerUtils.js";
|
import {createModuleLogger} from "./utils/LoggerUtils.js";
|
||||||
|
import { createCanvas } from "./utils/CommonUtils.js";
|
||||||
import type { Canvas } from './Canvas';
|
import type { Canvas } from './Canvas';
|
||||||
import type { Point, CanvasState } from './types';
|
import type { Point, CanvasState } from './types';
|
||||||
|
|
||||||
@@ -540,10 +541,7 @@ export class MaskTool {
|
|||||||
* Creates a canvas with specified dimensions and returns both canvas and context
|
* Creates a canvas with specified dimensions and returns both canvas and context
|
||||||
*/
|
*/
|
||||||
private createCanvas(width: number, height: number): { canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D } {
|
private createCanvas(width: number, height: number): { canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D } {
|
||||||
const canvas = document.createElement('canvas');
|
const { canvas, ctx } = createCanvas(width, height, '2d', { willReadFrequently: true });
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
const ctx = canvas.getContext('2d', { willReadFrequently: true });
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
throw new Error("Failed to get 2D context for canvas");
|
throw new Error("Failed to get 2D context for canvas");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user