@yogiswara/honcho-editor-ui 1.3.9 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/editor/useHonchoEditor.d.ts +8 -28
- package/dist/hooks/editor/useHonchoEditor.js +159 -561
- package/dist/hooks/useAdjustmentHistory.d.ts +2 -0
- package/dist/hooks/useAdjustmentHistory.example.d.ts +5 -0
- package/dist/hooks/useAdjustmentHistory.example.js +32 -0
- package/dist/hooks/useAdjustmentHistory.js +62 -2
- package/dist/hooks/useAdjustmentHistory.syncDemo.d.ts +8 -0
- package/dist/hooks/useAdjustmentHistory.syncDemo.js +180 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
2
|
+
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
|
|
3
3
|
import { HonchoEditor } from '../../lib/editor/honcho-editor';
|
|
4
4
|
import { mapAdjustmentStateToAdjustmentEditor, mapColorAdjustmentToAdjustmentState } from '../../utils/adjustment';
|
|
5
5
|
import { useAdjustmentHistory } from '../useAdjustmentHistory';
|
|
@@ -10,15 +10,12 @@ const initialAdjustments = {
|
|
|
10
10
|
};
|
|
11
11
|
const clamp = (value) => Math.max(-100, Math.min(100, value));
|
|
12
12
|
export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
13
|
-
const [currentImageId, setCurrentImageId] = useState(initImageId);
|
|
14
|
-
const [currentImageData, setCurrentImageData] = useState(null);
|
|
15
|
-
const [currentAdjustmentsState, setCurrentAdjustmentsState] = useState(initialAdjustments);
|
|
16
|
-
const { onSwipeNext, onSwipePrev, isNextAvailable, isPrevAvailable, isLoading: isGalleryLoading, error: galleryError, } = useGallerySwipe(firebaseUid, initImageId, controller);
|
|
13
|
+
// const [currentImageId, setCurrentImageId] = useState<string>(initImageId);
|
|
14
|
+
// const [currentImageData, setCurrentImageData] = useState<Gallery | null>(null);
|
|
15
|
+
// const [currentAdjustmentsState, setCurrentAdjustmentsState] = useState<AdjustmentState>(initialAdjustments);
|
|
16
|
+
const { onSwipeNext, onSwipePrev, isNextAvailable, isPrevAvailable, isLoading: isGalleryLoading, error: galleryError, currentImageData: galleryImageData } = useGallerySwipe(firebaseUid, initImageId, controller);
|
|
17
17
|
// The useAdjustmentHistory hook now manages all undo/redo and adjustment state logic.
|
|
18
|
-
const { currentState:
|
|
19
|
-
const [currentPage, setCurrentPage] = useState(1);
|
|
20
|
-
const [hasNextPage, setHasNextPage] = useState(true);
|
|
21
|
-
const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);
|
|
18
|
+
const { currentState: currentAdjustmentsState, actions: historyActions, historyInfo, config: historyConfig, } = useAdjustmentHistory(initialAdjustments);
|
|
22
19
|
const [eventId, setEventId] = useState(null);
|
|
23
20
|
// MARK: - Core Editor State & Refs
|
|
24
21
|
const editorRef = useRef(null);
|
|
@@ -30,36 +27,17 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
30
27
|
const [isImageLoaded, setIsImageLoaded] = useState(false);
|
|
31
28
|
const [zoomLevel, setZoomLevel] = useState(1);
|
|
32
29
|
// MARK: - Adjustment & History State
|
|
33
|
-
// const [adjustments, setAdjustments] = useState<AdjustmentState>(initialAdjustments);
|
|
34
|
-
const [history, setHistory] = useState([initialAdjustments]);
|
|
35
|
-
const [historyIndex, setHistoryIndex] = useState(0);
|
|
36
|
-
const [isViewingOriginal, setIsViewingOriginal] = useState(false);
|
|
37
30
|
const [copiedAdjustments, setCopiedAdjustments] = useState(null);
|
|
38
31
|
const [copyColorChecks, setCopyColorChecks] = useState({ temperature: true, tint: true, vibrance: true, saturation: true });
|
|
39
32
|
const [copyLightChecks, setCopyLightChecks] = useState({ exposure: true, contrast: true, highlights: true, shadows: true, whites: true, blacks: true });
|
|
40
33
|
const [copyDetailsChecks, setCopyDetailsChecks] = useState({ clarity: true, sharpness: true });
|
|
41
34
|
const [copyDialogExpanded, setCopyDialogExpanded] = useState({ color: true, light: true, details: true });
|
|
42
|
-
const [adjustmentsMap, setAdjustmentsMap] = useState(new Map());
|
|
43
|
-
// Individual Adjustment State
|
|
44
|
-
// const [tempScore, setTempScore] = useState(0);
|
|
45
|
-
// const [tintScore, setTintScore] = useState(0);
|
|
46
|
-
// const [vibranceScore, setVibranceScore] = useState(0);
|
|
47
|
-
// const [saturationScore, setSaturationScore] = useState(0);
|
|
48
|
-
// const [exposureScore, setExposureScore] = useState(0);
|
|
49
|
-
// const [highlightsScore, setHighlightsScore] = useState(0);
|
|
50
|
-
// const [shadowsScore, setShadowsScore] = useState(0);
|
|
51
|
-
// const [whitesScore, setWhitesScore] = useState(0);
|
|
52
|
-
// const [blacksScore, setBlacksScore] = useState(0);
|
|
53
|
-
// const [contrastScore, setContrastScore] = useState(0);
|
|
54
|
-
// const [clarityScore, setClarityScore] = useState(0);
|
|
55
|
-
// const [sharpnessScore, setSharpnessScore] = useState(0);
|
|
56
35
|
// MARK: - UI & App State (Moved from page.tsx)
|
|
57
36
|
// General UI State
|
|
58
37
|
const [isOnline, setIsOnline] = useState(true);
|
|
59
38
|
const [isConnectionSlow, setIsConnectionSlow] = useState(false);
|
|
60
39
|
const [showCopyAlert, setShowCopyAlert] = useState(false);
|
|
61
40
|
const [isCopyDialogOpen, setCopyDialogOpen] = useState(false);
|
|
62
|
-
const [isPublished, setIsPublished] = useState(false);
|
|
63
41
|
const [activePanel, setActivePanel] = useState('colorAdjustment');
|
|
64
42
|
const [activeSubPanel, setActiveSubPanel] = useState('');
|
|
65
43
|
const [headerMenuAnchorEl, setHeaderMenuAnchorEl] = useState(null);
|
|
@@ -77,7 +55,7 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
77
55
|
const [isPresetCreated, setIsPresetCreated] = useState(false);
|
|
78
56
|
const [selectedMobilePreset, setSelectedMobilePreset] = useState('preset1');
|
|
79
57
|
const [selectedDesktopPreset, setSelectedDesktopPreset] = useState('preset1');
|
|
80
|
-
const [selectedBulkPreset, setSelectedBulkPreset] = useState('preset1');
|
|
58
|
+
// const [selectedBulkPreset, setSelectedBulkPreset] = useState<string>('preset1');
|
|
81
59
|
const [presetMenuAnchorEl, setPresetMenuAnchorEl] = useState(null);
|
|
82
60
|
const [activePresetMenuId, setActivePresetMenuId] = useState(null);
|
|
83
61
|
const [isRenameModalOpen, setRenameModalOpen] = useState(false);
|
|
@@ -85,25 +63,22 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
85
63
|
const [newPresetName, setNewPresetName] = useState("");
|
|
86
64
|
// Aspect Ratio State
|
|
87
65
|
// Note: not used yet
|
|
88
|
-
const [currentAspectRatio, setCurrentAspectRatio] = useState('potrait');
|
|
89
|
-
const [currentSquareRatio, setCurrentSquareRatio] = useState('original');
|
|
90
|
-
const [currentWideRatio, setCurrentWideRatio] = useState('1:1');
|
|
91
|
-
const [angelScore, setAngleScore] = useState(0);
|
|
92
|
-
const [widthSizePX, setWidthSizePX] = useState(0);
|
|
93
|
-
const [heightSizePX, setHeightSizePX] = useState(0);
|
|
66
|
+
// const [currentAspectRatio, setCurrentAspectRatio] = useState('potrait');
|
|
67
|
+
// const [currentSquareRatio, setCurrentSquareRatio] = useState('original');
|
|
68
|
+
// const [currentWideRatio, setCurrentWideRatio] = useState('1:1');
|
|
69
|
+
// const [angelScore, setAngleScore] = useState(0);
|
|
70
|
+
// const [widthSizePX, setWidthSizePX] = useState(0);
|
|
71
|
+
// const [heightSizePX, setHeightSizePX] = useState(0);
|
|
94
72
|
// Bulk Editing State
|
|
95
|
-
const [isBulkEditing, setIsBulkEditing] = useState(false);
|
|
96
|
-
const [selectedImages, setSelectedImages] = useState('Select');
|
|
97
|
-
const [imageList, setImageList] = useState([]);
|
|
98
|
-
const [selectedImageIds, setSelectedImageIds] = useState(new Set());
|
|
73
|
+
// const [isBulkEditing, setIsBulkEditing] = useState(false);
|
|
74
|
+
// const [selectedImages, setSelectedImages] = useState('Select');
|
|
75
|
+
// const [imageList, setImageList] = useState<ImageItem[]>([]);
|
|
76
|
+
// const [selectedImageIds, setSelectedImageIds] = useState<Set<string>>(new Set());
|
|
99
77
|
// MARK: Framse- (Later use)
|
|
100
|
-
const [isFrameApplied, setIsFrameApplied] = useState(false);
|
|
101
78
|
// State for Copying specific adjustments
|
|
102
79
|
const [colorAdjustments, setColorAdjustments] = useState(true);
|
|
103
80
|
const [lightAdjustments, setLightAdjustments] = useState(true);
|
|
104
81
|
const [detailsAdjustments, setDetailsAdjustments] = useState(true);
|
|
105
|
-
// for connection native
|
|
106
|
-
const [displayedToken, setDisplayedToken] = useState(null);
|
|
107
82
|
// MARK: dragable
|
|
108
83
|
const PEEK_HEIGHT = 20;
|
|
109
84
|
const COLLAPSED_HEIGHT = 165;
|
|
@@ -169,18 +144,17 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
169
144
|
handleOpenCopyDialog(); // Assumes handleOpenCopyDialog is defined in the hook
|
|
170
145
|
}
|
|
171
146
|
}, [ /* handleOpenCopyDialog dependency */]);
|
|
172
|
-
useEffect(() => {
|
|
173
|
-
}, [editorRef]);
|
|
174
147
|
// Effect for measuring mobile panel content
|
|
175
|
-
useEffect(() => {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}, [activeSubPanel
|
|
148
|
+
// useEffect(() => {
|
|
149
|
+
// const timeoutId = setTimeout(() => {
|
|
150
|
+
// if (contentRef.current) {
|
|
151
|
+
// const height = contentRef.current.scrollHeight;
|
|
152
|
+
// setContentHeight(height);
|
|
153
|
+
// }
|
|
154
|
+
// }, 50);
|
|
155
|
+
// return () => clearTimeout(timeoutId);
|
|
156
|
+
// }, [activeSubPanel ]);
|
|
157
|
+
// isBulkEditing
|
|
184
158
|
// Effect for keyboard shortcuts
|
|
185
159
|
useEffect(() => {
|
|
186
160
|
window.addEventListener('keydown', handleKeyDown);
|
|
@@ -226,108 +200,12 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
226
200
|
};
|
|
227
201
|
}, []);
|
|
228
202
|
// MARK: - Core Editor Logic
|
|
229
|
-
const { tempScore, tintScore, vibranceScore, saturationScore, exposureScore, highlightsScore, shadowsScore, whitesScore, blacksScore, contrastScore, clarityScore, sharpnessScore } = currentAdjustmentsState;
|
|
230
203
|
const updateCanvasEditor = useCallback(() => {
|
|
231
204
|
if ((editorRef.current?.getInitialized() === true) && canvasRef.current) {
|
|
232
205
|
editorRef.current.processImage();
|
|
233
206
|
editorRef.current.renderToCanvas(canvasRef.current);
|
|
234
207
|
}
|
|
235
208
|
}, [canvasRef.current, editorRef.current]);
|
|
236
|
-
const loadImage = useCallback(async (file) => {
|
|
237
|
-
if (!editorRef.current) {
|
|
238
|
-
setEditorStatus("Editor not ready.");
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
setEditorStatus("Loading image...");
|
|
242
|
-
// TODO move
|
|
243
|
-
try {
|
|
244
|
-
await editorRef.current.loadImageFromFile(file);
|
|
245
|
-
setIsImageLoaded(true);
|
|
246
|
-
updateCanvasEditor();
|
|
247
|
-
}
|
|
248
|
-
catch (e) {
|
|
249
|
-
console.error("Error loading image:", e);
|
|
250
|
-
setEditorStatus("Error: Could not load the image.");
|
|
251
|
-
setIsImageLoaded(false);
|
|
252
|
-
}
|
|
253
|
-
}, []);
|
|
254
|
-
const applyUiStateToSelectedImages = useCallback((uiState) => {
|
|
255
|
-
setAdjustmentsMap(prevMap => {
|
|
256
|
-
const newMap = new Map(prevMap);
|
|
257
|
-
selectedImageIds.forEach(id => {
|
|
258
|
-
newMap.set(id, uiState);
|
|
259
|
-
});
|
|
260
|
-
return newMap;
|
|
261
|
-
});
|
|
262
|
-
}, [selectedImageIds]);
|
|
263
|
-
const loadImageFromUrl = useCallback(async (url) => {
|
|
264
|
-
try {
|
|
265
|
-
setEditorStatus("Downloading image...");
|
|
266
|
-
console.log(`[DEBUG] Attempting to fetch image from URL: ${url}`);
|
|
267
|
-
const response = await fetch(url);
|
|
268
|
-
if (!response.ok)
|
|
269
|
-
throw new Error(`Failed to fetch image from URL: ${url}`);
|
|
270
|
-
const blob = await response.blob();
|
|
271
|
-
const filename = url.substring(url.lastIndexOf('/') + 1) || 'image.jpg';
|
|
272
|
-
const file = new File([blob], filename, { type: blob.type });
|
|
273
|
-
await loadImage(file); // Pass the final File object to the core loader
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
console.error(error);
|
|
277
|
-
setEditorStatus("Error: Could not load image from URL.");
|
|
278
|
-
}
|
|
279
|
-
}, [loadImage]);
|
|
280
|
-
const loadImageFromId = useCallback(async (firebaseUid, imageId) => {
|
|
281
|
-
if (!controller)
|
|
282
|
-
return;
|
|
283
|
-
setEditorStatus("Fetching image...");
|
|
284
|
-
try {
|
|
285
|
-
const gallery = await controller.onGetImage(firebaseUid, imageId);
|
|
286
|
-
const imagePath = gallery?.raw_edited?.path
|
|
287
|
-
? gallery.raw_edited.path
|
|
288
|
-
: gallery?.download?.path;
|
|
289
|
-
console.log("[DEBUG] Extracted imagePath to load:", imagePath);
|
|
290
|
-
if (imagePath) {
|
|
291
|
-
await loadImageFromUrl(imagePath);
|
|
292
|
-
return gallery; // ✅ RETURN the gallery object on success
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
throw new Error("Controller did not return a valid image object with path.");
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
catch (error) {
|
|
299
|
-
console.error("Failed to fetch or load image via controller:", error);
|
|
300
|
-
setEditorStatus("Error: Could not fetch the image.");
|
|
301
|
-
}
|
|
302
|
-
}, [controller, loadImageFromUrl]);
|
|
303
|
-
const updateAdjustments = useCallback((newValues) => {
|
|
304
|
-
// In batch mode (like dragging a slider), this only updates the UI.
|
|
305
|
-
// When not in batch mode (or when the slider drag ends), it creates a history entry.
|
|
306
|
-
const newState = { ...currentAdjustmentsState, ...newValues };
|
|
307
|
-
historyActions.pushState(newState);
|
|
308
|
-
}, [currentAdjustmentsState, historyActions]);
|
|
309
|
-
const getImageFromId = useCallback(async (firebaseUid, imageId) => {
|
|
310
|
-
if (!controller)
|
|
311
|
-
return;
|
|
312
|
-
setEditorStatus("Fetching image...");
|
|
313
|
-
try {
|
|
314
|
-
const gallery = await controller.onGetImage(firebaseUid, imageId);
|
|
315
|
-
const imagePath = gallery?.raw_edited?.path
|
|
316
|
-
? gallery.raw_edited.path
|
|
317
|
-
: gallery?.download?.path;
|
|
318
|
-
console.log("[DEBUG] Extracted imagePath to load:", imagePath);
|
|
319
|
-
if (imagePath) {
|
|
320
|
-
return gallery; // ✅ RETURN the gallery object on success
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
throw new Error("Controller did not return a valid image object with path.");
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
catch (error) {
|
|
327
|
-
console.error("Failed to fetch or load image via controller:", error);
|
|
328
|
-
setEditorStatus("Error: Could not fetch the image.");
|
|
329
|
-
}
|
|
330
|
-
}, [controller]);
|
|
331
209
|
const extractPathFromGallery = useCallback((data) => {
|
|
332
210
|
const imagePath = data?.raw_edited?.path
|
|
333
211
|
? data.raw_edited.path
|
|
@@ -356,241 +234,59 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
356
234
|
setIsImageLoaded(false);
|
|
357
235
|
}
|
|
358
236
|
}, [editorRef.current]);
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
}
|
|
381
|
-
// Condition 2: Check if there's a next page and we aren't already fetching it.
|
|
382
|
-
if (hasNextPage && !isFetchingNextPage) {
|
|
383
|
-
console.log(`At end of list. Fetching next page: ${currentPage + 1}`);
|
|
384
|
-
setIsFetchingNextPage(true);
|
|
385
|
-
try {
|
|
386
|
-
const response = await controller.getImageList(firebaseUid, eventId, currentPage + 1);
|
|
387
|
-
if (response.gallery && response.gallery.length > 0) {
|
|
388
|
-
const newItems = response.gallery.map(g => ({
|
|
389
|
-
id: g.id,
|
|
390
|
-
url: g.raw_edited?.path || g.download?.path || '',
|
|
391
|
-
name: g.id, // ✅ ADDED: Fulfill the ImageItem 'name' property
|
|
392
|
-
file: new File([], g.id),
|
|
393
|
-
}));
|
|
394
|
-
setImageList(prevList => [...prevList, ...newItems]);
|
|
395
|
-
setCurrentPage(response.current_page);
|
|
396
|
-
setHasNextPage(response.next_page !== 0 && response.next_page > response.current_page);
|
|
397
|
-
setCurrentImageId(newItems[0].id);
|
|
398
|
-
}
|
|
399
|
-
else {
|
|
400
|
-
setHasNextPage(false);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
catch (error) {
|
|
404
|
-
console.error("Failed to fetch next page:", error);
|
|
405
|
-
}
|
|
406
|
-
finally {
|
|
407
|
-
setIsFetchingNextPage(false);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
// Condition 3: We are NOT at the end of the list, so just navigate normally.
|
|
411
|
-
}
|
|
412
|
-
else if (currentIndex !== -1) {
|
|
413
|
-
const nextImageId = imageList[currentIndex + 1]?.id;
|
|
414
|
-
if (nextImageId) {
|
|
415
|
-
setCurrentImageId(nextImageId);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}, [
|
|
419
|
-
imageList, currentImageId, hasNextPage,
|
|
420
|
-
isFetchingNextPage, currentPage, controller, firebaseUid, eventId
|
|
421
|
-
]);
|
|
422
|
-
useEffect(() => {
|
|
423
|
-
const initialize = async () => {
|
|
424
|
-
if (currentImageId && firebaseUid && controller && isEditorReady) {
|
|
425
|
-
console.log(`[INIT] Starting sequence for image: ${currentImageId}`);
|
|
426
|
-
const initialGallery = await loadImageFromId(firebaseUid, currentImageId);
|
|
427
|
-
// ✅ ADD THIS BLOCK TO CHECK THE DATA
|
|
428
|
-
console.group("[DEBUG] Checking Initial Gallery Data");
|
|
429
|
-
if (initialGallery) {
|
|
430
|
-
console.log("Full gallery object received:", initialGallery);
|
|
431
|
-
console.log("Discovered eventId from data:", initialGallery.event_id);
|
|
432
|
-
}
|
|
433
|
-
else {
|
|
434
|
-
console.error("Failed to fetch the initial gallery object.");
|
|
435
|
-
}
|
|
436
|
-
console.groupEnd();
|
|
437
|
-
if (initialGallery && initialGallery.event_id) {
|
|
438
|
-
const fetchedEventId = initialGallery.event_id;
|
|
439
|
-
console.log(`[INIT] Discovered eventID: ${fetchedEventId}`);
|
|
440
|
-
setEventId(fetchedEventId); // Store the discovered eventId in our state
|
|
441
|
-
// 4. Now, use the discovered eventId to fetch the full image list for navigation
|
|
442
|
-
const response = await controller.getImageList(firebaseUid, fetchedEventId, 1);
|
|
443
|
-
const items = response.gallery.map(g => ({
|
|
444
|
-
id: g.id,
|
|
445
|
-
url: g.raw_edited?.path || g.download?.path || '',
|
|
446
|
-
name: g.id,
|
|
447
|
-
file: new File([], g.id),
|
|
448
|
-
}));
|
|
449
|
-
setImageList(items);
|
|
450
|
-
setCurrentPage(1);
|
|
451
|
-
setHasNextPage(response.next_page !== 0 && response.next_page > response.current_page);
|
|
452
|
-
console.log("[INIT] Image list fetched and set.");
|
|
453
|
-
}
|
|
454
|
-
else {
|
|
455
|
-
console.error("[INIT] Failed to get initial gallery data or event_id was missing.");
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
};
|
|
459
|
-
initialize();
|
|
460
|
-
}, [currentImageId, firebaseUid, controller, isEditorReady, loadImageFromId]);
|
|
461
|
-
// useEffect(() => {
|
|
462
|
-
// // Ensure we have everything needed before trying to load.
|
|
463
|
-
// if (currentImageId && firebaseUid && controller && isEditorReady) {
|
|
464
|
-
// console.log(`[EFFECT] currentImageId changed to: ${currentImageId}. Loading new image into canvas.`);
|
|
465
|
-
// // Load the new image specified by the updated currentImageId
|
|
466
|
-
// loadImageFromId(firebaseUid, currentImageId);
|
|
467
|
-
// }
|
|
468
|
-
// }, [currentImageId, isEditorReady]);
|
|
469
|
-
const handleFileChange = (event) => {
|
|
470
|
-
const files = event.target?.files;
|
|
471
|
-
if (!files || files.length === 0)
|
|
472
|
-
return;
|
|
473
|
-
setHistory([initialAdjustments]);
|
|
474
|
-
setHistoryIndex(0);
|
|
475
|
-
if (files.length === 1) {
|
|
476
|
-
setIsBulkEditing(false);
|
|
477
|
-
setImageList([]);
|
|
478
|
-
setSelectedImageIds(new Set());
|
|
479
|
-
setAdjustmentsMap(new Map());
|
|
480
|
-
loadImage(files[0]);
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
setIsBulkEditing(true);
|
|
484
|
-
const newImageList = Array.from(files).map((file, index) => ({
|
|
485
|
-
id: `${file.name}-${Date.now()}-${index}`,
|
|
486
|
-
name: file.name,
|
|
487
|
-
file: file,
|
|
488
|
-
url: URL.createObjectURL(file),
|
|
489
|
-
}));
|
|
490
|
-
const newAdjustmentsMap = new Map();
|
|
491
|
-
newImageList.forEach(image => {
|
|
492
|
-
newAdjustmentsMap.set(image.id, { ...initialAdjustments });
|
|
493
|
-
});
|
|
494
|
-
setAdjustmentsMap(newAdjustmentsMap);
|
|
495
|
-
setImageList(newImageList);
|
|
496
|
-
setIsImageLoaded(true);
|
|
497
|
-
setSelectedImageIds(new Set(newImageList.map(img => img.id)));
|
|
498
|
-
}
|
|
499
|
-
};
|
|
500
|
-
// const applyAdjustmentState = useCallback((state: AdjustmentState) => {
|
|
501
|
-
// // Always update the UI controls
|
|
502
|
-
// setTempScore(state.tempScore);
|
|
503
|
-
// setTintScore(state.tintScore);
|
|
504
|
-
// setVibranceScore(state.vibranceScore);
|
|
505
|
-
// setExposureScore(state.exposureScore);
|
|
506
|
-
// setHighlightsScore(state.highlightsScore);
|
|
507
|
-
// setShadowsScore(state.shadowsScore);
|
|
508
|
-
// setWhitesScore(state.whitesScore);
|
|
509
|
-
// setBlacksScore(state.blacksScore);
|
|
510
|
-
// setSaturationScore(state.saturationScore);
|
|
511
|
-
// setContrastScore(state.contrastScore);
|
|
512
|
-
// setClarityScore(state.clarityScore);
|
|
513
|
-
// setSharpnessScore(state.sharpnessScore);
|
|
514
|
-
// // If in bulk mode, apply this state to all selected images
|
|
515
|
-
// if (isBulkEditing) {
|
|
516
|
-
// applyUiStateToSelectedImages(state);
|
|
517
|
-
// }
|
|
518
|
-
// }, [isBulkEditing, applyUiStateToSelectedImages]);
|
|
519
|
-
// const handleRevert = useCallback(() => {
|
|
520
|
-
// // This will reset the UI controls and, if in bulk mode, the selected images
|
|
521
|
-
// applyAdjustmentState(initialAdjustments);
|
|
522
|
-
// // For single image mode, also reset the underlying canvas engine
|
|
523
|
-
// if (!isBulkEditing && editorRef.current) {
|
|
524
|
-
// editorRef.current.resetAdjustments();
|
|
237
|
+
// MARK: Batch Edit logic
|
|
238
|
+
// const handleToggleImageSelection = useCallback((imageId: string) => {
|
|
239
|
+
// const newSelectedIds = new Set(selectedImageIds);
|
|
240
|
+
// const isCurrentlySelected = newSelectedIds.has(imageId);
|
|
241
|
+
// if (isCurrentlySelected) {
|
|
242
|
+
// if (newSelectedIds.size > 1) {
|
|
243
|
+
// newSelectedIds.delete(imageId);
|
|
244
|
+
// }
|
|
245
|
+
// } else {
|
|
246
|
+
// newSelectedIds.add(imageId);
|
|
247
|
+
// // Apply the current UI's adjustments to the newly selected image.
|
|
248
|
+
// setAdjustmentsMap(prevMap => {
|
|
249
|
+
// const newMap = new Map(prevMap);
|
|
250
|
+
// const currentUiState = {
|
|
251
|
+
// tempScore, tintScore, vibranceScore, saturationScore,
|
|
252
|
+
// exposureScore, highlightsScore, shadowsScore, whitesScore,
|
|
253
|
+
// blacksScore, contrastScore, clarityScore, sharpnessScore
|
|
254
|
+
// };
|
|
255
|
+
// newMap.set(imageId, currentUiState);
|
|
256
|
+
// return newMap;
|
|
257
|
+
// });
|
|
525
258
|
// }
|
|
526
|
-
//
|
|
527
|
-
//
|
|
528
|
-
//
|
|
529
|
-
//
|
|
530
|
-
//
|
|
531
|
-
//
|
|
259
|
+
// setSelectedImageIds(newSelectedIds);
|
|
260
|
+
// }, [selectedImageIds, tempScore, tintScore, vibranceScore, saturationScore, exposureScore, highlightsScore, shadowsScore, whitesScore, blacksScore, contrastScore, clarityScore, sharpnessScore]);
|
|
261
|
+
// const createAbsoluteSetter = (key: keyof AdjustmentState, setter: React.Dispatch<React.SetStateAction<number>>) => (value: number) => {
|
|
262
|
+
// setter(value); // Update UI slider
|
|
263
|
+
// if(isBulkEditing) {
|
|
264
|
+
// setAdjustmentsMap(prevMap => {
|
|
265
|
+
// const newMap = new Map(prevMap);
|
|
266
|
+
// selectedImageIds.forEach(id => {
|
|
267
|
+
// const currentState = newMap.get(id) || initialAdjustments;
|
|
268
|
+
// newMap.set(id, { ...currentState, [key]: value });
|
|
269
|
+
// });
|
|
270
|
+
// return newMap;
|
|
271
|
+
// });
|
|
532
272
|
// }
|
|
533
|
-
// }
|
|
534
|
-
// const
|
|
535
|
-
//
|
|
536
|
-
//
|
|
537
|
-
//
|
|
538
|
-
//
|
|
273
|
+
// };
|
|
274
|
+
// const createRelativeAdjuster = (key: keyof AdjustmentState, uiSetter: React.Dispatch<React.SetStateAction<number>>, amount: number) => () => {
|
|
275
|
+
// uiSetter(prev => clamp(prev + amount));
|
|
276
|
+
// if (isBulkEditing) {
|
|
277
|
+
// setAdjustmentsMap(prevMap => {
|
|
278
|
+
// const newMap = new Map(prevMap);
|
|
279
|
+
// selectedImageIds.forEach(id => {
|
|
280
|
+
// const currentState = newMap.get(id) || initialAdjustments;
|
|
281
|
+
// const currentValue = currentState[key];
|
|
282
|
+
// const newValue = clamp(currentValue + amount);
|
|
283
|
+
// newMap.set(id, { ...currentState, [key]: newValue });
|
|
284
|
+
// });
|
|
285
|
+
// console.log("this is UI Setter: ", uiSetter);
|
|
286
|
+
// return newMap;
|
|
287
|
+
// });
|
|
539
288
|
// }
|
|
540
|
-
// }
|
|
541
|
-
const handleToggleImageSelection = useCallback((imageId) => {
|
|
542
|
-
const newSelectedIds = new Set(selectedImageIds);
|
|
543
|
-
const isCurrentlySelected = newSelectedIds.has(imageId);
|
|
544
|
-
if (isCurrentlySelected) {
|
|
545
|
-
if (newSelectedIds.size > 1) {
|
|
546
|
-
newSelectedIds.delete(imageId);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
else {
|
|
550
|
-
newSelectedIds.add(imageId);
|
|
551
|
-
// Apply the current UI's adjustments to the newly selected image.
|
|
552
|
-
setAdjustmentsMap(prevMap => {
|
|
553
|
-
const newMap = new Map(prevMap);
|
|
554
|
-
const currentUiState = {
|
|
555
|
-
tempScore, tintScore, vibranceScore, saturationScore,
|
|
556
|
-
exposureScore, highlightsScore, shadowsScore, whitesScore,
|
|
557
|
-
blacksScore, contrastScore, clarityScore, sharpnessScore
|
|
558
|
-
};
|
|
559
|
-
newMap.set(imageId, currentUiState);
|
|
560
|
-
return newMap;
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
setSelectedImageIds(newSelectedIds);
|
|
564
|
-
}, [selectedImageIds, tempScore, tintScore, vibranceScore, saturationScore, exposureScore, highlightsScore, shadowsScore, whitesScore, blacksScore, contrastScore, clarityScore, sharpnessScore]);
|
|
565
|
-
const createAbsoluteSetter = (key, setter) => (value) => {
|
|
566
|
-
setter(value); // Update UI slider
|
|
567
|
-
if (isBulkEditing) {
|
|
568
|
-
setAdjustmentsMap(prevMap => {
|
|
569
|
-
const newMap = new Map(prevMap);
|
|
570
|
-
selectedImageIds.forEach(id => {
|
|
571
|
-
const currentState = newMap.get(id) || initialAdjustments;
|
|
572
|
-
newMap.set(id, { ...currentState, [key]: value });
|
|
573
|
-
});
|
|
574
|
-
return newMap;
|
|
575
|
-
});
|
|
576
|
-
}
|
|
577
|
-
};
|
|
578
|
-
const createRelativeAdjuster = (key, uiSetter, amount) => () => {
|
|
579
|
-
uiSetter(prev => clamp(prev + amount));
|
|
580
|
-
if (isBulkEditing) {
|
|
581
|
-
setAdjustmentsMap(prevMap => {
|
|
582
|
-
const newMap = new Map(prevMap);
|
|
583
|
-
selectedImageIds.forEach(id => {
|
|
584
|
-
const currentState = newMap.get(id) || initialAdjustments;
|
|
585
|
-
const currentValue = currentState[key];
|
|
586
|
-
const newValue = clamp(currentValue + amount);
|
|
587
|
-
newMap.set(id, { ...currentState, [key]: newValue });
|
|
588
|
-
});
|
|
589
|
-
console.log("this is UI Setter: ", uiSetter);
|
|
590
|
-
return newMap;
|
|
591
|
-
});
|
|
592
|
-
}
|
|
593
|
-
};
|
|
289
|
+
// };
|
|
594
290
|
// const setTempScoreAbs = createAbsoluteSetter('tempScore', setTempScore);
|
|
595
291
|
// const setTintScoreAbs = createAbsoluteSetter('tintScore', setTintScore);
|
|
596
292
|
// const setVibranceScoreAbs = createAbsoluteSetter('vibranceScore', setVibranceScore);
|
|
@@ -678,8 +374,10 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
678
374
|
}
|
|
679
375
|
}, []);
|
|
680
376
|
const handleBackCallback = useCallback(() => {
|
|
681
|
-
|
|
682
|
-
|
|
377
|
+
if (!galleryImageData)
|
|
378
|
+
return;
|
|
379
|
+
controller.handleBack(firebaseUid, galleryImageData.id);
|
|
380
|
+
}, [controller, firebaseUid, galleryImageData]);
|
|
683
381
|
// MARK: - UI Handlers (Moved from page.tsx)
|
|
684
382
|
// Header and Dialog Handlers
|
|
685
383
|
const handleHeaderMenuClick = (event) => setHeaderMenuAnchorEl(event.currentTarget);
|
|
@@ -689,22 +387,22 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
689
387
|
};
|
|
690
388
|
const handleOpenCopyDialog = () => {
|
|
691
389
|
const newColorChecks = {
|
|
692
|
-
temperature: tempScore !== 0,
|
|
693
|
-
tint: tintScore !== 0,
|
|
694
|
-
vibrance: vibranceScore !== 0,
|
|
695
|
-
saturation: saturationScore !== 0,
|
|
390
|
+
temperature: currentAdjustmentsState.tempScore !== 0,
|
|
391
|
+
tint: currentAdjustmentsState.tintScore !== 0,
|
|
392
|
+
vibrance: currentAdjustmentsState.vibranceScore !== 0,
|
|
393
|
+
saturation: currentAdjustmentsState.saturationScore !== 0,
|
|
696
394
|
};
|
|
697
395
|
const newLightChecks = {
|
|
698
|
-
exposure: exposureScore !== 0,
|
|
699
|
-
contrast: contrastScore !== 0,
|
|
700
|
-
highlights: highlightsScore !== 0,
|
|
701
|
-
shadows: shadowsScore !== 0,
|
|
702
|
-
whites: whitesScore !== 0,
|
|
703
|
-
blacks: blacksScore !== 0,
|
|
396
|
+
exposure: currentAdjustmentsState.exposureScore !== 0,
|
|
397
|
+
contrast: currentAdjustmentsState.contrastScore !== 0,
|
|
398
|
+
highlights: currentAdjustmentsState.highlightsScore !== 0,
|
|
399
|
+
shadows: currentAdjustmentsState.shadowsScore !== 0,
|
|
400
|
+
whites: currentAdjustmentsState.whitesScore !== 0,
|
|
401
|
+
blacks: currentAdjustmentsState.blacksScore !== 0,
|
|
704
402
|
};
|
|
705
403
|
const newDetailsChecks = {
|
|
706
|
-
clarity: clarityScore !== 0,
|
|
707
|
-
sharpness: sharpnessScore !== 0,
|
|
404
|
+
clarity: currentAdjustmentsState.clarityScore !== 0,
|
|
405
|
+
sharpness: currentAdjustmentsState.sharpnessScore !== 0,
|
|
708
406
|
};
|
|
709
407
|
setCopyColorChecks(newColorChecks);
|
|
710
408
|
setCopyLightChecks(newLightChecks);
|
|
@@ -739,40 +437,37 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
739
437
|
const adjustmentsToCopy = {};
|
|
740
438
|
// Color Adjustments
|
|
741
439
|
if (copyColorChecks.temperature)
|
|
742
|
-
adjustmentsToCopy.tempScore = tempScore;
|
|
440
|
+
adjustmentsToCopy.tempScore = currentAdjustmentsState.tempScore;
|
|
743
441
|
if (copyColorChecks.tint)
|
|
744
|
-
adjustmentsToCopy.tintScore = tintScore;
|
|
442
|
+
adjustmentsToCopy.tintScore = currentAdjustmentsState.tintScore;
|
|
745
443
|
if (copyColorChecks.vibrance)
|
|
746
|
-
adjustmentsToCopy.vibranceScore = vibranceScore;
|
|
444
|
+
adjustmentsToCopy.vibranceScore = currentAdjustmentsState.vibranceScore;
|
|
747
445
|
if (copyColorChecks.saturation)
|
|
748
|
-
adjustmentsToCopy.saturationScore = saturationScore;
|
|
446
|
+
adjustmentsToCopy.saturationScore = currentAdjustmentsState.saturationScore;
|
|
749
447
|
// Light Adjustments
|
|
750
448
|
if (copyLightChecks.exposure)
|
|
751
|
-
adjustmentsToCopy.exposureScore = exposureScore;
|
|
449
|
+
adjustmentsToCopy.exposureScore = currentAdjustmentsState.exposureScore;
|
|
752
450
|
if (copyLightChecks.contrast)
|
|
753
|
-
adjustmentsToCopy.contrastScore = contrastScore;
|
|
451
|
+
adjustmentsToCopy.contrastScore = currentAdjustmentsState.contrastScore;
|
|
754
452
|
if (copyLightChecks.highlights)
|
|
755
|
-
adjustmentsToCopy.highlightsScore = highlightsScore;
|
|
453
|
+
adjustmentsToCopy.highlightsScore = currentAdjustmentsState.highlightsScore;
|
|
756
454
|
if (copyLightChecks.shadows)
|
|
757
|
-
adjustmentsToCopy.shadowsScore = shadowsScore;
|
|
455
|
+
adjustmentsToCopy.shadowsScore = currentAdjustmentsState.shadowsScore;
|
|
758
456
|
if (copyLightChecks.whites)
|
|
759
|
-
adjustmentsToCopy.whitesScore = whitesScore;
|
|
457
|
+
adjustmentsToCopy.whitesScore = currentAdjustmentsState.whitesScore;
|
|
760
458
|
if (copyLightChecks.blacks)
|
|
761
|
-
adjustmentsToCopy.blacksScore = blacksScore;
|
|
459
|
+
adjustmentsToCopy.blacksScore = currentAdjustmentsState.blacksScore;
|
|
762
460
|
// Details Adjustments
|
|
763
461
|
if (copyDetailsChecks.clarity)
|
|
764
|
-
adjustmentsToCopy.clarityScore = clarityScore;
|
|
462
|
+
adjustmentsToCopy.clarityScore = currentAdjustmentsState.clarityScore;
|
|
765
463
|
if (copyDetailsChecks.sharpness)
|
|
766
|
-
adjustmentsToCopy.sharpnessScore = sharpnessScore;
|
|
464
|
+
adjustmentsToCopy.sharpnessScore = currentAdjustmentsState.sharpnessScore;
|
|
767
465
|
// Combine with existing copied adjustments to not lose unchecked values from a previous copy
|
|
768
466
|
setCopiedAdjustments(prev => ({ ...initialAdjustments, ...prev, ...adjustmentsToCopy }));
|
|
769
467
|
console.log("Copied selected adjustments:", adjustmentsToCopy);
|
|
770
|
-
}, [
|
|
771
|
-
copyColorChecks, copyLightChecks, copyDetailsChecks,
|
|
772
|
-
tempScore, tintScore, vibranceScore, saturationScore, exposureScore, contrastScore,
|
|
773
|
-
highlightsScore, shadowsScore, whitesScore, blacksScore, clarityScore, sharpnessScore
|
|
774
|
-
]);
|
|
468
|
+
}, [copyColorChecks, copyLightChecks, copyDetailsChecks, currentAdjustmentsState]);
|
|
775
469
|
const handleConfirmCopy = () => { handleCopyEdit(); handleCloseCopyDialog(); setShowCopyAlert(true); };
|
|
470
|
+
// MARK: - UI Handlers
|
|
776
471
|
// Panel Handlers
|
|
777
472
|
const handleColorAccordionChange = (panel) => (_, isExpanded) => {
|
|
778
473
|
setColorAdjustmentExpandedPanels(prev => isExpanded ? [...new Set([...prev, panel])] : prev.filter(p => p !== panel));
|
|
@@ -810,7 +505,7 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
810
505
|
const handleCreatePreset = useCallback(async () => {
|
|
811
506
|
if (!controller)
|
|
812
507
|
return;
|
|
813
|
-
const currentAdjustments = {
|
|
508
|
+
const currentAdjustments = { ...currentAdjustmentsState };
|
|
814
509
|
try {
|
|
815
510
|
const newPreset = await controller.createPreset(firebaseUid, presetName, currentAdjustments);
|
|
816
511
|
if (newPreset) {
|
|
@@ -827,7 +522,7 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
827
522
|
setIsPresetCreated(true);
|
|
828
523
|
handleClosePresetModal();
|
|
829
524
|
setTimeout(() => setIsPresetCreated(false), 1000);
|
|
830
|
-
}, [controller, presetName,
|
|
525
|
+
}, [controller, presetName, currentAdjustmentsState, firebaseUid]);
|
|
831
526
|
const handleOpenPresetModalMobile = () => { setIsPresetCreated(false); setPresetModalOpenMobile(true); };
|
|
832
527
|
const handleClosePresetModalMobile = () => setPresetModalOpenMobile(false);
|
|
833
528
|
const handleCreatePresetMobile = () => {
|
|
@@ -849,48 +544,47 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
849
544
|
const preset = presets.find(p => p.id === activePresetMenuId);
|
|
850
545
|
if (preset) {
|
|
851
546
|
setPresetToRename(preset);
|
|
852
|
-
setNewPresetName(preset.name);
|
|
547
|
+
setNewPresetName(preset.name);
|
|
853
548
|
setRenameModalOpen(true);
|
|
854
549
|
}
|
|
855
|
-
handlePresetMenuClose();
|
|
550
|
+
handlePresetMenuClose();
|
|
856
551
|
}, [activePresetMenuId, presets]);
|
|
857
552
|
const handleCloseRenameModal = () => {
|
|
858
553
|
setRenameModalOpen(false);
|
|
859
554
|
setPresetToRename(null);
|
|
860
555
|
setNewPresetName("");
|
|
861
556
|
};
|
|
862
|
-
// Bulk Editing Handlers
|
|
863
|
-
const toggleBulkEditing = () => {
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
};
|
|
870
|
-
const handleSelectBulkPreset = (event) => setSelectedBulkPreset(event.target.value);
|
|
557
|
+
// // Bulk Editing Handlers
|
|
558
|
+
// const toggleBulkEditing = () => {
|
|
559
|
+
// setIsBulkEditing(prev => {
|
|
560
|
+
// const isNowBulk = !prev;
|
|
561
|
+
// setSelectedImages(isNowBulk ? 'Selected' : 'Select');
|
|
562
|
+
// return isNowBulk;
|
|
563
|
+
// });
|
|
564
|
+
// };
|
|
565
|
+
// const handleSelectBulkPreset = (event: SelectChangeEvent<string>) => setSelectedBulkPreset(event.target.value as string);
|
|
871
566
|
// MARK : Image original and canvas
|
|
872
|
-
const handleShowOriginal = useCallback(() => {
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
}, [isImageLoaded, history, historyIndex]);
|
|
567
|
+
// const handleShowOriginal = useCallback(() => {
|
|
568
|
+
// if (!editorRef.current || !isImageLoaded) return;
|
|
569
|
+
// console.log("Showing original image...");
|
|
570
|
+
// // 1. Set the flag to true to pause history recording
|
|
571
|
+
// setIsViewingOriginal(true);
|
|
572
|
+
// // 2. Apply the initial state to the view
|
|
573
|
+
// // applyAdjustmentState(initialAdjustments);
|
|
574
|
+
// }, [isImageLoaded]);
|
|
575
|
+
// const handleShowEdited = useCallback(() => {
|
|
576
|
+
// if (!editorRef.current || !isImageLoaded) return;
|
|
577
|
+
// console.log("Restoring edited image...");
|
|
578
|
+
// const latestState = history[historyIndex];
|
|
579
|
+
// if (latestState) {
|
|
580
|
+
// // 3. Re-apply the latest state from history
|
|
581
|
+
// // applyAdjustmentState(latestState);
|
|
582
|
+
// }
|
|
583
|
+
// // 4. Set the flag back to false AFTER the state has been restored.
|
|
584
|
+
// // A small timeout ensures this runs after the re-render.
|
|
585
|
+
// setTimeout(() => setIsViewingOriginal(false), 0);
|
|
586
|
+
// }, [isImageLoaded, history, historyIndex]);
|
|
587
|
+
// MARK: DEBUG (NEW LOGIC)
|
|
894
588
|
// MARK: - Zoom Handlers
|
|
895
589
|
const handleZoomAction = useCallback((action) => {
|
|
896
590
|
let newZoom = zoomLevel;
|
|
@@ -931,35 +625,9 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
931
625
|
}
|
|
932
626
|
setZoomLevel(Math.max(0.1, Math.min(newZoom, 8)));
|
|
933
627
|
}, [zoomLevel, isImageLoaded]);
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setContrast(contrastScore); updateCanvas(); } }, [contrastScore, isImageLoaded, updateCanvas]);
|
|
938
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setHighlights(highlightsScore); updateCanvas(); } }, [highlightsScore, isImageLoaded, updateCanvas]);
|
|
939
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setShadows(shadowsScore); updateCanvas(); } }, [shadowsScore, isImageLoaded, updateCanvas]);
|
|
940
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setSaturation(saturationScore); updateCanvas(); } }, [saturationScore, isImageLoaded, updateCanvas]);
|
|
941
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setTemperature(tempScore); updateCanvas(); } }, [tempScore, isImageLoaded, updateCanvas]);
|
|
942
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setTint(tintScore); updateCanvas(); } }, [tintScore, isImageLoaded, updateCanvas]);
|
|
943
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setBlacks(blacksScore); updateCanvas(); } }, [blacksScore, isImageLoaded, updateCanvas]);
|
|
944
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setWhites(whitesScore); updateCanvas(); } }, [whitesScore, isImageLoaded, updateCanvas]);
|
|
945
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setClarity(clarityScore); updateCanvas(); } }, [clarityScore, isImageLoaded, updateCanvas]);
|
|
946
|
-
// useEffect(() => { if (isImageLoaded) { editorRef.current?.setSharpness(sharpnessScore); updateCanvas(); } }, [sharpnessScore, isImageLoaded, updateCanvas]);
|
|
947
|
-
useEffect(() => {
|
|
948
|
-
// 5. Add a check to ignore state changes while viewing the original
|
|
949
|
-
if (!isImageLoaded || isViewingOriginal)
|
|
950
|
-
return;
|
|
951
|
-
const newState = { tempScore, tintScore, vibranceScore, exposureScore, highlightsScore, shadowsScore, whitesScore, blacksScore, saturationScore, contrastScore, clarityScore, sharpnessScore };
|
|
952
|
-
if (JSON.stringify(history[historyIndex]) === JSON.stringify(newState))
|
|
953
|
-
return;
|
|
954
|
-
const newHistory = history.slice(0, historyIndex + 1);
|
|
955
|
-
setHistory([...newHistory, newState]);
|
|
956
|
-
setHistoryIndex(newHistory.length);
|
|
957
|
-
}, [
|
|
958
|
-
tempScore, tintScore, vibranceScore, exposureScore, highlightsScore, shadowsScore,
|
|
959
|
-
whitesScore, blacksScore, saturationScore, contrastScore, clarityScore, sharpnessScore,
|
|
960
|
-
isImageLoaded, history, historyIndex,
|
|
961
|
-
isViewingOriginal
|
|
962
|
-
]);
|
|
628
|
+
const zoomLevelText = useMemo(() => {
|
|
629
|
+
return `${Math.round(zoomLevel * 100)}%`;
|
|
630
|
+
}, [zoomLevel]);
|
|
963
631
|
useEffect(() => {
|
|
964
632
|
if (showCopyAlert) {
|
|
965
633
|
const timer = setTimeout(() => setShowCopyAlert(false), 2000);
|
|
@@ -976,75 +644,26 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
976
644
|
window.removeEventListener('offline', handleOffline);
|
|
977
645
|
};
|
|
978
646
|
}, []);
|
|
979
|
-
useEffect(() => {
|
|
980
|
-
// The function returned by useEffect is the cleanup function.
|
|
981
|
-
// It will run only when the component that uses this hook unmounts.
|
|
982
|
-
return () => {
|
|
983
|
-
if (editorRef.current) {
|
|
984
|
-
console.log("Cleaning up Honcho Editor instance...");
|
|
985
|
-
editorRef.current.cleanup(); // This calls the C++ cleanup function
|
|
986
|
-
}
|
|
987
|
-
};
|
|
988
|
-
}, []);
|
|
989
|
-
// MARK: DEBUG (NEW LOGIC)
|
|
990
|
-
// const { width, height } = editorRef.current.getImageSize();
|
|
991
|
-
// canvasRef.current.width = width;
|
|
992
|
-
// canvasRef.current.height = height;
|
|
993
647
|
useEffect(() => {
|
|
994
648
|
if (canvasRef.current) {
|
|
995
649
|
canvasRef.current.style.transition = 'transform 0.1s ease-out';
|
|
996
650
|
canvasRef.current.style.transform = `scale(${zoomLevel})`;
|
|
997
651
|
}
|
|
998
652
|
}, [zoomLevel]);
|
|
999
|
-
// Undo, Redo, Revert
|
|
1000
|
-
const handleRevert = useCallback(() => {
|
|
1001
|
-
setCurrentAdjustmentsState(initialAdjustments);
|
|
1002
|
-
}, [updateCanvasEditor]);
|
|
1003
|
-
const handleUndo = useCallback(() => {
|
|
1004
|
-
if (historyIndex > 0) {
|
|
1005
|
-
const prevIndex = historyIndex - 1;
|
|
1006
|
-
setCurrentAdjustmentsState(history[prevIndex]);
|
|
1007
|
-
setHistoryIndex(prevIndex);
|
|
1008
|
-
}
|
|
1009
|
-
}, [history, historyIndex, updateCanvasEditor]);
|
|
1010
|
-
const handleRedo = useCallback(() => {
|
|
1011
|
-
if (historyIndex < history.length - 1) {
|
|
1012
|
-
const nextIndex = historyIndex + 1;
|
|
1013
|
-
setCurrentAdjustmentsState(history[nextIndex]);
|
|
1014
|
-
setHistoryIndex(nextIndex);
|
|
1015
|
-
}
|
|
1016
|
-
}, [history, historyIndex, updateCanvasEditor]);
|
|
1017
|
-
// Undo, Redo, Revert [END]
|
|
1018
|
-
// Swipe
|
|
1019
|
-
const swipeNext = useCallback(() => {
|
|
1020
|
-
// find next imageId
|
|
1021
|
-
// setCurrentImageId()
|
|
1022
|
-
}, []);
|
|
1023
|
-
const swipePrev = useCallback(() => {
|
|
1024
|
-
// find next imageId
|
|
1025
|
-
// setCurrentImageId()
|
|
1026
|
-
}, []);
|
|
1027
|
-
// Swipe [END]
|
|
1028
653
|
useEffect(() => {
|
|
1029
654
|
// will trigger when currentImageId change
|
|
1030
|
-
if (!
|
|
655
|
+
if (!galleryImageData)
|
|
1031
656
|
return;
|
|
1032
657
|
const init = async () => {
|
|
1033
658
|
if (editorRef.current?.getInitialized() === false) {
|
|
1034
659
|
await editorRef.current?.initialize();
|
|
1035
660
|
}
|
|
1036
|
-
const
|
|
1037
|
-
if (!imageData) {
|
|
1038
|
-
// TODO please check to make sure not crash
|
|
1039
|
-
throw new Error("can't load image data");
|
|
1040
|
-
}
|
|
1041
|
-
setCurrentImageData(imageData);
|
|
1042
|
-
const adjustmentData = imageData.editor_config?.color_adjustment;
|
|
661
|
+
const adjustmentData = galleryImageData.editor_config?.color_adjustment;
|
|
1043
662
|
// set event
|
|
1044
|
-
setEventId(
|
|
663
|
+
setEventId(galleryImageData.event_id);
|
|
1045
664
|
// TODO get slideshow image list
|
|
1046
665
|
// set to imageList
|
|
1047
|
-
const pathGallery = extractPathFromGallery(
|
|
666
|
+
const pathGallery = extractPathFromGallery(galleryImageData);
|
|
1048
667
|
// load image to editor
|
|
1049
668
|
await loadImageEditorFromUrl(pathGallery);
|
|
1050
669
|
console.log("Image loaded to editor");
|
|
@@ -1052,14 +671,14 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
1052
671
|
if (adjustmentData) {
|
|
1053
672
|
const adjustmentState = mapColorAdjustmentToAdjustmentState(adjustmentData);
|
|
1054
673
|
// set adjustment to editor to make adjustmentState change
|
|
1055
|
-
|
|
674
|
+
historyActions.syncHistory([adjustmentState]);
|
|
1056
675
|
}
|
|
1057
676
|
else {
|
|
1058
677
|
console.log("no adjustment found, use default");
|
|
1059
678
|
}
|
|
1060
679
|
};
|
|
1061
680
|
init();
|
|
1062
|
-
}, [
|
|
681
|
+
}, [galleryImageData, editorRef.current]);
|
|
1063
682
|
useEffect(() => {
|
|
1064
683
|
// Render photo if adjustmentState change;
|
|
1065
684
|
if (!editorRef.current)
|
|
@@ -1077,12 +696,15 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
1077
696
|
editorStatus,
|
|
1078
697
|
isEditorReady,
|
|
1079
698
|
isImageLoaded: isImageLoaded && !isGalleryLoading, // Combine loading states
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
handlePrev: onSwipePrev,
|
|
1083
|
-
handleNext: onSwipeNext,
|
|
1084
|
-
isPrevAvailable,
|
|
699
|
+
onSwipeNext,
|
|
700
|
+
onSwipePrev,
|
|
1085
701
|
isNextAvailable,
|
|
702
|
+
isPrevAvailable,
|
|
703
|
+
isGalleryLoading,
|
|
704
|
+
galleryError,
|
|
705
|
+
galleryImageData,
|
|
706
|
+
currentAdjustmentsState,
|
|
707
|
+
historyActions,
|
|
1086
708
|
// History functions and state
|
|
1087
709
|
handleUndo: historyActions.undo,
|
|
1088
710
|
handleRedo: historyActions.redo,
|
|
@@ -1103,7 +725,6 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
1103
725
|
isConnectionSlow,
|
|
1104
726
|
showCopyAlert,
|
|
1105
727
|
isCopyDialogOpen,
|
|
1106
|
-
isPublished,
|
|
1107
728
|
activePanel,
|
|
1108
729
|
activeSubPanel,
|
|
1109
730
|
headerMenuAnchorEl,
|
|
@@ -1117,32 +738,18 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
1117
738
|
isPresetCreated,
|
|
1118
739
|
selectedMobilePreset,
|
|
1119
740
|
selectedDesktopPreset,
|
|
1120
|
-
selectedBulkPreset,
|
|
1121
741
|
presetMenuAnchorEl,
|
|
1122
742
|
activePresetMenuId,
|
|
1123
|
-
currentAspectRatio,
|
|
1124
|
-
currentSquareRatio,
|
|
1125
|
-
currentWideRatio,
|
|
1126
|
-
angelScore,
|
|
1127
|
-
widthSizePX,
|
|
1128
|
-
heightSizePX,
|
|
1129
|
-
isBulkEditing,
|
|
1130
|
-
selectedImages,
|
|
1131
743
|
colorAdjustments,
|
|
1132
744
|
lightAdjustments,
|
|
1133
745
|
detailsAdjustments,
|
|
1134
|
-
handleShowOriginal,
|
|
1135
|
-
handleShowEdited,
|
|
1136
746
|
handleWheelZoom,
|
|
1137
747
|
handleZoomAction,
|
|
1138
|
-
zoomLevelText
|
|
748
|
+
zoomLevelText,
|
|
1139
749
|
presets,
|
|
1140
750
|
// Functions
|
|
1141
751
|
handleScriptReady,
|
|
1142
|
-
handleFileChange,
|
|
1143
752
|
handleAlertClose,
|
|
1144
|
-
loadImageFromId,
|
|
1145
|
-
loadImageFromUrl,
|
|
1146
753
|
handleOpenCopyDialog,
|
|
1147
754
|
handleCloseCopyDialog,
|
|
1148
755
|
copyColorChecks,
|
|
@@ -1194,17 +801,8 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
1194
801
|
handleOpenWatermarkView,
|
|
1195
802
|
handleSaveWatermark,
|
|
1196
803
|
handleCancelWatermark,
|
|
1197
|
-
toggleBulkEditing,
|
|
1198
|
-
handleSelectBulkPreset,
|
|
1199
|
-
// Adjustment State & Setters
|
|
1200
|
-
currentAdjustmentsState,
|
|
1201
|
-
setCurrentAdjustmentsState,
|
|
1202
804
|
// Bulk Adjustment Handlers
|
|
1203
805
|
// Note: These handlers are for image list
|
|
1204
|
-
imageList,
|
|
1205
|
-
adjustmentsMap,
|
|
1206
|
-
selectedImageIds,
|
|
1207
|
-
handleToggleImageSelection,
|
|
1208
806
|
// Note: These handlers are for bulk adjustments
|
|
1209
807
|
// Adjustment Colors
|
|
1210
808
|
// handleBulkTempDecreaseMax,
|