@yogiswara/honcho-editor-ui 3.9.1 → 3.9.2

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.
@@ -12,6 +12,14 @@ export interface PhotoData {
12
12
  isSelected: boolean;
13
13
  adjustments?: Partial<AdjustmentValues>;
14
14
  }
15
+ export interface GalleryDataProps {
16
+ photos: any[];
17
+ isLoading: boolean;
18
+ isLoadingMore: boolean;
19
+ hasMore: boolean;
20
+ loadMore: () => void;
21
+ reloadGallery: () => void;
22
+ }
15
23
  export interface CopyCheckboxes {
16
24
  color: {
17
25
  temperature: boolean;
@@ -113,6 +121,7 @@ export interface UseHonchoEditorBulkReturn {
113
121
  selectedCount: number;
114
122
  totalImages: number;
115
123
  historySize: number;
124
+ isReady: boolean;
116
125
  };
117
126
  updateFromSocket: (imageId: string, adjustmentTaskId: string, adjustment: ColorAdjustment, preset_id?: string) => Promise<void>;
118
127
  adjustSelected: (delta: Partial<AdjustmentState>) => void;
@@ -137,22 +146,4 @@ export interface UseHonchoEditorBulkReturn {
137
146
  };
138
147
  };
139
148
  }
140
- /**
141
- * Helper function to create selective adjustments based on checkboxes
142
- */
143
- /**
144
- * Hook for bulk photo editing with multi-image backend synchronization.
145
- *
146
- * **Multi-Image Backend Sync:**
147
- * - Each selected image maintains its own history and backend state
148
- * - History operations (undo/redo) trigger separate controller.setHistoryIndex() calls for each selected image
149
- * - Preset application triggers separate controller.createEditorConfig() calls for each selected image
150
- * - Adjustment changes trigger separate controller.createEditorConfig() calls for each selected image
151
- *
152
- * **Key Features:**
153
- * - Individual history tracking per image with backend persistence
154
- * - Bulk operations that respect per-image differences
155
- * - Automatic backend synchronization for all state changes
156
- * - Comprehensive logging of multi-image operations
157
- */
158
- export declare function useHonchoEditorBulk(controller: Controller, eventID: string, firebaseUid: string): UseHonchoEditorBulkReturn;
149
+ export declare function useHonchoEditorBulk(controller: Controller, eventID: string, firebaseUid: string, galleryHookData: GalleryDataProps): UseHonchoEditorBulkReturn;
@@ -1,11 +1,9 @@
1
1
  'use client';
2
2
  import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
3
3
  import { useAdjustmentHistoryBatch } from '../useAdjustmentHistoryBatch';
4
- import { usePaging } from "../usePaging";
5
4
  import { usePreset } from "../usePreset";
6
5
  import { mapAdjustmentStateToAdjustmentEditor } from "../../utils/adjustment";
7
6
  import { log } from '../../utils/logger';
