@yogiswara/honcho-editor-ui 2.5.9 → 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.
- package/dist/components/editor/HBulkPreset.js +12 -2
- package/dist/hooks/demo/HonchoEditorBulkDemo.d.ts +3 -0
- package/dist/hooks/demo/HonchoEditorBulkDemo.js +228 -0
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.d.ts +3 -0
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.js +354 -0
- package/dist/hooks/demo/index.d.ts +2 -0
- package/dist/hooks/demo/index.js +2 -0
- package/dist/hooks/editor/type.d.ts +71 -0
- package/dist/hooks/editor/useHonchoEditorBulk.d.ts +12 -12
- package/dist/hooks/editor/useHonchoEditorBulk.js +155 -42
- package/dist/hooks/editor/useHonchoEditorSingle.d.ts +43 -0
- package/dist/hooks/editor/useHonchoEditorSingle.js +158 -0
- package/dist/hooks/useAdjustmentHistory.d.ts +9 -5
- package/dist/hooks/useAdjustmentHistory.js +187 -31
- package/dist/hooks/useAdjustmentHistoryBatch.d.ts +18 -1
- package/dist/hooks/useAdjustmentHistoryBatch.js +627 -201
- package/dist/hooks/useGallerySwipe.d.ts +1 -1
- package/dist/hooks/usePaging.d.ts +89 -0
- package/dist/hooks/usePaging.js +211 -0
- package/dist/hooks/usePreset.d.ts +1 -1
- package/dist/hooks/usePreset.js +35 -35
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -1
- package/dist/lib/context/EditorContext.d.ts +10 -0
- package/dist/lib/context/EditorContext.js +4 -2
- package/dist/lib/hooks/useEditorHeadless.d.ts +18 -2
- package/dist/lib/hooks/useEditorHeadless.js +142 -63
- package/dist/utils/adjustment.d.ts +2 -1
- package/dist/utils/adjustment.js +16 -0
- package/dist/utils/imageLoader.d.ts +11 -0
- package/dist/utils/imageLoader.js +53 -0
- package/package.json +1 -1
- package/dist/components/editor/GalleryAlbum/SimplifiedAlbumGallery.d.ts +0 -17
- package/dist/components/editor/GalleryAlbum/SimplifiedAlbumGallery.js +0 -14
- package/dist/components/editor/GalleryAlbum/SimplifiedImageItem.d.ts +0 -8
- package/dist/components/editor/GalleryAlbum/SimplifiedImageItem.js +0 -30
- package/dist/components/editor/HImageEditorPage.d.ts +0 -1
- package/dist/components/editor/HImageEditorPage.js +0 -187
- package/dist/hooks/__tests__/useGallerySwipe.test.d.ts +0 -0
- package/dist/hooks/__tests__/useGallerySwipe.test.js +0 -619
- package/dist/hooks/editor/useHonchoEditor.d.ts +0 -203
- package/dist/hooks/editor/useHonchoEditor.js +0 -716
- package/dist/hooks/useAdjustmentHistory.demo.d.ts +0 -8
- package/dist/hooks/useAdjustmentHistory.demo.js +0 -106
- package/dist/hooks/useAdjustmentHistory.example.d.ts +0 -38
- package/dist/hooks/useAdjustmentHistory.example.js +0 -182
- package/dist/hooks/useAdjustmentHistory.syncDemo.d.ts +0 -8
- package/dist/hooks/useAdjustmentHistory.syncDemo.js +0 -180
- package/dist/hooks/useGallerySwipe.example.d.ts +0 -24
- package/dist/hooks/useGallerySwipe.example.js +0 -184
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { useState, useCallback, useEffect, useMemo } from 'react';
|
|
2
|
+
import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
3
3
|
import { useAdjustmentHistoryBatch } from '../useAdjustmentHistoryBatch';
|
|
4
|
+
import { usePaging } from "../usePaging";
|
|
5
|
+
import { usePreset } from "../usePreset";
|
|
4
6
|
// Helper function to map the API response to the format our UI component needs
|
|
5
7
|
const mapGalleryToPhotoData = (gallery, selectedIds) => {
|
|
6
8
|
return {
|
|
@@ -38,36 +40,152 @@ function mapColorAdjustmentToAdjustmentState(adj) {
|
|
|
38
40
|
sharpnessScore: adj.sharpness || 0,
|
|
39
41
|
};
|
|
40
42
|
}
|
|
43
|
+
// Helper function to convert Preset to AdjustmentState
|
|
44
|
+
const presetToAdjustmentState = (preset) => {
|
|
45
|
+
return {
|
|
46
|
+
tempScore: preset.temperature || 0,
|
|
47
|
+
tintScore: preset.tint || 0,
|
|
48
|
+
vibranceScore: preset.vibrance || 0,
|
|
49
|
+
saturationScore: preset.saturation || 0,
|
|
50
|
+
exposureScore: preset.exposure || 0,
|
|
51
|
+
highlightsScore: preset.highlights || 0,
|
|
52
|
+
shadowsScore: preset.shadows || 0,
|
|
53
|
+
whitesScore: preset.whites || 0,
|
|
54
|
+
blacksScore: preset.blacks || 0,
|
|
55
|
+
contrastScore: preset.contrast || 0,
|
|
56
|
+
clarityScore: preset.clarity || 0,
|
|
57
|
+
sharpnessScore: preset.sharpness || 0,
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
// Helper function to compare adjustment states
|
|
61
|
+
const adjustmentsMatch = (a, b) => {
|
|
62
|
+
const keys = [
|
|
63
|
+
'tempScore', 'tintScore', 'vibranceScore', 'saturationScore',
|
|
64
|
+
'exposureScore', 'highlightsScore', 'shadowsScore', 'whitesScore',
|
|
65
|
+
'blacksScore', 'contrastScore', 'clarityScore', 'sharpnessScore'
|
|
66
|
+
];
|
|
67
|
+
return keys.every(key => (a[key] || 0) === (b[key] || 0));
|
|
68
|
+
};
|
|
41
69
|
export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
42
|
-
const { currentBatch, selectedIds, actions: batchActions } = useAdjustmentHistoryBatch(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
const { currentBatch, selectedIds, actions: batchActions, historyInfo } = useAdjustmentHistoryBatch({
|
|
71
|
+
controller,
|
|
72
|
+
firebaseUid,
|
|
73
|
+
eventId: eventID,
|
|
74
|
+
devWarnings: true
|
|
75
|
+
});
|
|
76
|
+
const { images, info, actions } = usePaging(controller, firebaseUid, eventID, {
|
|
77
|
+
autoLoad: true,
|
|
78
|
+
autoReset: false // Prevent auto-reset to avoid loops
|
|
79
|
+
});
|
|
80
|
+
// Preset management
|
|
81
|
+
const { presets, actions: presetActions } = usePreset(controller, firebaseUid, {
|
|
82
|
+
autoLoad: true,
|
|
83
|
+
devWarnings: true
|
|
84
|
+
});
|
|
85
|
+
// Track which images have been synced to prevent loops
|
|
86
|
+
const lastSyncedImageIds = useRef(new Set());
|
|
87
|
+
// State for Bulk Editing
|
|
88
|
+
const [selectedBulkPreset, setSelectedBulkPreset] = useState('');
|
|
89
|
+
// Calculate active preset based on selected images' adjustments
|
|
90
|
+
const activePreset = useMemo(() => {
|
|
91
|
+
if (selectedIds.length === 0) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
// Get adjustments for all selected images
|
|
95
|
+
const selectedAdjustments = selectedIds.map(imageId => {
|
|
96
|
+
return currentBatch.allImages[imageId] || {
|
|
97
|
+
tempScore: 0, tintScore: 0, vibranceScore: 0, saturationScore: 0,
|
|
98
|
+
exposureScore: 0, highlightsScore: 0, shadowsScore: 0, whitesScore: 0,
|
|
99
|
+
blacksScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
// Check if all selected images have the same adjustments
|
|
103
|
+
const firstAdjustment = selectedAdjustments[0];
|
|
104
|
+
const allSameAdjustments = selectedAdjustments.every(adj => adjustmentsMatch(adj, firstAdjustment));
|
|
105
|
+
if (!allSameAdjustments) {
|
|
106
|
+
// Selected images have different adjustments
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
// Find preset that matches the common adjustment state
|
|
110
|
+
const matchingPreset = presets.find(preset => {
|
|
111
|
+
const presetAdjustments = presetToAdjustmentState(preset);
|
|
112
|
+
return adjustmentsMatch(presetAdjustments, firstAdjustment);
|
|
113
|
+
});
|
|
114
|
+
return matchingPreset || null;
|
|
115
|
+
}, [selectedIds, currentBatch.allImages, presets]);
|
|
116
|
+
// Update selectedBulkPreset when activePreset changes
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
setSelectedBulkPreset(activePreset?.id || '');
|
|
119
|
+
}, [activePreset]);
|
|
120
|
+
// Use loading states from usePaging instead of local state
|
|
121
|
+
const isLoading = info.isLoading;
|
|
122
|
+
const error = info.error;
|
|
123
|
+
const hasMore = info.hasMore;
|
|
51
124
|
const imageData = useMemo(() => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
console.log("adjustment FROM USEHONCHOBULK: ", adjustment);
|
|
58
|
-
return adjustment ? { ...item, ...adjustment } : item;
|
|
125
|
+
console.debug("imageData recalculating with:", {
|
|
126
|
+
imagesLength: images.length,
|
|
127
|
+
selectedIds,
|
|
128
|
+
currentBatch_allImages: currentBatch.allImages,
|
|
129
|
+
currentBatch_allImages_keys: Object.keys(currentBatch.allImages)
|
|
59
130
|
});
|
|
60
|
-
|
|
131
|
+
const res = images.map(item => {
|
|
132
|
+
const basePhoto = mapGalleryToPhotoData(item, selectedIds);
|
|
133
|
+
const batchAdjustment = currentBatch.allImages[item.id];
|
|
134
|
+
console.debug(`Processing image ${item.id}:`, {
|
|
135
|
+
basePhoto,
|
|
136
|
+
batchAdjustment,
|
|
137
|
+
hasBatchAdjustment: !!batchAdjustment
|
|
138
|
+
});
|
|
139
|
+
// Merge batch adjustments over backend adjustments
|
|
140
|
+
return batchAdjustment ? { ...basePhoto, ...batchAdjustment } : basePhoto;
|
|
141
|
+
});
|
|
142
|
+
console.debug("imageData result:", res);
|
|
143
|
+
return res;
|
|
144
|
+
}, [images, selectedIds, currentBatch.allImages]);
|
|
145
|
+
// Store the latest batchActions.syncAdjustment in a ref to avoid dependency issues
|
|
146
|
+
const syncAdjustmentRef = useRef(batchActions.syncAdjustment);
|
|
147
|
+
syncAdjustmentRef.current = batchActions.syncAdjustment;
|
|
148
|
+
// Safe sync: Only sync new images to prevent infinite loops
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
if (images.length === 0)
|
|
151
|
+
return;
|
|
152
|
+
// Check if we have new images that haven't been synced
|
|
153
|
+
const currentImageIds = new Set(images.map(img => img.id));
|
|
154
|
+
const hasNewImages = images.some(img => !lastSyncedImageIds.current.has(img.id));
|
|
155
|
+
if (hasNewImages) {
|
|
156
|
+
console.log('[useHonchoEditorBulk] Syncing new images to batch:', images.length);
|
|
157
|
+
syncAdjustmentRef.current(images.map(mapToImageAdjustmentConfig));
|
|
158
|
+
lastSyncedImageIds.current = currentImageIds;
|
|
159
|
+
}
|
|
160
|
+
}, [images]); // Only depend on images, not batchActions
|
|
61
161
|
const handleBackCallbackBulk = useCallback(() => {
|
|
62
162
|
const lastSelectedId = selectedIds.length > 0 ? selectedIds[selectedIds.length - 1] : "";
|
|
63
163
|
controller.handleBack(firebaseUid, lastSelectedId);
|
|
64
164
|
}, [controller, firebaseUid, selectedIds]);
|
|
65
|
-
const handleSelectBulkPreset = (event) =>
|
|
165
|
+
const handleSelectBulkPreset = useCallback((event) => {
|
|
166
|
+
const presetId = event.target.value;
|
|
167
|
+
setSelectedBulkPreset(presetId);
|
|
168
|
+
if (presetId && selectedIds.length > 0) {
|
|
169
|
+
// Find the preset
|
|
170
|
+
const preset = presets.find(p => p.id === presetId);
|
|
171
|
+
if (preset) {
|
|
172
|
+
// Convert preset to adjustment state
|
|
173
|
+
const presetAdjustments = presetToAdjustmentState(preset);
|
|
174
|
+
// Apply preset directly to all selected images using the clean action
|
|
175
|
+
batchActions.adjustSelectedWithPreset(presetAdjustments);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}, [presets, selectedIds, batchActions]);
|
|
66
179
|
// This factory creates functions that adjust a value for all selected images
|
|
67
180
|
const createRelativeAdjuster = useCallback((key, amount) => () => {
|
|
68
|
-
console.debug("createRelativeAdjuster", key, amount);
|
|
181
|
+
console.debug("createRelativeAdjuster called:", { key, amount, selectedIds });
|
|
182
|
+
console.debug("currentBatch.allImages before:", currentBatch.allImages);
|
|
69
183
|
batchActions.adjustSelected({ [key]: amount });
|
|
70
|
-
|
|
184
|
+
// Debug after a short delay to see if the state changed
|
|
185
|
+
setTimeout(() => {
|
|
186
|
+
console.debug("currentBatch.allImages after:", currentBatch.allImages);
|
|
187
|
+
}, 100);
|
|
188
|
+
}, [batchActions, selectedIds, currentBatch.allImages]);
|
|
71
189
|
const handleBulkTempDecreaseMax = createRelativeAdjuster('tempScore', -20);
|
|
72
190
|
const handleBulkTempDecrease = createRelativeAdjuster('tempScore', -5);
|
|
73
191
|
const handleBulkTempIncrease = createRelativeAdjuster('tempScore', 5);
|
|
@@ -148,26 +266,8 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
148
266
|
// loadImages(page + 1);
|
|
149
267
|
// }
|
|
150
268
|
// }, [isFetchingMore, hasMore, page, loadImages]);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
setIsLoading(true);
|
|
154
|
-
setError(null);
|
|
155
|
-
controller.getImageList(firebaseUid, eventID, 2)
|
|
156
|
-
.then(response => {
|
|
157
|
-
// TODO need do pagination for this one
|
|
158
|
-
batchActions.syncAdjustment(response.gallery.map(mapToImageAdjustmentConfig));
|
|
159
|
-
setImageCollection(response.gallery);
|
|
160
|
-
})
|
|
161
|
-
.catch(err => {
|
|
162
|
-
console.error("Failed to fetch image list:", err);
|
|
163
|
-
setError("Could not load images.");
|
|
164
|
-
})
|
|
165
|
-
.finally(() => {
|
|
166
|
-
setIsLoading(false);
|
|
167
|
-
});
|
|
168
|
-
console.log("Image data FROM USEHONCHOBULK: ", imageData);
|
|
169
|
-
}
|
|
170
|
-
}, [eventID, firebaseUid, controller]);
|
|
269
|
+
// Note: Image loading is now handled by usePaging hook
|
|
270
|
+
// The sync logic above handles syncing loaded images to batch state
|
|
171
271
|
// useEffect(() => {
|
|
172
272
|
// if (eventID && firebaseUid) {
|
|
173
273
|
// setImageCollection([]); // reset when event changes
|
|
@@ -184,9 +284,17 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
184
284
|
// loadMoreImages,
|
|
185
285
|
// Gallery Handlers
|
|
186
286
|
handleBackCallbackBulk,
|
|
287
|
+
// Preset functionality
|
|
288
|
+
presets,
|
|
187
289
|
selectedBulkPreset,
|
|
188
|
-
|
|
290
|
+
activePreset,
|
|
189
291
|
handleSelectBulkPreset,
|
|
292
|
+
// Preset creation handlers
|
|
293
|
+
handleOpenPresetModal: () => { }, // TODO: Implement preset modal for bulk editing
|
|
294
|
+
presetActions, // Expose preset actions for create/rename/delete
|
|
295
|
+
handleToggleImageSelection: batchActions.toggleSelection,
|
|
296
|
+
handleLoadMore: actions.loadMore,
|
|
297
|
+
handleRefresh: actions.refresh,
|
|
190
298
|
// Adjustment
|
|
191
299
|
handleBulkTempDecreaseMax,
|
|
192
300
|
handleBulkTempDecrease,
|
|
@@ -238,5 +346,10 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
238
346
|
handleBulkSharpnessDecrease,
|
|
239
347
|
handleBulkSharpnessIncrease,
|
|
240
348
|
handleBulkSharpnessIncreaseMax,
|
|
349
|
+
// History actions
|
|
350
|
+
handleUndo: batchActions.undo,
|
|
351
|
+
handleRedo: batchActions.redo,
|
|
352
|
+
handleReset: batchActions.reset,
|
|
353
|
+
historyInfo,
|
|
241
354
|
};
|
|
242
355
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Controller, AdjustmentState, Preset } from './type';
|
|
2
|
+
import { Gallery } from './type';
|
|
3
|
+
import { AdjustmentValues } from '../../lib/editor/honcho-editor';
|
|
4
|
+
export interface UseHonchoEditorSingleOptions {
|
|
5
|
+
controller: Controller;
|
|
6
|
+
initImageId: string;
|
|
7
|
+
firebaseUid: string;
|
|
8
|
+
}
|
|
9
|
+
export interface UseHonchoEditorSingleState {
|
|
10
|
+
currentImageData: Gallery | null;
|
|
11
|
+
isGalleryLoading: boolean;
|
|
12
|
+
galleryError: string | null;
|
|
13
|
+
currentAdjustments: AdjustmentState;
|
|
14
|
+
isBatchMode: boolean;
|
|
15
|
+
canUndo: boolean;
|
|
16
|
+
canRedo: boolean;
|
|
17
|
+
isNextAvailable: boolean;
|
|
18
|
+
isPrevAvailable: boolean;
|
|
19
|
+
presets: Preset[];
|
|
20
|
+
activePreset: Preset | null;
|
|
21
|
+
presetsLoading: boolean;
|
|
22
|
+
presetsError: string | null;
|
|
23
|
+
}
|
|
24
|
+
export interface UseHonchoEditorSingleActions {
|
|
25
|
+
navigateNext: () => void;
|
|
26
|
+
navigatePrev: () => void;
|
|
27
|
+
updateAdjustment: (field: keyof AdjustmentState, value: number) => void;
|
|
28
|
+
setBatchMode: (enabled: boolean) => void;
|
|
29
|
+
startBatchMode: () => void;
|
|
30
|
+
endBatchMode: () => void;
|
|
31
|
+
undo: () => void;
|
|
32
|
+
redo: () => void;
|
|
33
|
+
reset: () => void;
|
|
34
|
+
loadPresets: () => Promise<void>;
|
|
35
|
+
applyPreset: (preset: Preset) => void;
|
|
36
|
+
createPreset: (name: string) => Promise<Preset | null>;
|
|
37
|
+
deletePreset: (presetId: string) => Promise<void>;
|
|
38
|
+
getEditorAdjustments: () => AdjustmentValues;
|
|
39
|
+
}
|
|
40
|
+
export declare function useHonchoEditorSingle({ controller, initImageId, firebaseUid }: UseHonchoEditorSingleOptions): {
|
|
41
|
+
state: UseHonchoEditorSingleState;
|
|
42
|
+
actions: UseHonchoEditorSingleActions;
|
|
43
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useCallback, useMemo } from 'react';
|
|
3
|
+
import { useAdjustmentHistory } from '../useAdjustmentHistory';
|
|
4
|
+
import { useGallerySwipe } from '../useGallerySwipe';
|
|
5
|
+
import { usePreset } from '../usePreset';
|
|
6
|
+
// Default adjustment values
|
|
7
|
+
const initialAdjustments = {
|
|
8
|
+
tempScore: 0, tintScore: 0, vibranceScore: 0, saturationScore: 0,
|
|
9
|
+
exposureScore: 0, highlightsScore: 0, shadowsScore: 0, whitesScore: 0,
|
|
10
|
+
blacksScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
|
|
11
|
+
};
|
|
12
|
+
export function useHonchoEditorSingle({ controller, initImageId, firebaseUid }) {
|
|
13
|
+
// Memoize parameters to prevent unnecessary re-renders
|
|
14
|
+
const memoizedController = useMemo(() => controller, [controller]);
|
|
15
|
+
const memoizedInitImageId = useMemo(() => initImageId, [initImageId]);
|
|
16
|
+
const memoizedFirebaseUid = useMemo(() => firebaseUid, [firebaseUid]);
|
|
17
|
+
// Initialize business logic hooks only
|
|
18
|
+
const adjustmentHistory = useAdjustmentHistory(initialAdjustments, memoizedController, memoizedFirebaseUid, memoizedInitImageId);
|
|
19
|
+
const gallerySwipe = useGallerySwipe(memoizedFirebaseUid, memoizedInitImageId, memoizedController);
|
|
20
|
+
const presetHook = usePreset(memoizedController, memoizedFirebaseUid, { autoLoad: true });
|
|
21
|
+
// Find active preset based on current adjustments
|
|
22
|
+
const activePreset = presetHook.actions.findByAdjustments(adjustmentHistory.currentState);
|
|
23
|
+
// Actions - pure business logic, no editor interaction - wrapped in useCallback to prevent re-renders
|
|
24
|
+
const navigateNext = useCallback(() => {
|
|
25
|
+
if (gallerySwipe.isNextAvailable) {
|
|
26
|
+
gallerySwipe.onSwipeNext();
|
|
27
|
+
}
|
|
28
|
+
}, [gallerySwipe.isNextAvailable, gallerySwipe.onSwipeNext]);
|
|
29
|
+
const navigatePrev = useCallback(() => {
|
|
30
|
+
if (gallerySwipe.isPrevAvailable) {
|
|
31
|
+
gallerySwipe.onSwipePrev();
|
|
32
|
+
}
|
|
33
|
+
}, [gallerySwipe.isPrevAvailable, gallerySwipe.onSwipePrev]);
|
|
34
|
+
const updateAdjustment = useCallback((field, value) => {
|
|
35
|
+
const newState = {
|
|
36
|
+
...adjustmentHistory.currentState,
|
|
37
|
+
[field]: value
|
|
38
|
+
};
|
|
39
|
+
adjustmentHistory.actions.pushState(newState);
|
|
40
|
+
}, [adjustmentHistory.currentState, adjustmentHistory.actions.pushState]);
|
|
41
|
+
const setBatchMode = useCallback((enabled) => {
|
|
42
|
+
adjustmentHistory.config.setBatchMode(enabled);
|
|
43
|
+
}, [adjustmentHistory.config.setBatchMode]);
|
|
44
|
+
const startBatchMode = useCallback(() => {
|
|
45
|
+
adjustmentHistory.config.setBatchMode(true);
|
|
46
|
+
}, [adjustmentHistory.config.setBatchMode]);
|
|
47
|
+
const endBatchMode = useCallback(() => {
|
|
48
|
+
adjustmentHistory.config.setBatchMode(false);
|
|
49
|
+
}, [adjustmentHistory.config.setBatchMode]);
|
|
50
|
+
const undo = useCallback(() => {
|
|
51
|
+
adjustmentHistory.actions.undo();
|
|
52
|
+
}, [adjustmentHistory.actions.undo]);
|
|
53
|
+
const redo = useCallback(() => {
|
|
54
|
+
adjustmentHistory.actions.redo();
|
|
55
|
+
}, [adjustmentHistory.actions.redo]);
|
|
56
|
+
const reset = useCallback(async () => {
|
|
57
|
+
// Reset means setting all adjustments to 0 and adding it as new history entry
|
|
58
|
+
// This allows users to undo the reset operation
|
|
59
|
+
// Reset acts like normal adjustment - each reset creates a new history entry
|
|
60
|
+
console.log('Resetting adjustments to 0 - adding to history and sending to backend');
|
|
61
|
+
// First add reset to history (this creates local history entry)
|
|
62
|
+
adjustmentHistory.actions.pushState(initialAdjustments);
|
|
63
|
+
// Then sync to backend
|
|
64
|
+
await adjustmentHistory.config.syncToBackend();
|
|
65
|
+
}, [adjustmentHistory.actions.pushState, adjustmentHistory.config.syncToBackend]);
|
|
66
|
+
const loadPresets = useCallback(async () => {
|
|
67
|
+
await presetHook.actions.load();
|
|
68
|
+
}, [presetHook.actions.load]);
|
|
69
|
+
const applyPreset = useCallback(async (preset) => {
|
|
70
|
+
console.log('Applying preset:', preset.name, '- saving to backend history');
|
|
71
|
+
const adjustmentState = {
|
|
72
|
+
tempScore: preset.temperature,
|
|
73
|
+
tintScore: preset.tint,
|
|
74
|
+
vibranceScore: preset.vibrance,
|
|
75
|
+
saturationScore: preset.saturation,
|
|
76
|
+
exposureScore: preset.exposure,
|
|
77
|
+
highlightsScore: preset.highlights,
|
|
78
|
+
shadowsScore: preset.shadows,
|
|
79
|
+
whitesScore: preset.whites,
|
|
80
|
+
blacksScore: preset.blacks,
|
|
81
|
+
contrastScore: preset.contrast,
|
|
82
|
+
clarityScore: preset.clarity,
|
|
83
|
+
sharpnessScore: preset.sharpness,
|
|
84
|
+
};
|
|
85
|
+
// Apply preset directly and add to history
|
|
86
|
+
adjustmentHistory.actions.pushState(adjustmentState);
|
|
87
|
+
// Then sync to backend
|
|
88
|
+
await adjustmentHistory.config.syncToBackend();
|
|
89
|
+
}, [adjustmentHistory.actions.pushState, adjustmentHistory.config.syncToBackend]);
|
|
90
|
+
const createPreset = useCallback(async (name) => {
|
|
91
|
+
return await presetHook.actions.create(name, adjustmentHistory.currentState);
|
|
92
|
+
}, [presetHook.actions.create, adjustmentHistory.currentState]);
|
|
93
|
+
const deletePreset = useCallback(async (presetId) => {
|
|
94
|
+
await presetHook.actions.delete(presetId);
|
|
95
|
+
}, [presetHook.actions.delete]);
|
|
96
|
+
const getEditorAdjustments = useCallback(() => {
|
|
97
|
+
const adjustments = adjustmentHistory.currentState;
|
|
98
|
+
return {
|
|
99
|
+
temperature: adjustments.tempScore,
|
|
100
|
+
tint: adjustments.tintScore,
|
|
101
|
+
vibrance: adjustments.vibranceScore / 100,
|
|
102
|
+
saturation: adjustments.saturationScore / 100,
|
|
103
|
+
exposure: (adjustments.exposureScore / 100) * 3,
|
|
104
|
+
highlights: adjustments.highlightsScore / 100,
|
|
105
|
+
shadows: adjustments.shadowsScore / 100,
|
|
106
|
+
whites: adjustments.whitesScore / 100,
|
|
107
|
+
blacks: adjustments.blacksScore / 100,
|
|
108
|
+
contrast: adjustments.contrastScore / 100,
|
|
109
|
+
clarity: adjustments.clarityScore / 100,
|
|
110
|
+
sharpness: adjustments.sharpnessScore / 100,
|
|
111
|
+
};
|
|
112
|
+
}, [adjustmentHistory.currentState]);
|
|
113
|
+
const actions = {
|
|
114
|
+
// Navigation
|
|
115
|
+
navigateNext,
|
|
116
|
+
navigatePrev,
|
|
117
|
+
// Adjustments
|
|
118
|
+
updateAdjustment,
|
|
119
|
+
setBatchMode,
|
|
120
|
+
startBatchMode,
|
|
121
|
+
endBatchMode,
|
|
122
|
+
// History
|
|
123
|
+
undo,
|
|
124
|
+
redo,
|
|
125
|
+
reset,
|
|
126
|
+
// Presets
|
|
127
|
+
loadPresets,
|
|
128
|
+
applyPreset,
|
|
129
|
+
createPreset,
|
|
130
|
+
deletePreset,
|
|
131
|
+
// Adjustment conversion for editor
|
|
132
|
+
getEditorAdjustments
|
|
133
|
+
};
|
|
134
|
+
// State - pure business state, no editor state
|
|
135
|
+
const state = {
|
|
136
|
+
// Image state
|
|
137
|
+
currentImageData: gallerySwipe.currentImageData,
|
|
138
|
+
isGalleryLoading: gallerySwipe.isLoading,
|
|
139
|
+
galleryError: gallerySwipe.error,
|
|
140
|
+
// Adjustment state
|
|
141
|
+
currentAdjustments: adjustmentHistory.currentState,
|
|
142
|
+
isBatchMode: adjustmentHistory.historyInfo.isBatchMode,
|
|
143
|
+
canUndo: adjustmentHistory.historyInfo.canUndo,
|
|
144
|
+
canRedo: adjustmentHistory.historyInfo.canRedo,
|
|
145
|
+
// Navigation state
|
|
146
|
+
isNextAvailable: gallerySwipe.isNextAvailable,
|
|
147
|
+
isPrevAvailable: gallerySwipe.isPrevAvailable,
|
|
148
|
+
// Preset state
|
|
149
|
+
presets: presetHook.presets,
|
|
150
|
+
activePreset: activePreset || null,
|
|
151
|
+
presetsLoading: presetHook.info.isLoading,
|
|
152
|
+
presetsError: presetHook.info.error,
|
|
153
|
+
};
|
|
154
|
+
return {
|
|
155
|
+
state,
|
|
156
|
+
actions
|
|
157
|
+
};
|
|
158
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AdjustmentState } from './editor/
|
|
1
|
+
import { AdjustmentState, Controller } from './editor/type';
|
|
2
2
|
/**
|
|
3
3
|
* Configuration options for the adjustment history hook
|
|
4
4
|
*/
|
|
5
|
-
interface HistoryOptions {
|
|
5
|
+
export interface HistoryOptions {
|
|
6
6
|
/** Maximum number of history entries to keep. Use 'unlimited' for no limit */
|
|
7
7
|
maxSize?: number | 'unlimited';
|
|
8
8
|
/** Whether to enable batch mode for grouping multiple changes */
|
|
@@ -57,9 +57,11 @@ export interface HistoryConfig {
|
|
|
57
57
|
/** Set maximum history size */
|
|
58
58
|
setMaxSize: (size: number | 'unlimited') => void;
|
|
59
59
|
/** Enable or disable batch mode */
|
|
60
|
-
setBatchMode: (enabled: boolean) => void
|
|
60
|
+
setBatchMode: (enabled: boolean) => Promise<void>;
|
|
61
61
|
/** Get current memory usage estimate */
|
|
62
62
|
getMemoryUsage: () => number;
|
|
63
|
+
/** Force sync current state to backend */
|
|
64
|
+
syncToBackend: () => Promise<void>;
|
|
63
65
|
}
|
|
64
66
|
/**
|
|
65
67
|
* Return type for the useAdjustmentHistory hook
|
|
@@ -86,8 +88,10 @@ export interface UseAdjustmentHistoryReturn {
|
|
|
86
88
|
* - Automatic AdjustmentState comparison
|
|
87
89
|
*
|
|
88
90
|
* @param initialState - The initial AdjustmentState value
|
|
91
|
+
* @param controller - Controller for backend operations (optional)
|
|
92
|
+
* @param firebaseUid - Firebase UID for backend operations (optional)
|
|
93
|
+
* @param currentImageId - Current image ID for backend operations (optional)
|
|
89
94
|
* @param options - Configuration options for history behavior
|
|
90
95
|
* @returns Object with current state, history info, actions, and config
|
|
91
96
|
*/
|
|
92
|
-
export declare function useAdjustmentHistory(initialState: AdjustmentState, options?: HistoryOptions): UseAdjustmentHistoryReturn;
|
|
93
|
-
export {};
|
|
97
|
+
export declare function useAdjustmentHistory(initialState: AdjustmentState, controller?: Controller, firebaseUid?: string, currentImageId?: string, options?: HistoryOptions): UseAdjustmentHistoryReturn;
|