suisuyy
commited on
Commit
·
545f5f7
1
Parent(s):
2f6c667
Refactor AI image handling in useAiFeatures hook for improved canvas integration and aspect ratio management
Browse files- hooks/useAiFeatures.ts +40 -42
hooks/useAiFeatures.ts
CHANGED
|
@@ -25,22 +25,22 @@ interface UseAiFeaturesProps {
|
|
| 25 |
currentDataURL: string | null;
|
| 26 |
showToast: (message: string, type: ToastMessage['type']) => void;
|
| 27 |
updateCanvasState: CanvasHistoryHook['updateCanvasState'];
|
| 28 |
-
setZoomLevel: (zoom: number) => void;
|
| 29 |
aiImageQuality: AiImageQuality;
|
| 30 |
aiApiEndpoint: string;
|
| 31 |
-
currentCanvasWidth: number;
|
| 32 |
-
currentCanvasHeight: number;
|
| 33 |
}
|
| 34 |
|
| 35 |
export const useAiFeatures = ({
|
| 36 |
currentDataURL,
|
| 37 |
showToast,
|
| 38 |
updateCanvasState,
|
| 39 |
-
setZoomLevel,
|
| 40 |
aiImageQuality,
|
| 41 |
aiApiEndpoint,
|
| 42 |
-
currentCanvasWidth,
|
| 43 |
-
currentCanvasHeight,
|
| 44 |
}: UseAiFeaturesProps): AiFeaturesHook => {
|
| 45 |
const [isMagicUploading, setIsMagicUploading] = useState<boolean>(false);
|
| 46 |
const [showAiEditModal, setShowAiEditModal] = useState<boolean>(false);
|
|
@@ -52,50 +52,48 @@ export const useAiFeatures = ({
|
|
| 52 |
const loadAiImageOntoCanvas = useCallback((aiImageDataUrl: string) => {
|
| 53 |
const img = new Image();
|
| 54 |
img.onload = () => {
|
| 55 |
-
const
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
let drawWidth = img.naturalWidth;
|
| 60 |
-
let drawHeight = img.naturalHeight;
|
| 61 |
-
|
| 62 |
-
const canvasAspectRatio = targetCanvasWidth / targetCanvasHeight;
|
| 63 |
-
const imageAspectRatio = img.naturalWidth / img.naturalHeight;
|
| 64 |
|
| 65 |
-
if (
|
| 66 |
-
//
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
} else {
|
| 70 |
-
// Image is taller or same aspect ratio: fit by height
|
| 71 |
-
drawHeight = targetCanvasHeight;
|
| 72 |
-
drawWidth = targetCanvasHeight * imageAspectRatio;
|
| 73 |
-
}
|
| 74 |
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
drawHeight = Math.max(1, Math.floor(drawHeight));
|
| 78 |
|
| 79 |
-
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
const tempCtx = tempCanvas.getContext('2d');
|
| 86 |
|
| 87 |
-
if (tempCtx) {
|
| 88 |
-
tempCtx.fillStyle = '#FFFFFF'; // White background for the canvas
|
| 89 |
-
tempCtx.fillRect(0, 0, targetCanvasWidth, targetCanvasHeight);
|
| 90 |
tempCtx.drawImage(img, drawX, drawY, drawWidth, drawHeight);
|
|
|
|
| 91 |
const newCanvasState = tempCanvas.toDataURL('image/png');
|
| 92 |
|
| 93 |
-
//
|
| 94 |
-
updateCanvasState(newCanvasState,
|
| 95 |
|
| 96 |
setShowAiEditModal(false);
|
| 97 |
-
showToast('AI image applied!', 'success');
|
| 98 |
-
setZoomLevel(1);
|
| 99 |
setAiPrompt('');
|
| 100 |
setSharedImageUrlForAi(null);
|
| 101 |
} else {
|
|
@@ -109,7 +107,7 @@ export const useAiFeatures = ({
|
|
| 109 |
};
|
| 110 |
img.crossOrigin = "anonymous";
|
| 111 |
img.src = aiImageDataUrl;
|
| 112 |
-
}, [showToast, updateCanvasState,
|
| 113 |
|
| 114 |
const handleMagicUpload = useCallback(async () => {
|
| 115 |
if (isMagicUploading || !currentDataURL) {
|
|
@@ -266,4 +264,4 @@ export const useAiFeatures = ({
|
|
| 266 |
handleCancelAiEdit,
|
| 267 |
setAiPrompt,
|
| 268 |
};
|
| 269 |
-
};
|
|
|
|
| 25 |
currentDataURL: string | null;
|
| 26 |
showToast: (message: string, type: ToastMessage['type']) => void;
|
| 27 |
updateCanvasState: CanvasHistoryHook['updateCanvasState'];
|
| 28 |
+
setZoomLevel: (zoom: number) => void;
|
| 29 |
aiImageQuality: AiImageQuality;
|
| 30 |
aiApiEndpoint: string;
|
| 31 |
+
currentCanvasWidth: number;
|
| 32 |
+
currentCanvasHeight: number;
|
| 33 |
}
|
| 34 |
|
| 35 |
export const useAiFeatures = ({
|
| 36 |
currentDataURL,
|
| 37 |
showToast,
|
| 38 |
updateCanvasState,
|
| 39 |
+
setZoomLevel,
|
| 40 |
aiImageQuality,
|
| 41 |
aiApiEndpoint,
|
| 42 |
+
currentCanvasWidth,
|
| 43 |
+
currentCanvasHeight,
|
| 44 |
}: UseAiFeaturesProps): AiFeaturesHook => {
|
| 45 |
const [isMagicUploading, setIsMagicUploading] = useState<boolean>(false);
|
| 46 |
const [showAiEditModal, setShowAiEditModal] = useState<boolean>(false);
|
|
|
|
| 52 |
const loadAiImageOntoCanvas = useCallback((aiImageDataUrl: string) => {
|
| 53 |
const img = new Image();
|
| 54 |
img.onload = () => {
|
| 55 |
+
const tempCanvas = document.createElement('canvas');
|
| 56 |
+
tempCanvas.width = currentCanvasWidth;
|
| 57 |
+
tempCanvas.height = currentCanvasHeight;
|
| 58 |
+
const tempCtx = tempCanvas.getContext('2d');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
+
if (tempCtx) {
|
| 61 |
+
// Fill background (e.g., white)
|
| 62 |
+
tempCtx.fillStyle = '#FFFFFF';
|
| 63 |
+
tempCtx.fillRect(0, 0, currentCanvasWidth, currentCanvasHeight);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
+
let drawWidth = img.naturalWidth;
|
| 66 |
+
let drawHeight = img.naturalHeight;
|
|
|
|
| 67 |
|
| 68 |
+
// Scale image if it's larger than the canvas, preserving aspect ratio
|
| 69 |
+
if (img.naturalWidth > currentCanvasWidth || img.naturalHeight > currentCanvasHeight) {
|
| 70 |
+
const aspectRatio = img.naturalWidth / img.naturalHeight;
|
| 71 |
+
if (currentCanvasWidth / aspectRatio <= currentCanvasHeight) {
|
| 72 |
+
drawWidth = currentCanvasWidth;
|
| 73 |
+
drawHeight = currentCanvasWidth / aspectRatio;
|
| 74 |
+
} else {
|
| 75 |
+
drawHeight = currentCanvasHeight;
|
| 76 |
+
drawWidth = currentCanvasHeight * aspectRatio;
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
// Ensure dimensions are at least 1px
|
| 81 |
+
drawWidth = Math.max(1, Math.floor(drawWidth));
|
| 82 |
+
drawHeight = Math.max(1, Math.floor(drawHeight));
|
| 83 |
|
| 84 |
+
// Calculate coordinates to center the image
|
| 85 |
+
const drawX = (currentCanvasWidth - drawWidth) / 2;
|
| 86 |
+
const drawY = (currentCanvasHeight - drawHeight) / 2;
|
|
|
|
| 87 |
|
|
|
|
|
|
|
|
|
|
| 88 |
tempCtx.drawImage(img, drawX, drawY, drawWidth, drawHeight);
|
| 89 |
+
|
| 90 |
const newCanvasState = tempCanvas.toDataURL('image/png');
|
| 91 |
|
| 92 |
+
// Update canvas state with the new image, but keep original canvas dimensions
|
| 93 |
+
updateCanvasState(newCanvasState, currentCanvasWidth, currentCanvasHeight);
|
| 94 |
|
| 95 |
setShowAiEditModal(false);
|
| 96 |
+
showToast('AI image applied to canvas!', 'success');
|
|
|
|
| 97 |
setAiPrompt('');
|
| 98 |
setSharedImageUrlForAi(null);
|
| 99 |
} else {
|
|
|
|
| 107 |
};
|
| 108 |
img.crossOrigin = "anonymous";
|
| 109 |
img.src = aiImageDataUrl;
|
| 110 |
+
}, [showToast, updateCanvasState, currentCanvasWidth, currentCanvasHeight]);
|
| 111 |
|
| 112 |
const handleMagicUpload = useCallback(async () => {
|
| 113 |
if (isMagicUploading || !currentDataURL) {
|
|
|
|
| 264 |
handleCancelAiEdit,
|
| 265 |
setAiPrompt,
|
| 266 |
};
|
| 267 |
+
};
|