8
- // Helper function to map the API response to the format our UI component needs
9
7
  const mapGalleryToPhotoData = (gallery, selectedIds) => {
10
8
  log.debug({ gallery }, "[useHonchoEditorBulk] mapGalleryToPhotoData");
11
9
  return {
@@ -19,8 +17,6 @@ const mapGalleryToPhotoData = (gallery, selectedIds) => {
19
17
  adjustments: gallery.editor_config?.color_adjustment,
20
18
  };
21
19
  };
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
20
  const mapPhotoDataToGallerySetup = (photoData) => {
25
21
  log.debug({ photoData }, "[useHonchoEditorBulk] mapPhotoDataToGallerySetup");
26
22
  return {
@@ -34,7 +30,7 @@ const mapPhotoDataToGallerySetup = (photoData) => {
34
30
  key: photoData.key,
35
31
  frame: undefined,
36
32
  isSelected: photoData.isSelected,
37
- adjustments: photoData.adjustments, // Already contains history adjustments if available
33
+ adjustments: photoData.adjustments,
38
34
  };
39
35
  };
40
36
  const mapToImageAdjustmentConfig = (gallery) => {
@@ -62,7 +58,6 @@ function mapColorAdjustmentToAdjustmentState(adj, preset_id) {
62
58
  preset_id: preset_id,
63
59
  };
64
60
  }
65
- // Helper function to convert Preset to AdjustmentState
66
61
  const presetToAdjustmentState = (preset) => {
67
62
  return {
68
63
  tempScore: preset.temperature || 0,
@@ -79,12 +74,6 @@ const presetToAdjustmentState = (preset) => {
79
74
  sharpnessScore: preset.sharpness || 0,
80
75
  };
81
76
  };
82
- // Helper function to compare adjustment states
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
77
  const getCurrentAdjustmentsForCopy = (selectedIds, currentBatch) => {
89
78
  if (selectedIds.length === 0) {
90
79
  return {
@@ -93,7 +82,6 @@ const getCurrentAdjustmentsForCopy = (selectedIds, currentBatch) => {
93
82
  blacksScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
94
83
  };
95
84
  }
96
- // Get adjustments from the first selected image
97
85
  const firstImageId = selectedIds[0];
98
86
  const firstImageAdjustments = currentBatch.allImages[firstImageId];
99
87
  if (!firstImageAdjustments) {
@@ -103,12 +91,9 @@ const getCurrentAdjustmentsForCopy = (selectedIds, currentBatch) => {
103
91
  blacksScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
104
92
  };
105
93
  }
106
- // If only one image is selected, return its adjustments
107
94
  if (selectedIds.length === 1) {
108
95
  return firstImageAdjustments;
109
96
  }
110
- // If multiple images are selected, check if they all have the same adjustments
111
- // If not, return zero values (indicating mixed adjustments)
112
97
  const allSame = selectedIds.slice(1).every(imageId => {
113
98
  const imageAdjustments = currentBatch.allImages[imageId];
114
99
  if (!imageAdjustments)
@@ -124,100 +109,64 @@ const getCurrentAdjustmentsForCopy = (selectedIds, currentBatch) => {
124
109
  blacksScore: 0, contrastScore: 0, clarityScore: 0, sharpnessScore: 0,
125
110
  };
126
111
  };
127
- /**
128
- * Helper function to create selective adjustments based on checkboxes
129
- */
130
- /**
131
- * Hook for bulk photo editing with multi-image backend synchronization.
132
- *
133
- * **Multi-Image Backend Sync:**
134
- * - Each selected image maintains its own history and backend state
135
- * - History operations (undo/redo) trigger separate controller.setHistoryIndex() calls for each selected image
136
- * - Preset application triggers separate controller.createEditorConfig() calls for each selected image
137
- * - Adjustment changes trigger separate controller.createEditorConfig() calls for each selected image
138
- *
139
- * **Key Features:**
140
- * - Individual history tracking per image with backend persistence
141
- * - Bulk operations that respect per-image differences
142
- * - Automatic backend synchronization for all state changes
143
- * - Comprehensive logging of multi-image operations
144
- */
145
- export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
112
+ // ✅ FIX: Added galleryHookData to the parameters
113
+ export function useHonchoEditorBulk(controller, eventID, firebaseUid, galleryHookData) {
146
114
  const { state, actions: batchActions } = useAdjustmentHistoryBatch(controller, firebaseUid, eventID);
147
115
  const { currentBatch, selectedIds } = state;
148
- const { images, info, actions } = usePaging(controller, firebaseUid, eventID, {
149
- autoLoad: true,
150
- autoReset: false, // Prevent auto-reset to avoid loops
151
- });
152
- // Preset management
116
+ // FIX: Using the mapped galleryHookData instead of usePaging
117
+ const images = useMemo(() => {
118
+ return galleryHookData.photos.map(p => p.value || p);
119
+ }, [galleryHookData.photos]);
153
120
  const { presets, info: presetInfo, actions: presetActions } = usePreset(controller, firebaseUid, {
154
121
  autoLoad: true,
155
122
  });
156
- // Track which images have been synced to prevent loops
157
123
  const lastSyncedImageIds = useRef(new Set());
158
- // State for Bulk Editing
159
124
  const [selectedBulkPreset, setSelectedBulkPreset] = useState('');
160
- // Calculate current adjustments for copy operations
161
125
  const currentAdjustments = useMemo(() => {
162
126
  return getCurrentAdjustmentsForCopy(selectedIds, currentBatch);
163
127
  }, [selectedIds, currentBatch]);
164
128
  const areAdjustmentsEqual = (adj1, adj2) => {
165
- // The fix is to use this more specific type for our keys array
166
129
  const keys = [
167
130
  'tempScore', 'tintScore', 'saturationScore', 'vibranceScore',
168
131
  'exposureScore', 'contrastScore', 'highlightsScore', 'shadowsScore',
169
132
  'whitesScore', 'blacksScore', 'clarityScore', 'sharpnessScore'
170
133
  ];
171
134
  for (const key of keys) {
172
- // Now, TypeScript knows `key` can't be 'preset_id', so adj1[key] will be a number.
173
135
  if (Math.round(adj1[key] || 0) !== Math.round(adj2[key] || 0)) {
174
136
  return false;
175
137
  }
176
138
  }
177
139
  return true;
178
140
  };
141
+ // ✅ FIX: Using galleryHookData loading status for readiness
179
142
  const readyState = useMemo(() => {
180
143
  const paging = {
181
- isReady: info.isReady ?? (info.isInitialized && !info.isLoading && info.error === null),
182
- isLoading: info.isLoading,
144
+ isReady: !galleryHookData.isLoading,
145
+ isLoading: galleryHookData.isLoading,
183
146
  };
184
- log.debug("[useHonchoEditorBulk] 📊 Paging state");
185
147
  const history = {
186
- isReady: state.isReady ?? true, // History sync happens on-demand, not blocking
148
+ isReady: state.isReady ?? true,
187
149
  isLoading: state.isLoading ?? false
188
150
  };
189
- log.debug("[useHonchoEditorBulk] 📊 History state");
190
151
  const presets = {
191
152
  isReady: presetInfo.isReady ?? (presetInfo.isInitialized && !presetInfo.isLoading),
192
153
  isLoading: presetInfo.isLoading
193
154
  };
194
- log.debug("[useHonchoEditorBulk] 📊 Preset state");
195
155
  const allReady = paging.isReady && history.isReady && presets.isReady;
196
156
  const anyLoading = paging.isLoading || history.isLoading || presets.isLoading;
197
- log.debug({
198
- paging: { isReady: paging.isReady, isLoading: paging.isLoading },
199
- history: { isReady: history.isReady, isLoading: history.isLoading },
200
- presets: { isReady: presets.isReady, isLoading: presets.isLoading },
201
- allReady,
202
- anyLoading
203
- }, '[useHonchoEditorBulk] 📊 Ready state computed');
204
157
  return {
205
158
  isReady: allReady,
206
159
  isLoading: anyLoading,
207
160
  operations: { paging, history, presets }
208
161
  };
209
162
  }, [
210
- info.isReady,
211
- info.isInitialized,
212
- info.isLoading,
213
- info.error,
163
+ galleryHookData.isLoading,
214
164
  state.isReady,
215
165
  state.isLoading,
216
166
  presetInfo.isReady,
217
167
  presetInfo.isInitialized,
218
168
  presetInfo.isLoading
219
169
  ]);
220
- // Calculate active preset based on preset_id from history (not value comparison)
221
170
  const { activePreset, presetSummary } = useMemo(() => {
222
171
  if (selectedIds.length === 0) {
223
172
  return { activePreset: null, presetSummary: 'NO_SELECTION' };
@@ -225,9 +174,7 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
225
174
  const imageDetails = selectedIds.map(id => {
226
175
  const adjustment = currentBatch.allImages[id];
227
176
  const presetId = adjustment?.preset_id || null;
228
- // Check if preset exists in our presets list
229
177
  const matchingPreset = presetId ? presets.find(p => p.id === presetId) : null;
230
- // Check if the adjustment values actually match the preset values
231
178
  let hasValidMatchingPreset = false;
232
179
  if (matchingPreset && adjustment) {
233
180
  const presetAdjustments = presetToAdjustmentState(matchingPreset);
@@ -241,194 +188,80 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
241
188
  adjustmentValues: adjustment
242
189
  };
243
190
  });
244
- console.log('Debug preset calculation (with custom check):', {
245
- selectedIds,
246
- imageDetails: imageDetails.map(detail => ({
247
- imageId: detail.imageId,
248
- presetId: detail.presetId,
249
- presetName: detail.matchingPreset?.name || 'N/A',
250
- hasValidMatchingPreset: detail.hasValidMatchingPreset,
251
- isCustomAdjustment: detail.presetId && !detail.hasValidMatchingPreset
252
- }))
253
- });
254
- // Get images that have ACTUALLY matching presets (not just preset IDs)
255
191
  const imagesWithValidPresets = imageDetails.filter(detail => detail.hasValidMatchingPreset);
256
192
  const validPresetIds = imagesWithValidPresets.map(detail => detail.presetId);
257
193
  const uniqueValidPresetIds = new Set(validPresetIds);
258
- // Case 1: No images have actually matching presets
259
- // This includes: no preset_id, non-existent preset_id, or preset_id with modified values
260
194
  if (imagesWithValidPresets.length === 0) {
261
- console.log('Case 1: No images have valid matching presets - showing Select');
262
195
  return { activePreset: null, presetSummary: 'NO_SELECTION' };
263
196
  }
264
- // Case 2: Some images have valid matching presets, some don't (mixed state)
265
197
  if (imagesWithValidPresets.length > 0 && imagesWithValidPresets.length < selectedIds.length) {
266
- console.log('Case 2: Mixed preset state (some valid, some custom/none) - showing Multiple presets');
267
198
  return { activePreset: null, presetSummary: 'MULTIPLE_PRESETS' };
268
199
  }
269
- // Case 3: All images have valid matching presets, but different ones
270
200
  if (uniqueValidPresetIds.size > 1) {
271
- console.log('Case 3: Multiple different valid presets - showing Multiple presets');
272
201
  return { activePreset: null, presetSummary: 'MULTIPLE_PRESETS' };
273
202
  }
274
- // Case 4: All images have the same valid matching preset
275
203
  const singleValidPresetId = Array.from(uniqueValidPresetIds)[0];
276
204
  const matchingPreset = presets.find(p => p.id === singleValidPresetId);
277
205
  if (matchingPreset) {
278
- console.log('Case 4: All images have the same valid matching preset');
279
206
  return { activePreset: matchingPreset, presetSummary: 'SINGLE' };
280
207
  }
281
208
  else {
282
- // This shouldn't happen given our filtering above, but safety check
283
- console.log('Case 4 safety check failed - showing Select');
284
209
  return { activePreset: null, presetSummary: 'NO_SELECTION' };
285
210
  }
286
211
  }, [selectedIds, currentBatch.allImages, presets]);
287
- // Update selectedBulkPreset when activePreset changes
288
212
  useEffect(() => {
289
213
  const newPresetId = activePreset?.id || '';
290
214
  setSelectedBulkPreset(newPresetId);
291
- log.debug({
292
- activePreset: activePreset?.name || 'none',
293
- presetId: newPresetId,
294
- selectedImagesCount: selectedIds.length,
295
- triggerReason: 'activePreset changed'
296
- }, '[useHonchoEditorBulk] 🎨 Preset selection updated');
297
215
  }, [activePreset]);
298
- // Use loading states from usePaging instead of local state
299
- const isLoading = info.isLoading;
300
- const error = info.error;
301
- const hasMore = info.hasMore;
216
+ // FIX: Connect UI states directly to galleryHookData
217
+ const isLoading = galleryHookData.isLoading;
218
+ const error = null;
219
+ const hasMore = galleryHookData.hasMore;
302
220
  const imageData = useMemo(() => {
303
221
  const res = images.map(item => {
304
222
  const basePhoto = mapGalleryToPhotoData(item, selectedIds);
305
223
  const historyAdjustment = currentBatch.allImages[item.id];
306
- // **ADJUSTMENT PRIORITY LOGIC**
307
- // 1. History adjustments (from useAdjustmentHistoryBatch) - highest priority
308
- // These are the most current client-side changes that may not be saved to backend yet
309
- // 2. Backend adjustments (from paging data) - fallback
310
- // These come from the server and represent previously saved adjustments
311
- //
312
- // This ensures that when user makes adjustments in the UI, they are immediately
313
- // reflected in the gallery view even before they're synced to the backend.
314
224
  if (historyAdjustment) {
315
- // Use adjustments from history (most current client-side changes)
316
- // Convert AdjustmentState (from history) to AdjustmentValues (for UI)
317
225
  const adjustmentsValues = mapAdjustmentStateToAdjustmentEditor(historyAdjustment);
318
226
  basePhoto.adjustments = adjustmentsValues;
319
- log.debug({
320
- historyAdjustment,
321
- convertedValues: adjustmentsValues
322
- }, `[useHonchoEditorBulk] 📊 Image ${item.id} using HISTORY adjustments`);
323
- }
324
- else {
325
- // Fall back to backend adjustments if no history exists for this image
326
- // basePhoto.adjustments already contains backend data from mapGalleryToPhotoData
327
- log.debug({
328
- backendAdjustments: basePhoto.adjustments
329
- }, `[useHonchoEditorBulk] 📊 Image ${item.id} using BACKEND adjustments`);
330
227
  }
331
228
  return basePhoto;
332
229
  });
333
- log.debug({
334
- totalImages: res.length,
335
- imagesWithHistory: res.filter(img => currentBatch.allImages[img.key]).length,
336
- imagesWithBackendOnly: res.filter(img => !currentBatch.allImages[img.key] && img.adjustments).length,
337
- imagesWithNoAdjustments: res.filter(img => !currentBatch.allImages[img.key] && !img.adjustments).length
338
- }, '[useHonchoEditorBulk] 📊 ImageData construction summary');
339
230
  return res;
340
231
  }, [images, selectedIds, currentBatch.allImages]);
341
- // Convert imageData (PhotoData[]) to GallerySetup[] for AlbumImageGalleryInfinite
342
232
  const gallerySetupData = useMemo(() => {
343
- const result = imageData.map(mapPhotoDataToGallerySetup);
344
- log.debug({
345
- photoDataCount: imageData.length,
346
- gallerySetupCount: result.length,
347
- batchImageCount: Object.keys(currentBatch.allImages).length,
348
- samplePhotoData: imageData[0] ? {
349
- key: imageData[0].key,
350
- src: imageData[0].src,
351
- isSelected: imageData[0].isSelected,
352
- hasAdjustments: !!imageData[0].adjustments
353
- } : null,
354
- sampleGallerySetup: result[0] ? {
355
- key: result[0].key,
356
- src: result[0].src,
357
- isSelected: result[0].isSelected,
358
- hasAdjustments: !!result[0].adjustments,
359
- adjustmentsSource: currentBatch.allImages[result[0].key] ? 'history' : 'backend'
360
- } : null
361
- }, '[useHonchoEditorBulk] 🔄 Mapped PhotoData to GallerySetup');
362
- return result;
363
- }, [imageData, currentBatch.allImages]);
364
- // Store the latest batchActions functions in refs to avoid dependency issues
233
+ return imageData.map(mapPhotoDataToGallerySetup);
234
+ }, [imageData]);
365
235
  const syncAdjustmentRef = useRef(batchActions.syncAdjustment);
366
236
  const initializeFromPaginationRef = useRef(batchActions.initializeFromPagination);
367
237
  syncAdjustmentRef.current = batchActions.syncAdjustment;
368
238
  initializeFromPaginationRef.current = batchActions.initializeFromPagination;
369
- // Safe sync: Only sync new images to prevent infinite loops
370
239
  useEffect(() => {
371
- log.debug({
372
- imagesLength: images.length,
373
- imageIds: images.map(img => img.id),
374
- lastSyncedImageIds: Array.from(lastSyncedImageIds.current),
375
- lastSyncedCount: lastSyncedImageIds.current.size
376
- }, '[useHonchoEditorBulk] 🔄 Sync effect triggered');
377
240
  if (images.length === 0)
378
241
  return;
379
- // Check if we have new images that haven't been synced
380
242
  const currentImageIds = new Set(images.map(img => img.id));
381
243
  const hasNewImages = images.some(img => !lastSyncedImageIds.current.has(img.id));
382
- log.debug({
383
- currentImageIds: Array.from(currentImageIds),
384
- hasNewImages,
385
- newImages: images.filter(img => !lastSyncedImageIds.current.has(img.id)).map(img => img.id)
386
- }, '[useHonchoEditorBulk] 🔍 New images check');
387
244
  if (hasNewImages) {
388
245
  const newImagesOnly = images.filter(img => !lastSyncedImageIds.current.has(img.id));
389
- log.info({ imageCount: newImagesOnly.length }, '[useHonchoEditorBulk] 🔄 INITIALIZE: Initializing new images from pagination data');
390
- // ✅ FIX: Only pass the new images to the initializer so you don't overwrite the first 2 images!
391
246
  initializeFromPaginationRef.current(newImagesOnly.map(mapToImageAdjustmentConfig));
392
247
  lastSyncedImageIds.current = currentImageIds;
393
248
  }
394
- else {
395
- log.debug('[useHonchoEditorBulk] ✅ No new images, skipping initialization (history preserved)');
396
- }
397
- }, [images]); // Only depend on images, not batchActions
249
+ }, [images]);
398
250
  const clearSelection = useCallback(() => {
399
- log.info({
400
- currentlySelected: selectedIds.length,
401
- selectedImageIds: selectedIds
402
- }, '[useHonchoEditorBulk] Clearing all selections');
403
- // If there are selected images, toggle them off one by one
404
251
  if (selectedIds.length > 0) {
405
252
  selectedIds.forEach(imageId => {
406
253
  batchActions.toggleSelection(imageId);
407
254
  });
408
255
  }
409
- log.info('[useHonchoEditorBulk] All selections cleared');
410
256
  }, [selectedIds, batchActions]);
411
257
  const selectAllImages = useCallback(() => {
412
- log.info({
413
- totalImages: gallerySetupData.length,
414
- currentlySelected: selectedIds.length,
415
- availableImageIds: gallerySetupData.map(img => img.key)
416
- }, '[useHonchoEditorBulk] Selecting all images');
417
- // Get all image IDs from gallerySetupData
418
258
  const allImageIds = gallerySetupData.map(image => image.key);
419
- if (allImageIds.length === 0) {
420
- log.warn('[useHonchoEditorBulk] No images available to select');
259
+ if (allImageIds.length === 0)
421
260
  return;
422
- }
423
- // Find images that are not currently selected and select them
424
261
  const unselectedImages = allImageIds.filter(imageId => !selectedIds.includes(imageId));
425
262
  unselectedImages.forEach(imageId => {
426
263
  batchActions.toggleSelection(imageId);
427
264
  });
428
- log.info({
429
- selectedCount: allImageIds.length,
430
- newlySelected: unselectedImages.length
431
- }, '[useHonchoEditorBulk] All images selected');
432
265
  }, [gallerySetupData, selectedIds, batchActions]);
433
266
  const handleBackCallbackBulk = useCallback(() => {
434
267
  const lastSelectedId = selectedIds.length > 0 ? selectedIds[selectedIds.length - 1] : "";
@@ -436,57 +269,17 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
436
269
  }, [controller, firebaseUid, selectedIds]);
437
270
  const handleSelectBulkPreset = useCallback((presetId) => {
438
271
  setSelectedBulkPreset(presetId);
439
- log.info({
440
- presetId,
441
- selectedImages: selectedIds,
442
- imageCount: selectedIds.length,
443
- hasController: !!controller,
444
- hasFirebaseUid: !!firebaseUid
445
- }, '[useHonchoEditorBulk] 🎨 Preset selection attempt');
446
- if (!presetId) {
447
- log.warn('[useHonchoEditorBulk] ❌ No preset ID provided, skipping backend call');
448
- return;
449
- }
450
- if (selectedIds.length === 0) {
451
- log.warn('[useHonchoEditorBulk] ❌ No images selected, skipping backend call');
272
+ if (!presetId || selectedIds.length === 0)
452
273
  return;
453
- }
454
- log.info({
455
- presetId,
456
- selectedImages: selectedIds,
457
- imageCount: selectedIds.length
458
- }, '[useHonchoEditorBulk] 🎨 Applying preset to multiple images');
459
- // Find the preset
460
274
  const preset = presets.find(p => p.id === presetId);
461
- if (!preset) {
462
- log.error({ presetId }, '[useHonchoEditorBulk] ❌ Preset not found in presets list');
275
+ if (!preset)
463
276
  return;
464
- }
465
- // Convert preset to adjustment state
466
277
  const presetAdjustments = presetToAdjustmentState(preset);
467
- log.debug({ presetAdjustments }, '[useHonchoEditorBulk] 📤 Sending preset adjustments to controller for each image');
468
- log.debug('[useHonchoEditorBulk] 🔄 About to call batchActions.adjustSelectedWithPreset');
469
- // Apply preset directly to all selected images using the clean action
470
- // This will trigger backend calls for each selected image via adjustSelectedWithPreset
471
278
  batchActions.adjustSelectedWithPreset(presetAdjustments, preset.id);
472
- log.info('[useHonchoEditorBulk] Called batchActions.adjustSelectedWithPreset, backend calls should be triggered');
473
- }, [presets, selectedIds, batchActions, controller, firebaseUid]);
474
- // This factory creates functions that adjust a value for all selected images
279
+ }, [presets, selectedIds, batchActions]);
475
280
  const createRelativeAdjuster = useCallback((key, amount) => () => {
476
- log.debug({
477
- key,
478
- amount,
479
- selectedImages: selectedIds,
480
- imageCount: selectedIds.length
481
- }, `[useHonchoEditorBulk] 🎛️ Bulk ${key} adjustment`);
482
- log.debug('[useHonchoEditorBulk] 📤 Sending bulk adjustment to controller for each selected image');
483
- log.debug({ allImages: currentBatch.allImages }, "currentBatch.allImages before");
484
281
  batchActions.adjustSelected({ [key]: amount });
485
- // Debug after a short delay to see if the state changed
486
- setTimeout(() => {
487
- log.debug({ allImages: currentBatch.allImages }, "currentBatch.allImages after");
488
- }, 100);
489
- }, [batchActions, selectedIds, currentBatch.allImages]);
282
+ }, [batchActions]);
490
283
  const handleBulkTempDecreaseMax = createRelativeAdjuster('tempScore', -20);
