@yogiswara/honcho-editor-ui 3.3.4 → 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.
Files changed (34) hide show
  1. package/dist/components/editor/GalleryAlbum/AlbumImageGallery.d.ts +14 -7
  2. package/dist/components/editor/GalleryAlbum/AlbumImageGallery.js +207 -5
  3. package/dist/components/editor/GalleryAlbum/ImageItemComponents.d.ts +25 -0
  4. package/dist/components/editor/GalleryAlbum/ImageItemComponents.js +179 -0
  5. package/dist/components/editor/GalleryAlbum/colorsGallery.d.ts +9 -0
  6. package/dist/components/editor/GalleryAlbum/colorsGallery.js +9 -0
  7. package/dist/components/editor/GalleryAlbum/svg/Tick.d.ts +2 -0
  8. package/dist/components/editor/GalleryAlbum/svg/Tick.js +6 -0
  9. package/dist/components/editor/HBulkAccordionColorAdjustment.js +1 -2
  10. package/dist/components/editor/HBulkAccordionColorAdjustmentColors.js +1 -1
  11. package/dist/components/editor/HBulkPresetMobile.d.ts +2 -2
  12. package/dist/components/editor/HBulkPresetMobile.js +2 -2
  13. package/dist/components/editor/HImageEditorBulkMobile.d.ts +2 -2
  14. package/dist/hooks/demo/HonchoEditorBulkDemo.d.ts +0 -3
  15. package/dist/hooks/demo/HonchoEditorBulkDemo.js +770 -411
  16. package/dist/hooks/demo/HonchoEditorSingleCleanDemo.d.ts +0 -3
  17. package/dist/hooks/demo/HonchoEditorSingleCleanDemo.js +882 -354
  18. package/dist/hooks/demo/index.d.ts +0 -2
  19. package/dist/hooks/demo/index.js +3 -2
  20. package/dist/hooks/editor/type.d.ts +15 -13
  21. package/dist/hooks/editor/useHonchoEditorBulk.d.ts +47 -5
  22. package/dist/hooks/editor/useHonchoEditorBulk.js +252 -133
  23. package/dist/hooks/useAdjustmentHistory.js +12 -12
  24. package/dist/hooks/useAdjustmentHistoryBatch.d.ts +33 -31
  25. package/dist/hooks/useAdjustmentHistoryBatch.js +703 -170
  26. package/dist/hooks/usePreset.js +12 -12
  27. package/dist/index.d.ts +5 -7
  28. package/dist/index.js +5 -4
  29. package/dist/services/type.d.ts +14 -0
  30. package/dist/utils/adjustment.d.ts +1 -1
  31. package/dist/utils/adjustment.js +15 -14
  32. package/dist/utils/logger.d.ts +3 -0
  33. package/dist/utils/logger.js +11 -0
  34. 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
- const adjustmentsMatch = (a, b) => {
63
- const keys = [
64
- 'tempScore', 'tintScore', 'vibranceScore', 'saturationScore',
65
- 'exposureScore', 'highlightsScore', 'shadowsScore', 'whitesScore',
66
- 'blacksScore', 'contrastScore', 'clarityScore', 'sharpnessScore'
67
- ];
68
- return keys.every(key => (a[key] || 0) === (b[key] || 0));
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
- console.log('[useHonchoEditorBulk] 🏭 Initializing with controller for multi-image backend sync');
87
- const { currentBatch, selectedIds, actions: batchActions, historyInfo } = useAdjustmentHistoryBatch({
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 active preset based on selected images' adjustments
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 adjustments for all selected images
112
- const selectedAdjustments = selectedIds.map(imageId => {
113
- return currentBatch.allImages[imageId] || {
114
- tempScore: 0, tintScore: 0, vibranceScore: 0, saturationScore: 0,
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
- // Check if all selected images have the same adjustments
120
- const firstAdjustment = selectedAdjustments[0];
121
- const allSameAdjustments = selectedAdjustments.every(adj => adjustmentsMatch(adj, firstAdjustment));
122
- if (!allSameAdjustments) {
123
- // Selected images have different adjustments
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 adjustment state
127
- const matchingPreset = presets.find(preset => {
128
- const presetAdjustments = presetToAdjustmentState(preset);
129
- return adjustmentsMatch(presetAdjustments, firstAdjustment);
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
- setSelectedBulkPreset(activePreset?.id || '');
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 batchAdjustment = currentBatch.allImages[item.id];
151
- if (batchAdjustment) {
152
- const adjustmentsValues = mapAdjustmentStateToAdjustmentEditor(batchAdjustment);
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
- // Merge batch adjustments over backend adjustments
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
- // Store the latest batchActions.syncAdjustment in a ref to avoid dependency issues
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
- console.log('[useHonchoEditorBulk] 🔄 Sync effect triggered:', {
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
- console.log('[useHonchoEditorBulk] 🔍 New images check:', {
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
- console.log('[useHonchoEditorBulk] ⚠️ SYNC TRIGGER: Syncing new images to batch (THIS RESETS HISTORY!):', images.length);
183
- syncAdjustmentRef.current(images.map(mapToImageAdjustmentConfig));
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
- console.log('[useHonchoEditorBulk] ✅ No new images, skipping sync (history preserved)');
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((event) => {
195
- const presetId = event.target.value;
346
+ const handleSelectBulkPreset = useCallback((presetId) => {
196
347
  setSelectedBulkPreset(presetId);
197
- console.log('[useHonchoEditorBulk] 🎨 Preset selection attempt:', {
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
- console.log('[useHonchoEditorBulk] ❌ No preset ID provided, skipping backend call');
356
+ log.warn('[useHonchoEditorBulk] ❌ No preset ID provided, skipping backend call');
206
357
  return;
207
358
  }
208
359
  if (selectedIds.length === 0) {
209
- console.log('[useHonchoEditorBulk] ❌ No images selected, skipping backend call');
360
+ log.warn('[useHonchoEditorBulk] ❌ No images selected, skipping backend call');
210
361
  return;
211
362
  }
212
- console.log('[useHonchoEditorBulk] 🎨 Applying preset to multiple images:', {
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
- console.log('[useHonchoEditorBulk] ❌ Preset not found in presets list:', presetId);
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
- console.log('[useHonchoEditorBulk] 📤 Sending preset adjustments to controller for each image:', presetAdjustments);
226
- console.log('[useHonchoEditorBulk] 🔄 About to call batchActions.adjustSelectedWithPreset');
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
- console.log('[useHonchoEditorBulk] ✅ Called batchActions.adjustSelectedWithPreset, backend calls should be triggered');
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
- console.debug(`[useHonchoEditorBulk] 🎛️ Bulk ${key} adjustment:`, {
385
+ log.debug({
235
386
  key,
236
387
  amount,
237
388
  selectedImages: selectedIds,
238
389
  imageCount: selectedIds.length
239
- });
240
- console.debug('[useHonchoEditorBulk] 📤 Sending bulk adjustment to controller for each selected image');
241
- console.debug("currentBatch.allImages before:", currentBatch.allImages);
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
- console.debug("currentBatch.allImages after:", currentBatch.allImages);
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
- console.log('[useHonchoEditorBulk] ⏪ Undo requested for multiple images:', {
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
  /**