@yogiswara/honcho-editor-ui 3.3.3 → 3.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/components/editor/GalleryAlbum/AlbumImageGallery.d.ts +14 -7
- package/dist/components/editor/GalleryAlbum/AlbumImageGallery.js +207 -5
- package/dist/components/editor/GalleryAlbum/ImageItemComponents.d.ts +25 -0
- package/dist/components/editor/GalleryAlbum/ImageItemComponents.js +179 -0
- package/dist/components/editor/GalleryAlbum/colorsGallery.d.ts +9 -0
- package/dist/components/editor/GalleryAlbum/colorsGallery.js +9 -0
- package/dist/components/editor/GalleryAlbum/svg/Tick.d.ts +2 -0
- package/dist/components/editor/GalleryAlbum/svg/Tick.js +6 -0
- package/dist/components/editor/HBulkAccordionColorAdjustment.js +1 -2
- package/dist/components/editor/HBulkAccordionColorAdjustmentColors.js +1 -1
- package/dist/components/editor/HBulkPresetMobile.d.ts +2 -2
- package/dist/components/editor/HBulkPresetMobile.js +2 -2
- package/dist/components/editor/HImageEditorBulkMobile.d.ts +2 -2
- package/dist/hooks/demo/HonchoEditorBulkDemo.d.ts +0 -3
- package/dist/hooks/demo/HonchoEditorBulkDemo.js +770 -411
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.d.ts +0 -3
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.js +882 -354
- package/dist/hooks/demo/index.d.ts +0 -2
- package/dist/hooks/demo/index.js +3 -2
- package/dist/hooks/editor/type.d.ts +15 -12
- package/dist/hooks/editor/useHonchoEditorBulk.d.ts +47 -5
- package/dist/hooks/editor/useHonchoEditorBulk.js +252 -133
- package/dist/hooks/useAdjustmentHistory.js +12 -12
- package/dist/hooks/useAdjustmentHistoryBatch.d.ts +33 -31
- package/dist/hooks/useAdjustmentHistoryBatch.js +703 -170
- package/dist/hooks/usePreset.js +12 -12
- package/dist/index.d.ts +5 -7
- package/dist/index.js +5 -4
- package/dist/services/type.d.ts +14 -0
- package/dist/utils/adjustment.d.ts +1 -1
- package/dist/utils/adjustment.js +15 -14
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.js +11 -0
- package/package.json +4 -2
|
@@ -4,8 +4,10 @@ import { useAdjustmentHistoryBatch } from '../useAdjustmentHistoryBatch';
|
|
|
4
4
|
import { usePaging } from "../usePaging";
|
|
5
5
|
import { usePreset } from "../usePreset";
|
|
6
6
|
import { mapAdjustmentStateToAdjustmentEditor } from "../../utils/adjustment";
|
|
7
|
+
import { log } from '../../utils/logger';
|
|
7
8
|
// Helper function to map the API response to the format our UI component needs
|
|
8
9
|
const mapGalleryToPhotoData = (gallery, selectedIds) => {
|
|
10
|
+
log.debug({ gallery }, "[useHonchoEditorBulk] mapGalleryToPhotoData");
|
|
9
11
|
return {
|
|
10
12
|
key: gallery.id,
|
|
11
13
|
src: gallery.raw_thumbnail?.path ? gallery.raw_thumbnail.path : gallery.thumbnail?.path,
|
|
@@ -17,13 +19,31 @@ const mapGalleryToPhotoData = (gallery, selectedIds) => {
|
|
|
17
19
|
adjustments: gallery.editor_config?.color_adjustment,
|
|
18
20
|
};
|
|
19
21
|
};
|
|
22
|
+
// Helper function to map PhotoData to GallerySetup format for AlbumImageGalleryInfinite
|
|
23
|
+
// PhotoData already contains the correct adjustments from history (processed in imageData useMemo)
|
|
24
|
+
const mapPhotoDataToGallerySetup = (photoData) => {
|
|
25
|
+
log.debug({ photoData }, "[useHonchoEditorBulk] mapPhotoDataToGallerySetup");
|
|
26
|
+
return {
|
|
27
|
+
src: photoData.src,
|
|
28
|
+
original: photoData.original,
|
|
29
|
+
srcSet: undefined,
|
|
30
|
+
sizes: undefined,
|
|
31
|
+
width: photoData.width,
|
|
32
|
+
height: photoData.height,
|
|
33
|
+
alt: photoData.alt,
|
|
34
|
+
key: photoData.key,
|
|
35
|
+
frame: undefined,
|
|
36
|
+
isSelected: photoData.isSelected,
|
|
37
|
+
adjustments: photoData.adjustments, // Already contains history adjustments if available
|
|
38
|
+
};
|
|
39
|
+
};
|
|
20
40
|
const mapToImageAdjustmentConfig = (gallery) => {
|
|
21
41
|
return {
|
|
22
42
|
imageId: gallery.id,
|
|
23
|
-
adjustment: mapColorAdjustmentToAdjustmentState(gallery.editor_config?.color_adjustment),
|
|
43
|
+
adjustment: mapColorAdjustmentToAdjustmentState(gallery.editor_config?.color_adjustment, gallery.editor_config?.preset_id),
|
|
24
44
|
};
|
|
25
45
|
};
|
|
26
|
-
function mapColorAdjustmentToAdjustmentState(adj) {
|
|
46
|
+
function mapColorAdjustmentToAdjustmentState(adj, preset_id) {
|
|
27
47
|
if (!adj)
|
|
28
48
|
return undefined;
|
|
29
49
|
return {
|
|
@@ -39,6 +59,7 @@ function mapColorAdjustmentToAdjustmentState(adj) {
|
|
|
39
59
|
contrastScore: adj.contrast || 0,
|
|
40
60
|
clarityScore: adj.clarity || 0,
|
|
41
61
|
sharpnessScore: adj.sharpness || 0,
|
|
62
|
+
preset_id: preset_id,
|
|
42
63
|
};
|
|
43
64
|
}
|
|
44
65
|
// Helper function to convert Preset to AdjustmentState
|
|
@@ -59,14 +80,53 @@ const presetToAdjustmentState = (preset) => {
|
|
|
59
80
|
};
|
|
60
81
|
};
|
|
61
82
|
// Helper function to compare adjustment states
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
83
|
+
// Remove adjustmentsMatch function as we now use preset_id based comparison
|
|
84
|
+
/**
|
|
85
|
+
* Helper function to get current adjustments from selected images
|
|
86
|
+
* Returns the common adjustments or zero values if images have different adjustments
|
|
87
|
+
*/
|
|
88
|
+
const getCurrentAdjustmentsForCopy = (selectedIds, currentBatch) => {
|
|
89
|
+
if (selectedIds.length === 0) {
|
|
90
|
+
return {
|
|
91
|
+
tempScore: 0, tintScore: 0, vibranceScore: 0, saturationScore: 0,
|
|
92
|
+
exposureScore: 0, highlightsScore: 0, shadowsScore: 0, whitesScore: 0,
|
|
93
|
+
blacksScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// Get adjustments from the first selected image
|
|
97
|
+
const firstImageId = selectedIds[0];
|
|
98
|
+
const firstImageAdjustments = currentBatch.allImages[firstImageId];
|
|
99
|
+
if (!firstImageAdjustments) {
|
|
100
|
+
return {
|
|
101
|
+
tempScore: 0, tintScore: 0, vibranceScore: 0, saturationScore: 0,
|
|
102
|
+
exposureScore: 0, highlightsScore: 0, shadowsScore: 0, whitesScore: 0,
|
|
103
|
+
blacksScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// If only one image is selected, return its adjustments
|
|
107
|
+
if (selectedIds.length === 1) {
|
|
108
|
+
return firstImageAdjustments;
|
|
109
|
+
}
|
|
110
|
+
// If multiple images are selected, check if they all have the same adjustments
|
|
111
|
+
// If not, return zero values (indicating mixed adjustments)
|
|
112
|
+
const allSame = selectedIds.slice(1).every(imageId => {
|
|
113
|
+
const imageAdjustments = currentBatch.allImages[imageId];
|
|
114
|
+
if (!imageAdjustments)
|
|
115
|
+
return false;
|
|
116
|
+
return Object.keys(firstImageAdjustments).every(key => {
|
|
117
|
+
return firstImageAdjustments[key] ===
|
|
118
|
+
imageAdjustments[key];
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
return allSame ? firstImageAdjustments : {
|
|
122
|
+
tempScore: 0, tintScore: 0, vibranceScore: 0, saturationScore: 0,
|
|
123
|
+
exposureScore: 0, highlightsScore: 0, shadowsScore: 0, whitesScore: 0,
|
|
124
|
+
blacksScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
|
|
125
|
+
};
|
|
69
126
|
};
|
|
127
|
+
/**
|
|
128
|
+
* Helper function to create selective adjustments based on checkboxes
|
|
129
|
+
*/
|
|
70
130
|
/**
|
|
71
131
|
* Hook for bulk photo editing with multi-image backend synchronization.
|
|
72
132
|
*
|
|
@@ -83,166 +143,257 @@ const adjustmentsMatch = (a, b) => {
|
|
|
83
143
|
* - Comprehensive logging of multi-image operations
|
|
84
144
|
*/
|
|
85
145
|
export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
86
|
-
|
|
87
|
-
const { currentBatch, selectedIds
|
|
88
|
-
controller,
|
|
89
|
-
firebaseUid,
|
|
90
|
-
eventId: eventID,
|
|
91
|
-
devWarnings: true
|
|
92
|
-
});
|
|
146
|
+
const { state, actions: batchActions } = useAdjustmentHistoryBatch(controller, firebaseUid, eventID);
|
|
147
|
+
const { currentBatch, selectedIds } = state;
|
|
93
148
|
const { images, info, actions } = usePaging(controller, firebaseUid, eventID, {
|
|
94
149
|
autoLoad: true,
|
|
95
|
-
autoReset: false // Prevent auto-reset to avoid loops
|
|
150
|
+
autoReset: false, // Prevent auto-reset to avoid loops
|
|
96
151
|
});
|
|
97
152
|
// Preset management
|
|
98
153
|
const { presets, actions: presetActions } = usePreset(controller, firebaseUid, {
|
|
99
154
|
autoLoad: true,
|
|
100
|
-
devWarnings: true
|
|
101
155
|
});
|
|
102
156
|
// Track which images have been synced to prevent loops
|
|
103
157
|
const lastSyncedImageIds = useRef(new Set());
|
|
104
|
-
// State for Bulk Editing
|
|
158
|
+
// State for Bulk Editing
|
|
105
159
|
const [selectedBulkPreset, setSelectedBulkPreset] = useState('');
|
|
106
|
-
// Calculate
|
|
160
|
+
// Calculate current adjustments for copy operations
|
|
161
|
+
const currentAdjustments = useMemo(() => {
|
|
162
|
+
return getCurrentAdjustmentsForCopy(selectedIds, currentBatch);
|
|
163
|
+
}, [selectedIds, currentBatch]);
|
|
164
|
+
// Calculate active preset based on preset_id from history (not value comparison)
|
|
107
165
|
const activePreset = useMemo(() => {
|
|
108
166
|
if (selectedIds.length === 0) {
|
|
109
167
|
return null;
|
|
110
168
|
}
|
|
111
|
-
// Get
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
exposureScore: 0, highlightsScore: 0, shadowsScore: 0, whitesScore: 0,
|
|
116
|
-
blacksScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
|
|
117
|
-
};
|
|
169
|
+
// Get preset_id for all selected images from current batch
|
|
170
|
+
const selectedPresetIds = selectedIds.map(imageId => {
|
|
171
|
+
const adjustment = currentBatch.allImages[imageId];
|
|
172
|
+
return adjustment?.preset_id;
|
|
118
173
|
});
|
|
119
|
-
//
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
174
|
+
// Get the first preset_id to compare against
|
|
175
|
+
const firstPresetId = selectedPresetIds[0];
|
|
176
|
+
// Check if all selected images have the same preset_id
|
|
177
|
+
const allSamePresetId = selectedPresetIds.every(presetId => presetId === firstPresetId);
|
|
178
|
+
if (!allSamePresetId || !firstPresetId) {
|
|
179
|
+
// Either not all images have the same preset_id, or no preset_id at all
|
|
124
180
|
return null;
|
|
125
181
|
}
|
|
126
|
-
// Find preset that matches the common
|
|
127
|
-
const matchingPreset = presets.find(preset =>
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
182
|
+
// Find the preset that matches the common preset_id
|
|
183
|
+
const matchingPreset = presets.find(preset => preset.id === firstPresetId);
|
|
184
|
+
log.debug({
|
|
185
|
+
selectedIds,
|
|
186
|
+
selectedPresetIds,
|
|
187
|
+
firstPresetId,
|
|
188
|
+
allSamePresetId,
|
|
189
|
+
matchingPreset: matchingPreset?.name || 'none',
|
|
190
|
+
selectedImageAdjustments: selectedIds.map(id => ({
|
|
191
|
+
imageId: id,
|
|
192
|
+
preset_id: currentBatch.allImages[id]?.preset_id,
|
|
193
|
+
hasAdjustment: !!currentBatch.allImages[id]
|
|
194
|
+
}))
|
|
195
|
+
}, '[useHonchoEditorBulk] 🎨 Active preset calculation');
|
|
131
196
|
return matchingPreset || null;
|
|
132
197
|
}, [selectedIds, currentBatch.allImages, presets]);
|
|
133
198
|
// Update selectedBulkPreset when activePreset changes
|
|
134
199
|
useEffect(() => {
|
|
135
|
-
|
|
200
|
+
const newPresetId = activePreset?.id || '';
|
|
201
|
+
setSelectedBulkPreset(newPresetId);
|
|
202
|
+
log.debug({
|
|
203
|
+
activePreset: activePreset?.name || 'none',
|
|
204
|
+
presetId: newPresetId,
|
|
205
|
+
selectedImagesCount: selectedIds.length,
|
|
206
|
+
triggerReason: 'activePreset changed'
|
|
207
|
+
}, '[useHonchoEditorBulk] 🎨 Preset selection updated');
|
|
136
208
|
}, [activePreset]);
|
|
137
209
|
// Use loading states from usePaging instead of local state
|
|
138
210
|
const isLoading = info.isLoading;
|
|
139
211
|
const error = info.error;
|
|
140
212
|
const hasMore = info.hasMore;
|
|
141
213
|
const imageData = useMemo(() => {
|
|
142
|
-
// console.debug("imageData recalculating with:", {
|
|
143
|
-
// imagesLength: images.length,
|
|
144
|
-
// selectedIds,
|
|
145
|
-
// currentBatch_allImages: currentBatch.allImages,
|
|
146
|
-
// currentBatch_allImages_keys: Object.keys(currentBatch.allImages)
|
|
147
|
-
// });
|
|
148
214
|
const res = images.map(item => {
|
|
149
215
|
const basePhoto = mapGalleryToPhotoData(item, selectedIds);
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
216
|
+
const historyAdjustment = currentBatch.allImages[item.id];
|
|
217
|
+
// **ADJUSTMENT PRIORITY LOGIC**
|
|
218
|
+
// 1. History adjustments (from useAdjustmentHistoryBatch) - highest priority
|
|
219
|
+
// These are the most current client-side changes that may not be saved to backend yet
|
|
220
|
+
// 2. Backend adjustments (from paging data) - fallback
|
|
221
|
+
// These come from the server and represent previously saved adjustments
|
|
222
|
+
//
|
|
223
|
+
// This ensures that when user makes adjustments in the UI, they are immediately
|
|
224
|
+
// reflected in the gallery view even before they're synced to the backend.
|
|
225
|
+
if (historyAdjustment) {
|
|
226
|
+
// Use adjustments from history (most current client-side changes)
|
|
227
|
+
// Convert AdjustmentState (from history) to AdjustmentValues (for UI)
|
|
228
|
+
const adjustmentsValues = mapAdjustmentStateToAdjustmentEditor(historyAdjustment);
|
|
153
229
|
basePhoto.adjustments = adjustmentsValues;
|
|
230
|
+
log.debug({
|
|
231
|
+
historyAdjustment,
|
|
232
|
+
convertedValues: adjustmentsValues
|
|
233
|
+
}, `[useHonchoEditorBulk] 📊 Image ${item.id} using HISTORY adjustments`);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
// Fall back to backend adjustments if no history exists for this image
|
|
237
|
+
// basePhoto.adjustments already contains backend data from mapGalleryToPhotoData
|
|
238
|
+
log.debug({
|
|
239
|
+
backendAdjustments: basePhoto.adjustments
|
|
240
|
+
}, `[useHonchoEditorBulk] 📊 Image ${item.id} using BACKEND adjustments`);
|
|
154
241
|
}
|
|
155
|
-
|
|
156
|
-
return batchAdjustment ? { ...basePhoto } : basePhoto;
|
|
242
|
+
return basePhoto;
|
|
157
243
|
});
|
|
244
|
+
log.debug({
|
|
245
|
+
totalImages: res.length,
|
|
246
|
+
imagesWithHistory: res.filter(img => currentBatch.allImages[img.key]).length,
|
|
247
|
+
imagesWithBackendOnly: res.filter(img => !currentBatch.allImages[img.key] && img.adjustments).length,
|
|
248
|
+
imagesWithNoAdjustments: res.filter(img => !currentBatch.allImages[img.key] && !img.adjustments).length
|
|
249
|
+
}, '[useHonchoEditorBulk] 📊 ImageData construction summary');
|
|
158
250
|
return res;
|
|
159
251
|
}, [images, selectedIds, currentBatch.allImages]);
|
|
160
|
-
//
|
|
252
|
+
// Convert imageData (PhotoData[]) to GallerySetup[] for AlbumImageGalleryInfinite
|
|
253
|
+
const gallerySetupData = useMemo(() => {
|
|
254
|
+
const result = imageData.map(mapPhotoDataToGallerySetup);
|
|
255
|
+
log.debug({
|
|
256
|
+
photoDataCount: imageData.length,
|
|
257
|
+
gallerySetupCount: result.length,
|
|
258
|
+
batchImageCount: Object.keys(currentBatch.allImages).length,
|
|
259
|
+
samplePhotoData: imageData[0] ? {
|
|
260
|
+
key: imageData[0].key,
|
|
261
|
+
src: imageData[0].src,
|
|
262
|
+
isSelected: imageData[0].isSelected,
|
|
263
|
+
hasAdjustments: !!imageData[0].adjustments
|
|
264
|
+
} : null,
|
|
265
|
+
sampleGallerySetup: result[0] ? {
|
|
266
|
+
key: result[0].key,
|
|
267
|
+
src: result[0].src,
|
|
268
|
+
isSelected: result[0].isSelected,
|
|
269
|
+
hasAdjustments: !!result[0].adjustments,
|
|
270
|
+
adjustmentsSource: currentBatch.allImages[result[0].key] ? 'history' : 'backend'
|
|
271
|
+
} : null
|
|
272
|
+
}, '[useHonchoEditorBulk] 🔄 Mapped PhotoData to GallerySetup');
|
|
273
|
+
return result;
|
|
274
|
+
}, [imageData, currentBatch.allImages]);
|
|
275
|
+
// Store the latest batchActions functions in refs to avoid dependency issues
|
|
161
276
|
const syncAdjustmentRef = useRef(batchActions.syncAdjustment);
|
|
277
|
+
const initializeFromPaginationRef = useRef(batchActions.initializeFromPagination);
|
|
162
278
|
syncAdjustmentRef.current = batchActions.syncAdjustment;
|
|
279
|
+
initializeFromPaginationRef.current = batchActions.initializeFromPagination;
|
|
163
280
|
// Safe sync: Only sync new images to prevent infinite loops
|
|
164
281
|
useEffect(() => {
|
|
165
|
-
|
|
282
|
+
log.debug({
|
|
166
283
|
imagesLength: images.length,
|
|
167
284
|
imageIds: images.map(img => img.id),
|
|
168
285
|
lastSyncedImageIds: Array.from(lastSyncedImageIds.current),
|
|
169
286
|
lastSyncedCount: lastSyncedImageIds.current.size
|
|
170
|
-
});
|
|
287
|
+
}, '[useHonchoEditorBulk] 🔄 Sync effect triggered');
|
|
171
288
|
if (images.length === 0)
|
|
172
289
|
return;
|
|
173
290
|
// Check if we have new images that haven't been synced
|
|
174
291
|
const currentImageIds = new Set(images.map(img => img.id));
|
|
175
292
|
const hasNewImages = images.some(img => !lastSyncedImageIds.current.has(img.id));
|
|
176
|
-
|
|
293
|
+
log.debug({
|
|
177
294
|
currentImageIds: Array.from(currentImageIds),
|
|
178
295
|
hasNewImages,
|
|
179
296
|
newImages: images.filter(img => !lastSyncedImageIds.current.has(img.id)).map(img => img.id)
|
|
180
|
-
});
|
|
297
|
+
}, '[useHonchoEditorBulk] 🔍 New images check');
|
|
181
298
|
if (hasNewImages) {
|
|
182
|
-
|
|
183
|
-
|
|
299
|
+
log.info({ imageCount: images.length }, '[useHonchoEditorBulk] 🔄 INITIALIZE: Initializing new images from pagination data (preserves history)');
|
|
300
|
+
initializeFromPaginationRef.current(images.map(mapToImageAdjustmentConfig));
|
|
184
301
|
lastSyncedImageIds.current = currentImageIds;
|
|
185
302
|
}
|
|
186
303
|
else {
|
|
187
|
-
|
|
304
|
+
log.debug('[useHonchoEditorBulk] ✅ No new images, skipping initialization (history preserved)');
|
|
188
305
|
}
|
|
189
306
|
}, [images]); // Only depend on images, not batchActions
|
|
307
|
+
const clearSelection = useCallback(() => {
|
|
308
|
+
log.info({
|
|
309
|
+
currentlySelected: selectedIds.length,
|
|
310
|
+
selectedImageIds: selectedIds
|
|
311
|
+
}, '[useHonchoEditorBulk] Clearing all selections');
|
|
312
|
+
// If there are selected images, toggle them off one by one
|
|
313
|
+
if (selectedIds.length > 0) {
|
|
314
|
+
selectedIds.forEach(imageId => {
|
|
315
|
+
batchActions.toggleSelection(imageId);
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
log.info('[useHonchoEditorBulk] All selections cleared');
|
|
319
|
+
}, [selectedIds, batchActions]);
|
|
320
|
+
const selectAllImages = useCallback(() => {
|
|
321
|
+
log.info({
|
|
322
|
+
totalImages: gallerySetupData.length,
|
|
323
|
+
currentlySelected: selectedIds.length,
|
|
324
|
+
availableImageIds: gallerySetupData.map(img => img.key)
|
|
325
|
+
}, '[useHonchoEditorBulk] Selecting all images');
|
|
326
|
+
// Get all image IDs from gallerySetupData
|
|
327
|
+
const allImageIds = gallerySetupData.map(image => image.key);
|
|
328
|
+
if (allImageIds.length === 0) {
|
|
329
|
+
log.warn('[useHonchoEditorBulk] No images available to select');
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
// Find images that are not currently selected and select them
|
|
333
|
+
const unselectedImages = allImageIds.filter(imageId => !selectedIds.includes(imageId));
|
|
334
|
+
unselectedImages.forEach(imageId => {
|
|
335
|
+
batchActions.toggleSelection(imageId);
|
|
336
|
+
});
|
|
337
|
+
log.info({
|
|
338
|
+
selectedCount: allImageIds.length,
|
|
339
|
+
newlySelected: unselectedImages.length
|
|
340
|
+
}, '[useHonchoEditorBulk] All images selected');
|
|
341
|
+
}, [gallerySetupData, selectedIds, batchActions]);
|
|
190
342
|
const handleBackCallbackBulk = useCallback(() => {
|
|
191
343
|
const lastSelectedId = selectedIds.length > 0 ? selectedIds[selectedIds.length - 1] : "";
|
|
192
344
|
controller.handleBack(firebaseUid, lastSelectedId);
|
|
193
345
|
}, [controller, firebaseUid, selectedIds]);
|
|
194
|
-
const handleSelectBulkPreset = useCallback((
|
|
195
|
-
const presetId = event.target.value;
|
|
346
|
+
const handleSelectBulkPreset = useCallback((presetId) => {
|
|
196
347
|
setSelectedBulkPreset(presetId);
|
|
197
|
-
|
|
348
|
+
log.info({
|
|
198
349
|
presetId,
|
|
199
350
|
selectedImages: selectedIds,
|
|
200
351
|
imageCount: selectedIds.length,
|
|
201
352
|
hasController: !!controller,
|
|
202
353
|
hasFirebaseUid: !!firebaseUid
|
|
203
|
-
});
|
|
354
|
+
}, '[useHonchoEditorBulk] 🎨 Preset selection attempt');
|
|
204
355
|
if (!presetId) {
|
|
205
|
-
|
|
356
|
+
log.warn('[useHonchoEditorBulk] ❌ No preset ID provided, skipping backend call');
|
|
206
357
|
return;
|
|
207
358
|
}
|
|
208
359
|
if (selectedIds.length === 0) {
|
|
209
|
-
|
|
360
|
+
log.warn('[useHonchoEditorBulk] ❌ No images selected, skipping backend call');
|
|
210
361
|
return;
|
|
211
362
|
}
|
|
212
|
-
|
|
363
|
+
log.info({
|
|
213
364
|
presetId,
|
|
214
365
|
selectedImages: selectedIds,
|
|
215
366
|
imageCount: selectedIds.length
|
|
216
|
-
});
|
|
367
|
+
}, '[useHonchoEditorBulk] 🎨 Applying preset to multiple images');
|
|
217
368
|
// Find the preset
|
|
218
369
|
const preset = presets.find(p => p.id === presetId);
|
|
219
370
|
if (!preset) {
|
|
220
|
-
|
|
371
|
+
log.error({ presetId }, '[useHonchoEditorBulk] ❌ Preset not found in presets list');
|
|
221
372
|
return;
|
|
222
373
|
}
|
|
223
374
|
// Convert preset to adjustment state
|
|
224
375
|
const presetAdjustments = presetToAdjustmentState(preset);
|
|
225
|
-
|
|
226
|
-
|
|
376
|
+
log.debug({ presetAdjustments }, '[useHonchoEditorBulk] 📤 Sending preset adjustments to controller for each image');
|
|
377
|
+
log.debug('[useHonchoEditorBulk] 🔄 About to call batchActions.adjustSelectedWithPreset');
|
|
227
378
|
// Apply preset directly to all selected images using the clean action
|
|
228
379
|
// This will trigger backend calls for each selected image via adjustSelectedWithPreset
|
|
229
|
-
batchActions.adjustSelectedWithPreset(presetAdjustments);
|
|
230
|
-
|
|
380
|
+
batchActions.adjustSelectedWithPreset(presetAdjustments, preset.id);
|
|
381
|
+
log.info('[useHonchoEditorBulk] ✅ Called batchActions.adjustSelectedWithPreset, backend calls should be triggered');
|
|
231
382
|
}, [presets, selectedIds, batchActions, controller, firebaseUid]);
|
|
232
383
|
// This factory creates functions that adjust a value for all selected images
|
|
233
384
|
const createRelativeAdjuster = useCallback((key, amount) => () => {
|
|
234
|
-
|
|
385
|
+
log.debug({
|
|
235
386
|
key,
|
|
236
387
|
amount,
|
|
237
388
|
selectedImages: selectedIds,
|
|
238
389
|
imageCount: selectedIds.length
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
|
|
390
|
+
}, `[useHonchoEditorBulk] 🎛️ Bulk ${key} adjustment`);
|
|
391
|
+
log.debug('[useHonchoEditorBulk] 📤 Sending bulk adjustment to controller for each selected image');
|
|
392
|
+
log.debug({ allImages: currentBatch.allImages }, "currentBatch.allImages before");
|
|
242
393
|
batchActions.adjustSelected({ [key]: amount });
|
|
243
394
|
// Debug after a short delay to see if the state changed
|
|
244
395
|
setTimeout(() => {
|
|
245
|
-
|
|
396
|
+
log.debug({ allImages: currentBatch.allImages }, "currentBatch.allImages after");
|
|
246
397
|
}, 100);
|
|
247
398
|
}, [batchActions, selectedIds, currentBatch.allImages]);
|
|
248
399
|
const handleBulkTempDecreaseMax = createRelativeAdjuster('tempScore', -20);
|
|
@@ -293,50 +444,10 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
293
444
|
const handleBulkSharpnessDecrease = createRelativeAdjuster('sharpnessScore', -5);
|
|
294
445
|
const handleBulkSharpnessIncrease = createRelativeAdjuster('sharpnessScore', 5);
|
|
295
446
|
const handleBulkSharpnessIncreaseMax = createRelativeAdjuster('sharpnessScore', 20);
|
|
296
|
-
// const loadImages = useCallback(async (pageNum: number) => {
|
|
297
|
-
// // Use the correct loading state
|
|
298
|
-
// if (pageNum === 1) {
|
|
299
|
-
// setIsLoading(true);
|
|
300
|
-
// } else {
|
|
301
|
-
// setIsFetchingMore(true);
|
|
302
|
-
// }
|
|
303
|
-
// setError(null);
|
|
304
|
-
// try {
|
|
305
|
-
// const response = await controller.getImageList(firebaseUid, eventID, pageNum);
|
|
306
|
-
// // Sync adjustments for the new images with the batch history
|
|
307
|
-
// batchActions.syncAdjustment(response.gallery.map(mapToImageAdjustmentConfig));
|
|
308
|
-
// // Append new images for page > 1, otherwise replace
|
|
309
|
-
// setImageCollection(prev => pageNum === 1 ? response.gallery : [...prev, ...response.gallery]);
|
|
310
|
-
// setPage(response.current_page);
|
|
311
|
-
// setHasMore(response.next_page > 0 && response.gallery.length > 0);
|
|
312
|
-
// } catch (err: any) {
|
|
313
|
-
// console.error("Failed to fetch image list:", err);
|
|
314
|
-
// setError(err.message || "Could not load images.");
|
|
315
|
-
// } finally {
|
|
316
|
-
// if (pageNum === 1) {
|
|
317
|
-
// setIsLoading(false);
|
|
318
|
-
// } else {
|
|
319
|
-
// setIsFetchingMore(false);
|
|
320
|
-
// }
|
|
321
|
-
// }
|
|
322
|
-
// }, [controller, firebaseUid, eventID, batchActions]);
|
|
323
|
-
// const loadMoreImages = useCallback(() => {
|
|
324
|
-
// if (!isFetchingMore && hasMore) {
|
|
325
|
-
// loadImages(page + 1);
|
|
326
|
-
// }
|
|
327
|
-
// }, [isFetchingMore, hasMore, page, loadImages]);
|
|
328
|
-
// Note: Image loading is now handled by usePaging hook
|
|
329
|
-
// The sync logic above handles syncing loaded images to batch state
|
|
330
|
-
// useEffect(() => {
|
|
331
|
-
// if (eventID && firebaseUid) {
|
|
332
|
-
// setImageCollection([]); // reset when event changes
|
|
333
|
-
// setPage(1);
|
|
334
|
-
// loadImages(1);
|
|
335
|
-
// }
|
|
336
|
-
// }, [eventID, firebaseUid, loadImages]);
|
|
337
447
|
return {
|
|
338
448
|
imageData,
|
|
339
449
|
isLoading,
|
|
450
|
+
isLoadingMore: info.isLoadingMore,
|
|
340
451
|
error,
|
|
341
452
|
selectedIds,
|
|
342
453
|
hasMore,
|
|
@@ -348,6 +459,8 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
348
459
|
selectedBulkPreset,
|
|
349
460
|
activePreset,
|
|
350
461
|
handleSelectBulkPreset,
|
|
462
|
+
clearSelection,
|
|
463
|
+
selectAllImages,
|
|
351
464
|
// Preset creation handlers
|
|
352
465
|
presetActions, // Expose preset actions for create/rename/delete
|
|
353
466
|
handleToggleImageSelection: batchActions.toggleSelection,
|
|
@@ -404,24 +517,30 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
404
517
|
handleBulkSharpnessDecrease,
|
|
405
518
|
handleBulkSharpnessIncrease,
|
|
406
519
|
handleBulkSharpnessIncreaseMax,
|
|
520
|
+
// Adjustment History
|
|
521
|
+
createRelativeAdjuster,
|
|
522
|
+
// copy paste
|
|
523
|
+
// copiedAdjustments,
|
|
524
|
+
currentAdjustments,
|
|
407
525
|
// History actions
|
|
408
|
-
handleUndo:
|
|
409
|
-
|
|
410
|
-
selectedImages: selectedIds,
|
|
411
|
-
imageCount: selectedIds.length
|
|
412
|
-
});
|
|
413
|
-
console.log('[useHonchoEditorBulk] 📤 Sending undo (setHistoryIndex) to controller for each image');
|
|
414
|
-
return batchActions.undo();
|
|
415
|
-
},
|
|
416
|
-
handleRedo: () => {
|
|
417
|
-
console.log('[useHonchoEditorBulk] ⏩ Redo requested for multiple images:', {
|
|
418
|
-
selectedImages: selectedIds,
|
|
419
|
-
imageCount: selectedIds.length
|
|
420
|
-
});
|
|
421
|
-
console.log('[useHonchoEditorBulk] 📤 Sending redo (setHistoryIndex) to controller for each image');
|
|
422
|
-
return batchActions.redo();
|
|
423
|
-
},
|
|
526
|
+
handleUndo: batchActions.undo,
|
|
527
|
+
handleRedo: batchActions.redo,
|
|
424
528
|
handleReset: batchActions.reset,
|
|
425
|
-
historyInfo
|
|
529
|
+
historyInfo: {
|
|
530
|
+
canUndo: state.canUndo,
|
|
531
|
+
canRedo: state.canRedo,
|
|
532
|
+
currentIndex: state.currentIndex,
|
|
533
|
+
totalStates: state.totalStates,
|
|
534
|
+
selectedCount: state.selectedCount,
|
|
535
|
+
totalImages: state.totalImages,
|
|
536
|
+
historySize: state.historySize
|
|
537
|
+
},
|
|
538
|
+
// Socket updates
|
|
539
|
+
updateFromSocket: batchActions.updateFromSocket,
|
|
540
|
+
adjustSelected: batchActions.adjustSelected,
|
|
541
|
+
adjustSelectedWithPreset: batchActions.adjustSelectedWithPreset,
|
|
542
|
+
adjustSelectedWithPaste: batchActions.adjustSelectedWithPaste,
|
|
543
|
+
// Gallery setup data for AlbumImageGalleryInfinite
|
|
544
|
+
gallerySetupData,
|
|
426
545
|
};
|
|
427
546
|
}
|
|
@@ -4,18 +4,18 @@ import { useState, useCallback, useMemo, useRef, useEffect } from 'react';
|
|
|
4
4
|
*/
|
|
5
5
|
const convertAdjustmentStateToColorAdjustment = (adjustmentState) => {
|
|
6
6
|
return {
|
|
7
|
-
temperature: adjustmentState.tempScore,
|
|
8
|
-
tint: adjustmentState.tintScore,
|
|
9
|
-
saturation: adjustmentState.saturationScore,
|
|
10
|
-
vibrance: adjustmentState.vibranceScore,
|
|
11
|
-
exposure: adjustmentState.exposureScore,
|
|
12
|
-
contrast: adjustmentState.contrastScore,
|
|
13
|
-
highlights: adjustmentState.highlightsScore,
|
|
14
|
-
shadows: adjustmentState.shadowsScore,
|
|
15
|
-
whites: adjustmentState.whitesScore,
|
|
16
|
-
blacks: adjustmentState.blacksScore,
|
|
17
|
-
clarity: adjustmentState.clarityScore,
|
|
18
|
-
sharpness: adjustmentState.sharpnessScore,
|
|
7
|
+
temperature: adjustmentState.tempScore || 0,
|
|
8
|
+
tint: adjustmentState.tintScore || 0,
|
|
9
|
+
saturation: adjustmentState.saturationScore || 0,
|
|
10
|
+
vibrance: adjustmentState.vibranceScore || 0,
|
|
11
|
+
exposure: adjustmentState.exposureScore || 0,
|
|
12
|
+
contrast: adjustmentState.contrastScore || 0,
|
|
13
|
+
highlights: adjustmentState.highlightsScore || 0,
|
|
14
|
+
shadows: adjustmentState.shadowsScore || 0,
|
|
15
|
+
whites: adjustmentState.whitesScore || 0,
|
|
16
|
+
blacks: adjustmentState.blacksScore || 0,
|
|
17
|
+
clarity: adjustmentState.clarityScore || 0,
|
|
18
|
+
sharpness: adjustmentState.sharpnessScore || 0,
|
|
19
19
|
};
|
|
20
20
|
};
|
|
21
21
|
/**
|