491
284
  const handleBulkTempDecrease = createRelativeAdjuster('tempScore', -5);
492
285
  const handleBulkTempIncrease = createRelativeAdjuster('tempScore', 5);
@@ -538,14 +331,11 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
538
331
  return {
539
332
  imageData,
540
333
  isLoading,
541
- isLoadingMore: info.isLoadingMore,
334
+ isLoadingMore: galleryHookData.isLoadingMore, // ✅ FIX: Use galleryHookData
542
335
  error,
543
336
  selectedIds,
544
337
  hasMore,
545
- // loadMoreImages,
546
- // Gallery Handlers
547
338
  handleBackCallbackBulk,
548
- // Preset functionality
549
339
  presets,
550
340
  selectedBulkPreset,
551
341
  activePreset,
@@ -553,12 +343,10 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
553
343
  handleSelectBulkPreset,
554
344
  clearSelection,
555
345
  selectAllImages,
556
- // Preset creation handlers
557
- presetActions, // Expose preset actions for create/rename/delete
346
+ presetActions,
558
347
  handleToggleImageSelection: batchActions.toggleSelection,
559
- handleLoadMore: actions.loadMore,
560
- handleRefresh: actions.refresh,
561
- // Adjustment
348
+ handleLoadMore: async () => { galleryHookData.loadMore(); }, // ✅ FIX: Bridge to KMP Engine
349
+ handleRefresh: async () => { galleryHookData.reloadGallery(); }, // ✅ FIX: Bridge to KMP Engine
562
350
  handleBulkTempDecreaseMax,
563
351
  handleBulkTempDecrease,
564
352
  handleBulkTempIncrease,
@@ -575,7 +363,6 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
575
363
  handleBulkSaturationDecrease,
576
364
  handleBulkSaturationIncrease,
577
365
  handleBulkSaturationIncreaseMax,
578
- // Adjustment Light
579
366
  handleBulkExposureDecreaseMax,
580
367
  handleBulkExposureDecrease,
581
368
  handleBulkExposureIncrease,
@@ -600,7 +387,6 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
600
387
  handleBulkBlacksDecrease,
601
388
  handleBulkBlacksIncrease,
602
389
  handleBulkBlacksIncreaseMax,
603
- // Adjustment Details
604
390
  handleBulkClarityDecreaseMax,
605
391
  handleBulkClarityDecrease,
606
392
  handleBulkClarityIncrease,
@@ -609,12 +395,8 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
609
395
  handleBulkSharpnessDecrease,
610
396
  handleBulkSharpnessIncrease,
611
397
  handleBulkSharpnessIncreaseMax,
612
- // Adjustment History
613
398
  createRelativeAdjuster,
614
- // copy paste
615
- // copiedAdjustments,
616
399
  currentAdjustments,
617
- // History actions
618
400
  handleUndo: batchActions.undo,
619
401
  handleRedo: batchActions.redo,
620
402
  handleReset: batchActions.reset,
@@ -625,14 +407,13 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
625
407
  totalStates: state.totalStates,
626
408
  selectedCount: state.selectedCount,
627
409
  totalImages: state.totalImages,
628
- historySize: state.historySize
410
+ historySize: state.historySize,
411
+ isReady: state.isReady ?? true, // ✅ FIX: Added missing isReady boolean
629
412
  },
630
- // Socket updates
631
413
  updateFromSocket: batchActions.updateFromSocket,
632
414
  adjustSelected: batchActions.adjustSelected,
633
415
  adjustSelectedWithPreset: batchActions.adjustSelectedWithPreset,
634
416
  adjustSelectedWithPaste: batchActions.adjustSelectedWithPaste,
635
- // Gallery setup data for AlbumImageGalleryInfinite
636
417
  gallerySetupData,
637
418
  readyState,
638
419
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yogiswara/honcho-editor-ui",
3
- "version": "3.9.1",
3
+ "version": "3.9.2",
4
4
  "description": "A complete UI component library for the Honcho photo editor.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",