@yogiswara/honcho-editor-ui 2.5.10 → 2.6.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.
Files changed (50) hide show
  1. package/dist/components/editor/HBulkPreset.js +12 -2
  2. package/dist/hooks/demo/HonchoEditorBulkDemo.d.ts +3 -0
  3. package/dist/hooks/demo/HonchoEditorBulkDemo.js +228 -0
  4. package/dist/hooks/demo/HonchoEditorSingleCleanDemo.d.ts +3 -0
  5. package/dist/hooks/demo/HonchoEditorSingleCleanDemo.js +354 -0
  6. package/dist/hooks/demo/index.d.ts +2 -0
  7. package/dist/hooks/demo/index.js +2 -0
  8. package/dist/hooks/editor/type.d.ts +71 -0
  9. package/dist/hooks/editor/useHonchoEditorBulk.d.ts +10 -12
  10. package/dist/hooks/editor/useHonchoEditorBulk.js +126 -10
  11. package/dist/hooks/editor/useHonchoEditorSingle.d.ts +43 -0
  12. package/dist/hooks/editor/useHonchoEditorSingle.js +158 -0
  13. package/dist/hooks/useAdjustmentHistory.d.ts +9 -5
  14. package/dist/hooks/useAdjustmentHistory.js +187 -31
  15. package/dist/hooks/useAdjustmentHistoryBatch.d.ts +18 -1
  16. package/dist/hooks/useAdjustmentHistoryBatch.js +627 -201
  17. package/dist/hooks/useGallerySwipe.d.ts +1 -1
  18. package/dist/hooks/usePaging.d.ts +1 -1
  19. package/dist/hooks/usePaging.js +1 -1
  20. package/dist/hooks/usePreset.d.ts +1 -1
  21. package/dist/hooks/usePreset.js +35 -35
  22. package/dist/index.d.ts +3 -3
  23. package/dist/index.js +1 -1
  24. package/dist/lib/context/EditorContext.d.ts +10 -0
  25. package/dist/lib/context/EditorContext.js +4 -2
  26. package/dist/lib/hooks/useEditorHeadless.d.ts +18 -2
  27. package/dist/lib/hooks/useEditorHeadless.js +142 -63
  28. package/dist/utils/adjustment.d.ts +2 -1
  29. package/dist/utils/adjustment.js +16 -0
  30. package/dist/utils/imageLoader.d.ts +11 -0
  31. package/dist/utils/imageLoader.js +53 -0
  32. package/package.json +1 -1
  33. package/dist/components/editor/GalleryAlbum/SimplifiedAlbumGallery.d.ts +0 -17
  34. package/dist/components/editor/GalleryAlbum/SimplifiedAlbumGallery.js +0 -14
  35. package/dist/components/editor/GalleryAlbum/SimplifiedImageItem.d.ts +0 -8
  36. package/dist/components/editor/GalleryAlbum/SimplifiedImageItem.js +0 -30
  37. package/dist/components/editor/HImageEditorPage.d.ts +0 -1
  38. package/dist/components/editor/HImageEditorPage.js +0 -187
  39. package/dist/hooks/__tests__/useGallerySwipe.test.d.ts +0 -0
  40. package/dist/hooks/__tests__/useGallerySwipe.test.js +0 -619
  41. package/dist/hooks/editor/useHonchoEditor.d.ts +0 -203
  42. package/dist/hooks/editor/useHonchoEditor.js +0 -716
  43. package/dist/hooks/useAdjustmentHistory.demo.d.ts +0 -8
  44. package/dist/hooks/useAdjustmentHistory.demo.js +0 -106
  45. package/dist/hooks/useAdjustmentHistory.example.d.ts +0 -38
  46. package/dist/hooks/useAdjustmentHistory.example.js +0 -182
  47. package/dist/hooks/useAdjustmentHistory.syncDemo.d.ts +0 -8
  48. package/dist/hooks/useAdjustmentHistory.syncDemo.js +0 -180
  49. package/dist/hooks/useGallerySwipe.example.d.ts +0 -24
  50. package/dist/hooks/useGallerySwipe.example.js +0 -184
@@ -1,716 +0,0 @@
1
- 'use client';
2
- import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
3
- import { HonchoEditor } from '../../lib/editor/honcho-editor';
4
- import { mapAdjustmentStateToAdjustmentEditor, mapColorAdjustmentToAdjustmentState } from '../../utils/adjustment';
5
- import { useAdjustmentHistory } from '../useAdjustmentHistory';
6
- import { useGallerySwipe } from '../useGallerySwipe';
7
- const initialAdjustments = {
8
- tempScore: 0, tintScore: 0, vibranceScore: 0, exposureScore: 0, highlightsScore: 0, shadowsScore: 0,
9
- whitesScore: 0, blacksScore: 0, saturationScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
10
- };
11
- export function useHonchoEditor(controller, initImageId, firebaseUid) {
12
- const { onSwipeNext, onSwipePrev, isNextAvailable, isPrevAvailable, isLoading: isGalleryLoading, error: galleryError, currentImageData: galleryImageData } = useGallerySwipe(firebaseUid, initImageId, controller);
13
- // The useAdjustmentHistory hook now manages all undo/redo and adjustment state logic.
14
- const { currentState: currentAdjustmentsState, actions: historyActions, historyInfo, config: historyConfig, } = useAdjustmentHistory(initialAdjustments);
15
- const [eventId, setEventId] = useState(null);
16
- // MARK: - Core Editor State & Refs
17
- const editorRef = useRef(null);
18
- const canvasRef = useRef(null);
19
- const canvasContainerRef = useRef(null);
20
- const fileInputRef = useRef(null);
21
- const [editorStatus, setEditorStatus] = useState("Initializing...");
22
- const [isEditorReady, setIsEditorReady] = useState(false);
23
- const [isImageLoaded, setIsImageLoaded] = useState(false);
24
- const [zoomLevel, setZoomLevel] = useState(1);
25
- const [presets, setPresets] = useState([]);
26
- // MARK: - Adjustment & History State
27
- const [copiedAdjustments, setCopiedAdjustments] = useState(null);
28
- const [copyColorChecks, setCopyColorChecks] = useState({ temperature: true, tint: true, vibrance: true, saturation: true });
29
- const [copyLightChecks, setCopyLightChecks] = useState({ exposure: true, contrast: true, highlights: true, shadows: true, whites: true, blacks: true });
30
- const [copyDetailsChecks, setCopyDetailsChecks] = useState({ clarity: true, sharpness: true });
31
- const [copyDialogExpanded, setCopyDialogExpanded] = useState({ color: true, light: true, details: true });
32
- // MARK: - UI & App State (Moved from page.tsx)
33
- // General UI State
34
- const [isOnline, setIsOnline] = useState(true);
35
- const [isConnectionSlow, setIsConnectionSlow] = useState(false);
36
- const [showCopyAlert, setShowCopyAlert] = useState(false);
37
- const [isCopyDialogOpen, setCopyDialogOpen] = useState(false);
38
- const [activePanel, setActivePanel] = useState('colorAdjustment');
39
- const [activeSubPanel, setActiveSubPanel] = useState('');
40
- const [headerMenuAnchorEl, setHeaderMenuAnchorEl] = useState(null);
41
- const [anchorMenuZoom, setAnchorMenuZoom] = useState(null);
42
- // Panel Expansion State
43
- const [colorAdjustmentExpandedPanels, setColorAdjustmentExpandedPanels] = useState(['whiteBalance', 'light', 'details']);
44
- const [presetExpandedPanels, setPresetExpandedPanels] = useState(['preset']);
45
- // Watermark State
46
- const [isCreatingWatermark, setIsCreatingWatermark] = useState(false);
47
- // Preset State
48
- const [isPresetModalOpen, setPresetModalOpen] = useState(false);
49
- const [isPresetModalOpenMobile, setPresetModalOpenMobile] = useState(false);
50
- const [presetName, setPresetName] = useState("Type Here");
51
- const [isPresetCreated, setIsPresetCreated] = useState(false);
52
- const [selectedMobilePreset, setSelectedMobilePreset] = useState('preset1');
53
- const [selectedDesktopPreset, setSelectedDesktopPreset] = useState('preset1');
54
- const [presetMenuAnchorEl, setPresetMenuAnchorEl] = useState(null);
55
- const [activePresetMenuId, setActivePresetMenuId] = useState(null);
56
- const [isRenameModalOpen, setRenameModalOpen] = useState(false);
57
- const [presetToRename, setPresetToRename] = useState(null);
58
- const [newPresetName, setNewPresetName] = useState("");
59
- // Aspect Ratio State
60
- // Note: not used yet
61
- // const [currentAspectRatio, setCurrentAspectRatio] = useState('potrait');
62
- // const [currentSquareRatio, setCurrentSquareRatio] = useState('original');
63
- // const [currentWideRatio, setCurrentWideRatio] = useState('1:1');
64
- // const [angelScore, setAngleScore] = useState(0);
65
- // const [widthSizePX, setWidthSizePX] = useState(0);
66
- // const [heightSizePX, setHeightSizePX] = useState(0);
67
- // Bulk Editing State
68
- // const [isBulkEditing, setIsBulkEditing] = useState(false);
69
- // const [selectedImages, setSelectedImages] = useState('Select');
70
- // const [imageList, setImageList] = useState<ImageItem[]>([]);
71
- // const [selectedImageIds, setSelectedImageIds] = useState<Set<string>>(new Set());
72
- // MARK: Framse- (Later use)
73
- // State for Copying specific adjustments
74
- const [colorAdjustments, setColorAdjustments] = useState(true);
75
- const [lightAdjustments, setLightAdjustments] = useState(true);
76
- const [detailsAdjustments, setDetailsAdjustments] = useState(true);
77
- // MARK: dragable
78
- const PEEK_HEIGHT = 20;
79
- const COLLAPSED_HEIGHT = 165;
80
- const PANEL_CHROME_HEIGHT = 10;
81
- // Mobile Draggable Panel State
82
- const [panelHeight, setPanelHeight] = useState(COLLAPSED_HEIGHT);
83
- const [contentHeight, setContentHeight] = useState(0);
84
- const [isDragging, setIsDragging] = useState(false);
85
- const dragStartPos = useRef(0);
86
- const initialHeight = useRef(0);
87
- const panelRef = useRef(null);
88
- const contentRef = useRef(null);
89
- // Effect for keyboard shortcuts
90
- // MARK: - Core Editor Logic
91
- // Mobile Panel Drag Handlers
92
- const handleContentHeightChange = useCallback((height) => {
93
- if (height > 0 && height !== contentHeight)
94
- setContentHeight(height);
95
- }, [contentHeight]);
96
- const handleDragStart = useCallback((e) => {
97
- setIsDragging(true);
98
- const startY = 'touches' in e ? e.touches[0].clientY : e.clientY;
99
- dragStartPos.current = startY;
100
- initialHeight.current = panelHeight;
101
- if (panelRef.current)
102
- panelRef.current.style.transition = 'none';
103
- }, [panelHeight]);
104
- const handleDragMove = useCallback((e) => {
105
- if (!isDragging)
106
- return;
107
- const currentY = 'touches' in e ? e.touches[0].clientY : e.clientY;
108
- const deltaY = dragStartPos.current - currentY;
109
- const newHeight = initialHeight.current + deltaY;
110
- const dynamicPanelFullHeight = contentHeight + PANEL_CHROME_HEIGHT;
111
- const clampedHeight = Math.max(PEEK_HEIGHT, Math.min(newHeight, dynamicPanelFullHeight));
112
- setPanelHeight(clampedHeight);
113
- }, [isDragging, contentHeight]);
114
- const handleDragEnd = useCallback(() => {
115
- if (!isDragging)
116
- return;
117
- setIsDragging(false);
118
- dragStartPos.current = 0;
119
- if (panelRef.current)
120
- panelRef.current.style.transition = 'height 0.3s ease-in-out';
121
- const dynamicPanelFullHeight = contentHeight + PANEL_CHROME_HEIGHT;
122
- const snapPointLow = (PEEK_HEIGHT + COLLAPSED_HEIGHT) / 2;
123
- const snapPointHigh = (COLLAPSED_HEIGHT + dynamicPanelFullHeight) / 2;
124
- if (panelHeight < snapPointLow) {
125
- setPanelHeight(PEEK_HEIGHT);
126
- }
127
- else if (panelHeight >= snapPointLow && panelHeight < snapPointHigh) {
128
- setPanelHeight(COLLAPSED_HEIGHT);
129
- }
130
- else {
131
- setPanelHeight(dynamicPanelFullHeight);
132
- }
133
- }, [isDragging, panelHeight, contentHeight]);
134
- // Keyboard Shortcut Handler
135
- const handleKeyDown = useCallback((event) => {
136
- const target = event.target;
137
- if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA')
138
- return;
139
- if ((event.ctrlKey || event.metaKey) && event.key === 'c') {
140
- event.preventDefault();
141
- handleOpenCopyDialog();
142
- }
143
- }, [ /* handleOpenCopyDialog dependency */]);
144
- const extractPathFromGallery = useCallback((data) => {
145
- const imagePath = data?.raw_edited?.path
146
- ? data.raw_edited.path
147
- : data?.download?.path;
148
- console.log("[DEBUG FOR EXTRACT] Extracted imagePath to load:", imagePath);
149
- return imagePath;
150
- }, []);
151
- const loadImageEditorFromUrl = useCallback(async (url) => {
152
- try {
153
- if (!editorRef.current)
154
- return;
155
- setEditorStatus("Downloading image...");
156
- const response = await fetch(url);
157
- if (!response.ok)
158
- throw new Error(`Failed to fetch image from URL: ${url}`);
159
- const blob = await response.blob();
160
- const filename = url.substring(url.lastIndexOf('/') + 1) || 'image.jpg';
161
- const file = new File([blob], filename, { type: blob.type });
162
- console.log("[DEBUG FOR LOAD] File to load:", file);
163
- await editorRef.current.loadImageFromFile(file);
164
- setIsImageLoaded(true);
165
- }
166
- catch (error) {
167
- console.error(error);
168
- setEditorStatus("Error: Could not load image from URL.");
169
- setIsImageLoaded(false);
170
- }
171
- }, [editorRef.current]);
172
- const handleScriptReady = useCallback(async () => {
173
- console.log("[Editor] Script tag is ready."); // Log entry
174
- if (typeof window.Module === 'function' && !editorRef.current) {
175
- console.log("[Editor] window.Module found. Initializing editor..."); // Log entry
176
- try {
177
- setEditorStatus("Loading WASM module...");
178
- const editor = new HonchoEditor();
179
- await editor.initialize(true);
180
- editorRef.current = editor;
181
- setIsEditorReady(true);
182
- setEditorStatus("Ready! Select an image to start.");
183
- }
184
- catch (error) {
185
- console.error("[Editor] CRITICAL: Editor initialization failed:", error); // Critical error log
186
- setEditorStatus(`Error: Could not load editor. See device logs.`);
187
- }
188
- }
189
- else {
190
- console.warn("[Editor] handleScriptReady called but conditions not met.", {
191
- isModuleFunction: typeof window.Module === 'function',
192
- isEditorAlreadyInitialized: !!editorRef.current
193
- });
194
- }
195
- }, []);
196
- const handleBackCallback = useCallback(() => {
197
- if (!galleryImageData)
198
- return;
199
- controller.handleBack(firebaseUid, galleryImageData.id);
200
- }, [controller, firebaseUid, galleryImageData]);
201
- // MARK: - UI Handlers
202
- // Panel Handlers
203
- const handleColorAccordionChange = (panel) => (_, isExpanded) => {
204
- setColorAdjustmentExpandedPanels(prev => isExpanded ? [...new Set([...prev, panel])] : prev.filter(p => p !== panel));
205
- };
206
- const handlePresetAccordionChange = (panel) => (_, isExpanded) => {
207
- setPresetExpandedPanels(prev => isExpanded ? [...new Set([...prev, panel])] : prev.filter(p => p !== panel));
208
- };
209
- const handleShowOriginal = useCallback(() => {
210
- if (!editorRef.current || !isImageLoaded || !canvasRef.current)
211
- return;
212
- console.log("Showing original image...");
213
- editorRef.current.setAdjustments(mapAdjustmentStateToAdjustmentEditor(initialAdjustments));
214
- editorRef.current.processImage();
215
- editorRef.current.renderToCanvas(canvasRef.current);
216
- }, [isImageLoaded, editorRef, canvasRef]);
217
- const handleShowEdited = useCallback(() => {
218
- if (!editorRef.current || !isImageLoaded || !canvasRef.current)
219
- return;
220
- editorRef.current.setAdjustments(mapAdjustmentStateToAdjustmentEditor(currentAdjustmentsState));
221
- editorRef.current.processImage();
222
- editorRef.current.renderToCanvas(canvasRef.current);
223
- }, [isImageLoaded, editorRef, canvasRef, currentAdjustmentsState]);
224
- // MARK: - Preset Handlers
225
- // Also it calls for the backend endpoint
226
- const handleSelectMobilePreset = (presetId) => setSelectedMobilePreset(presetId);
227
- const handleSelectDesktopPreset = (presetId) => setSelectedDesktopPreset(presetId);
228
- const handlePresetMenuClick = (event, presetId) => {
229
- event.stopPropagation();
230
- setPresetMenuAnchorEl(event.currentTarget);
231
- setActivePresetMenuId(presetId);
232
- };
233
- const handlePresetMenuClose = () => { setPresetMenuAnchorEl(null); setActivePresetMenuId(null); };
234
- const handleRemovePreset = () => { console.log(`Remove: ${activePresetMenuId}`); handlePresetMenuClose(); };
235
- // Preset Modal Handlers
236
- const handleOpenPresetModal = () => { setIsPresetCreated(false); setPresetModalOpen(true); };
237
- const handleClosePresetModal = () => setPresetModalOpen(false);
238
- const handleOpenPresetModalMobile = () => { setIsPresetCreated(false); setPresetModalOpenMobile(true); };
239
- const handleClosePresetModalMobile = () => setPresetModalOpenMobile(false);
240
- const handleNameChange = (event) => setPresetName(event.target.value);
241
- // Watermark Handlers
242
- const handleOpenWatermarkView = () => setIsCreatingWatermark(true);
243
- const handleSaveWatermark = () => setIsCreatingWatermark(false);
244
- const handleCancelWatermark = () => setIsCreatingWatermark(false);
245
- const handleOpenRenameModal = useCallback(() => {
246
- if (!activePresetMenuId)
247
- return;
248
- const preset = presets.find(p => p.id === activePresetMenuId);
249
- if (preset) {
250
- setPresetToRename(preset);
251
- setNewPresetName(preset.name);
252
- setRenameModalOpen(true);
253
- }
254
- handlePresetMenuClose();
255
- }, [activePresetMenuId, presets]);
256
- const handleCloseRenameModal = () => {
257
- setRenameModalOpen(false);
258
- setPresetToRename(null);
259
- setNewPresetName("");
260
- };
261
- // MARK: DEBUG (NEW LOGIC)
262
- // MARK: - Zoom Handlers
263
- const handleZoomAction = useCallback((action) => {
264
- let newZoom = zoomLevel;
265
- const zoomStep = 1.25;
266
- switch (action) {
267
- case 'in':
268
- newZoom *= zoomStep;
269
- break;
270
- case 'out':
271
- newZoom /= zoomStep;
272
- break;
273
- case 'fit':
274
- newZoom = 1;
275
- break;
276
- case '50%':
277
- newZoom = 0.5;
278
- break;
279
- case '100%':
280
- newZoom = 1;
281
- break;
282
- case '200%':
283
- newZoom = 2;
284
- break;
285
- }
286
- setZoomLevel(Math.max(0.1, Math.min(newZoom, 8)));
287
- }, [zoomLevel]);
288
- const handleWheelZoom = useCallback((event) => {
289
- if (!isImageLoaded)
290
- return;
291
- event.preventDefault(); // Prevent page from scrolling
292
- const zoomFactor = 1.1;
293
- let newZoom = zoomLevel;
294
- if (event.deltaY < 0) {
295
- newZoom *= zoomFactor; // Scroll up to zoom in
296
- }
297
- else {
298
- newZoom /= zoomFactor; // Scroll down to zoom out
299
- }
300
- setZoomLevel(Math.max(0.1, Math.min(newZoom, 8)));
301
- }, [zoomLevel, isImageLoaded]);
302
- const zoomLevelText = useMemo(() => {
303
- return `${Math.round(zoomLevel * 100)}%`;
304
- }, [zoomLevel]);
305
- const updateAdjustments = useCallback((newValues) => {
306
- const newState = { ...currentAdjustmentsState, ...newValues };
307
- historyActions.pushState(newState);
308
- }, [currentAdjustmentsState, historyActions]);
309
- const setTempScore = (value) => updateAdjustments({ tempScore: value });
310
- const setTintScore = (value) => updateAdjustments({ tintScore: value });
311
- const setVibranceScore = (value) => updateAdjustments({ vibranceScore: value });
312
- const setSaturationScore = (value) => updateAdjustments({ saturationScore: value });
313
- const setExposureScore = (value) => updateAdjustments({ exposureScore: value });
314
- const setHighlightsScore = (value) => updateAdjustments({ highlightsScore: value });
315
- const setShadowsScore = (value) => updateAdjustments({ shadowsScore: value });
316
- const setWhitesScore = (value) => updateAdjustments({ whitesScore: value });
317
- const setBlacksScore = (value) => updateAdjustments({ blacksScore: value });
318
- const setContrastScore = (value) => updateAdjustments({ contrastScore: value });
319
- const setClarityScore = (value) => updateAdjustments({ clarityScore: value });
320
- const setSharpnessScore = (value) => updateAdjustments({ sharpnessScore: value });
321
- // MARK: Copied ClipBoard
322
- const handleHeaderMenuClick = (event) => setHeaderMenuAnchorEl(event.currentTarget);
323
- const handleHeaderMenuClose = () => setHeaderMenuAnchorEl(null);
324
- const handleAlertClose = () => {
325
- setIsConnectionSlow(false);
326
- };
327
- const handleOpenCopyDialog = () => {
328
- const newColorChecks = {
329
- temperature: currentAdjustmentsState.tempScore !== 0,
330
- tint: currentAdjustmentsState.tintScore !== 0,
331
- vibrance: currentAdjustmentsState.vibranceScore !== 0,
332
- saturation: currentAdjustmentsState.saturationScore !== 0,
333
- };
334
- const newLightChecks = {
335
- exposure: currentAdjustmentsState.exposureScore !== 0,
336
- contrast: currentAdjustmentsState.contrastScore !== 0,
337
- highlights: currentAdjustmentsState.highlightsScore !== 0,
338
- shadows: currentAdjustmentsState.shadowsScore !== 0,
339
- whites: currentAdjustmentsState.whitesScore !== 0,
340
- blacks: currentAdjustmentsState.blacksScore !== 0,
341
- };
342
- const newDetailsChecks = {
343
- clarity: currentAdjustmentsState.clarityScore !== 0,
344
- sharpness: currentAdjustmentsState.sharpnessScore !== 0,
345
- };
346
- setCopyColorChecks(newColorChecks);
347
- setCopyLightChecks(newLightChecks);
348
- setCopyDetailsChecks(newDetailsChecks);
349
- setCopyDialogExpanded({
350
- color: Object.values(newColorChecks).some(isChecked => isChecked),
351
- light: Object.values(newLightChecks).some(isChecked => isChecked),
352
- details: Object.values(newDetailsChecks).some(isChecked => isChecked),
353
- });
354
- setCopyDialogOpen(true);
355
- handleHeaderMenuClose();
356
- };
357
- const handleCopyParentChange = (event, setter) => {
358
- const isChecked = event.target.checked;
359
- setter((prev) => {
360
- const newState = {};
361
- Object.keys(prev).forEach(key => { newState[key] = isChecked; });
362
- return newState;
363
- });
364
- };
365
- const handleCopyChildChange = (event, setter) => {
366
- setter((prev) => ({
367
- ...prev,
368
- [event.target.name]: event.target.checked,
369
- }));
370
- };
371
- const handleToggleCopyDialogExpand = (section) => {
372
- setCopyDialogExpanded(prev => ({ ...prev, [section]: !prev[section] }));
373
- };
374
- const handleCopyEdit = useCallback(() => {
375
- const adjustmentsToCopy = {};
376
- // Color Adjustments
377
- if (copyColorChecks.temperature)
378
- adjustmentsToCopy.tempScore = currentAdjustmentsState.tempScore;
379
- if (copyColorChecks.tint)
380
- adjustmentsToCopy.tintScore = currentAdjustmentsState.tintScore;
381
- if (copyColorChecks.vibrance)
382
- adjustmentsToCopy.vibranceScore = currentAdjustmentsState.vibranceScore;
383
- if (copyColorChecks.saturation)
384
- adjustmentsToCopy.saturationScore = currentAdjustmentsState.saturationScore;
385
- // Light Adjustments
386
- if (copyLightChecks.exposure)
387
- adjustmentsToCopy.exposureScore = currentAdjustmentsState.exposureScore;
388
- if (copyLightChecks.contrast)
389
- adjustmentsToCopy.contrastScore = currentAdjustmentsState.contrastScore;
390
- if (copyLightChecks.highlights)
391
- adjustmentsToCopy.highlightsScore = currentAdjustmentsState.highlightsScore;
392
- if (copyLightChecks.shadows)
393
- adjustmentsToCopy.shadowsScore = currentAdjustmentsState.shadowsScore;
394
- if (copyLightChecks.whites)
395
- adjustmentsToCopy.whitesScore = currentAdjustmentsState.whitesScore;
396
- if (copyLightChecks.blacks)
397
- adjustmentsToCopy.blacksScore = currentAdjustmentsState.blacksScore;
398
- // Details Adjustments
399
- if (copyDetailsChecks.clarity)
400
- adjustmentsToCopy.clarityScore = currentAdjustmentsState.clarityScore;
401
- if (copyDetailsChecks.sharpness)
402
- adjustmentsToCopy.sharpnessScore = currentAdjustmentsState.sharpnessScore;
403
- // Combine with existing copied adjustments to not lose unchecked values from a previous copy
404
- setCopiedAdjustments(prev => ({ ...initialAdjustments, ...prev, ...adjustmentsToCopy }));
405
- console.log("Copied selected adjustments:", adjustmentsToCopy);
406
- }, [copyColorChecks, copyLightChecks, copyDetailsChecks, currentAdjustmentsState]);
407
- const handlePasteEdit = useCallback(() => {
408
- if (!copiedAdjustments)
409
- return;
410
- updateAdjustments(copiedAdjustments);
411
- handleHeaderMenuClose();
412
- }, [copiedAdjustments, updateAdjustments]);
413
- const handleCloseCopyDialog = () => setCopyDialogOpen(false);
414
- const handleConfirmCopy = () => { handleCopyEdit(); handleCloseCopyDialog(); setShowCopyAlert(true); };
415
- // MARK: useEffect HERE!
416
- useEffect(() => {
417
- const timeoutId = setTimeout(() => {
418
- if (contentRef.current) {
419
- const height = contentRef.current.scrollHeight;
420
- setContentHeight(height);
421
- }
422
- }, 50);
423
- return () => clearTimeout(timeoutId);
424
- }, [activePanel, activeSubPanel]);
425
- useEffect(() => {
426
- if (showCopyAlert) {
427
- const timer = setTimeout(() => setShowCopyAlert(false), 2000);
428
- return () => clearTimeout(timer);
429
- }
430
- }, [showCopyAlert]);
431
- useEffect(() => {
432
- const handleOnline = () => setIsOnline(true);
433
- const handleOffline = () => setIsOnline(false);
434
- window.addEventListener('online', handleOnline);
435
- window.addEventListener('offline', handleOffline);
436
- return () => {
437
- window.removeEventListener('online', handleOnline);
438
- window.removeEventListener('offline', handleOffline);
439
- };
440
- }, []);
441
- useEffect(() => {
442
- if (canvasRef.current) {
443
- canvasRef.current.style.transition = 'transform 0.1s ease-out';
444
- canvasRef.current.style.transform = `scale(${zoomLevel})`;
445
- }
446
- }, [zoomLevel]);
447
- useEffect(() => {
448
- // will trigger when currentImageId change
449
- if (!galleryImageData)
450
- return;
451
- console.log("++ USE EFFECT FOR NEXT AND PREV");
452
- const init = async () => {
453
- console.log("1. INIT EDITOR");
454
- if (editorRef.current?.getInitialized() === false) {
455
- await editorRef.current?.initialize();
456
- }
457
- const adjustmentData = galleryImageData.editor_config?.color_adjustment;
458
- console.log("2. ADJUSTMENT DATA: ", { ...adjustmentData }, { ...galleryImageData });
459
- // set event
460
- setEventId(galleryImageData.event_id);
461
- console.log("3. EVENTID: ", eventId);
462
- const pathGallery = extractPathFromGallery(galleryImageData);
463
- // load image to editor
464
- console.log("4. PATH GALLERY: ", pathGallery);
465
- await loadImageEditorFromUrl(pathGallery);
466
- console.log("5. LOAD IMAGE TO EDITOR");
467
- // adjustment setup
468
- if (adjustmentData) {
469
- console.log("7. ADJUSTMENT DATA FOUND");
470
- const adjustmentState = mapColorAdjustmentToAdjustmentState(adjustmentData);
471
- // set adjustment to editor to make adjustmentState change
472
- console.log("8. SYNC HISTORY");
473
- historyActions.syncHistory([adjustmentState]);
474
- }
475
- else {
476
- historyActions.syncHistory([initialAdjustments]);
477
- console.log("no adjustment found, use default");
478
- }
479
- };
480
- init();
481
- }, [galleryImageData, editorRef.current]);
482
- useEffect(() => {
483
- // Render photo if adjustmentState change;
484
- if (!editorRef.current || !isImageLoaded)
485
- return;
486
- console.log("Rendering adjustments to editor...", currentAdjustmentsState);
487
- if ((editorRef.current?.getInitialized() === true) && canvasRef.current) {
488
- editorRef.current.setAdjustments(mapAdjustmentStateToAdjustmentEditor(currentAdjustmentsState));
489
- editorRef.current.processImage();
490
- editorRef.current.renderToCanvas(canvasRef.current);
491
- }
492
- }, [editorRef.current, currentAdjustmentsState, isImageLoaded, canvasRef.current]);
493
- useEffect(() => {
494
- window.addEventListener('keydown', handleKeyDown);
495
- return () => {
496
- window.removeEventListener('keydown', handleKeyDown);
497
- };
498
- }, [handleKeyDown]);
499
- // Effect for drag listeners
500
- useEffect(() => {
501
- if (isDragging) {
502
- window.addEventListener('mousemove', handleDragMove);
503
- window.addEventListener('mouseup', handleDragEnd);
504
- window.addEventListener('touchmove', handleDragMove);
505
- window.addEventListener('touchend', handleDragEnd);
506
- }
507
- return () => {
508
- window.removeEventListener('mousemove', handleDragMove);
509
- window.removeEventListener('mouseup', handleDragEnd);
510
- window.removeEventListener('touchmove', handleDragMove);
511
- window.removeEventListener('touchend', handleDragEnd);
512
- };
513
- }, [isDragging, handleDragMove, handleDragEnd]);
514
- useEffect(() => {
515
- // Cast navigator to our custom type to access the connection property safely
516
- const navigatorWithConnection = navigator;
517
- if (!navigatorWithConnection.connection)
518
- return;
519
- const navigatorConnection = navigatorWithConnection.connection;
520
- const updateConnectionStatus = () => {
521
- const slowConnectionTypes = ['slow-2g', '2g', '3g'];
522
- const isSlow = navigatorConnection.saveData || slowConnectionTypes.includes(navigatorConnection.effectiveType);
523
- setIsConnectionSlow(isSlow);
524
- };
525
- // Check status immediately
526
- updateConnectionStatus();
527
- // Add event listener for changes
528
- navigatorConnection.addEventListener('change', updateConnectionStatus);
529
- // Cleanup on unmount
530
- return () => {
531
- navigatorConnection.removeEventListener('change', updateConnectionStatus);
532
- };
533
- }, []);
534
- return {
535
- // Refs
536
- canvasRef,
537
- canvasContainerRef,
538
- fileInputRef,
539
- handleShowOriginal,
540
- handleShowEdited,
541
- // Status & State
542
- editorStatus,
543
- isEditorReady,
544
- isImageLoaded: isImageLoaded && !isGalleryLoading, // Combine loading states
545
- onSwipeNext,
546
- onSwipePrev,
547
- isNextAvailable,
548
- isPrevAvailable,
549
- isGalleryLoading,
550
- galleryError,
551
- galleryImageData,
552
- historyActions,
553
- handleBackCallback,
554
- currentAdjustmentsState,
555
- setTempScore,
556
- setTintScore,
557
- setVibranceScore,
558
- setSaturationScore,
559
- setExposureScore,
560
- setHighlightsScore,
561
- setShadowsScore,
562
- setWhitesScore,
563
- setBlacksScore,
564
- setContrastScore,
565
- setClarityScore,
566
- setSharpnessScore,
567
- // History functions and state
568
- handleUndo: historyActions.undo,
569
- handleRedo: historyActions.redo,
570
- handleRevert: () => historyActions.reset(initialAdjustments),
571
- canUndo: historyInfo.canUndo,
572
- canRedo: historyInfo.canRedo,
573
- // Refs for mobile panel
574
- panelRef,
575
- contentRef,
576
- // State for mobile panel
577
- panelHeight,
578
- // Handlers for mobile panel
579
- handleDragStart,
580
- handleContentHeightChange,
581
- // Status & State
582
- isPasteAvailable: copiedAdjustments !== null,
583
- isOnline,
584
- isConnectionSlow,
585
- showCopyAlert,
586
- isCopyDialogOpen,
587
- activePanel,
588
- activeSubPanel,
589
- headerMenuAnchorEl,
590
- anchorMenuZoom,
591
- colorAdjustmentExpandedPanels,
592
- presetExpandedPanels,
593
- isCreatingWatermark,
594
- isPresetModalOpen,
595
- isPresetModalOpenMobile,
596
- presetName,
597
- isPresetCreated,
598
- selectedMobilePreset,
599
- selectedDesktopPreset,
600
- presetMenuAnchorEl,
601
- activePresetMenuId,
602
- colorAdjustments,
603
- lightAdjustments,
604
- detailsAdjustments,
605
- handleWheelZoom,
606
- handleZoomAction,
607
- zoomLevelText,
608
- presets,
609
- // Functions
610
- handleScriptReady,
611
- handleAlertClose,
612
- handleOpenCopyDialog,
613
- handleCloseCopyDialog,
614
- copyColorChecks,
615
- setCopyColorChecks,
616
- copyLightChecks,
617
- setCopyLightChecks,
618
- copyDetailsChecks,
619
- setCopyDetailsChecks,
620
- copyDialogExpanded,
621
- handleCopyParentChange,
622
- handleCopyChildChange,
623
- handleToggleCopyDialogExpand,
624
- handleConfirmCopy,
625
- handleCopyEdit,
626
- handlePasteEdit,
627
- // adjustClarityBulk,
628
- // adjustSharpnessBulk,
629
- // Setters & Handlers
630
- setActivePanel,
631
- setActiveSubPanel,
632
- setHeaderMenuAnchorEl,
633
- setAnchorMenuZoom,
634
- handleHeaderMenuClick,
635
- handleHeaderMenuClose,
636
- setColorAdjustments,
637
- setLightAdjustments,
638
- setDetailsAdjustments,
639
- handleColorAccordionChange,
640
- handlePresetAccordionChange,
641
- handleSelectMobilePreset,
642
- handleSelectDesktopPreset,
643
- handlePresetMenuClick,
644
- handlePresetMenuClose,
645
- handleRemovePreset,
646
- handleOpenPresetModal,
647
- handleClosePresetModal,
648
- handleOpenPresetModalMobile,
649
- handleClosePresetModalMobile,
650
- setPresetName,
651
- handleNameChange,
652
- isRenameModalOpen,
653
- presetToRename,
654
- newPresetName,
655
- setNewPresetName,
656
- handleOpenRenameModal,
657
- handleCloseRenameModal,
658
- handleOpenWatermarkView,
659
- handleSaveWatermark,
660
- handleCancelWatermark,
661
- // Bulk Adjustment Handlers
662
- // Note: These handlers are for image list
663
- // Note: These handlers are for bulk adjustments
664
- // Adjustment Colors
665
- // handleBulkTempDecreaseMax,
666
- // handleBulkTempDecrease,
667
- // handleBulkTempIncrease,
668
- // handleBulkTempIncreaseMax,
669
- // handleBulkTintDecreaseMax,
670
- // handleBulkTintDecrease,
671
- // handleBulkTintIncrease,
672
- // handleBulkTintIncreaseMax,
673
- // handleBulkVibranceDecreaseMax,
674
- // handleBulkVibranceDecrease,
675
- // handleBulkVibranceIncrease,
676
- // handleBulkVibranceIncreaseMax,
677
- // handleBulkSaturationDecreaseMax,
678
- // handleBulkSaturationDecrease,
679
- // handleBulkSaturationIncrease,
680
- // handleBulkSaturationIncreaseMax,
681
- // // Adjustment Light
682
- // handleBulkExposureDecreaseMax,
683
- // handleBulkExposureDecrease,
684
- // handleBulkExposureIncrease,
685
- // handleBulkExposureIncreaseMax,
686
- // handleBulkContrastDecreaseMax,
687
- // handleBulkContrastDecrease,
688
- // handleBulkContrastIncrease,
689
- // handleBulkContrastIncreaseMax,
690
- // handleBulkHighlightsDecreaseMax,
691
- // handleBulkHighlightsDecrease,
692
- // handleBulkHighlightsIncrease,
693
- // handleBulkHighlightsIncreaseMax,
694
- // handleBulkShadowsDecreaseMax,
695
- // handleBulkShadowsDecrease,
696
- // handleBulkShadowsIncrease,
697
- // handleBulkShadowsIncreaseMax,
698
- // handleBulkWhitesDecreaseMax,
699
- // handleBulkWhitesDecrease,
700
- // handleBulkWhitesIncrease,
701
- // handleBulkWhitesIncreaseMax,
702
- // handleBulkBlacksDecreaseMax,
703
- // handleBulkBlacksDecrease,
704
- // handleBulkBlacksIncrease,
705
- // handleBulkBlacksIncreaseMax,
706
- // // Adjustment Details
707
- // handleBulkClarityDecreaseMax,
708
- // handleBulkClarityDecrease,
709
- // handleBulkClarityIncrease,
710
- // handleBulkClarityIncreaseMax,
711
- // handleBulkSharpnessDecreaseMax,
712
- // handleBulkSharpnessDecrease,
713
- // handleBulkSharpnessIncrease,
714
- // handleBulkSharpnessIncreaseMax,
715
- };
716
- }