@yogiswara/honcho-editor-ui 3.8.5 → 3.9.1
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.
|
@@ -385,8 +385,10 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
385
385
|
newImages: images.filter(img => !lastSyncedImageIds.current.has(img.id)).map(img => img.id)
|
|
386
386
|
}, '[useHonchoEditorBulk] 🔍 New images check');
|
|
387
387
|
if (hasNewImages) {
|
|
388
|
-
|
|
389
|
-
|
|
388
|
+
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
|
+
initializeFromPaginationRef.current(newImagesOnly.map(mapToImageAdjustmentConfig));
|
|
390
392
|
lastSyncedImageIds.current = currentImageIds;
|
|
391
393
|
}
|
|
392
394
|
else {
|
|
@@ -17,6 +17,8 @@ export interface UseHonchoEditorSingleState {
|
|
|
17
17
|
canRedo: boolean;
|
|
18
18
|
isNextAvailable: boolean;
|
|
19
19
|
isPrevAvailable: boolean;
|
|
20
|
+
imageList: Gallery[];
|
|
21
|
+
currentIndex: number;
|
|
20
22
|
presets: Preset[];
|
|
21
23
|
activePreset: Preset | null;
|
|
22
24
|
presetsLoading: boolean;
|
|
@@ -43,6 +45,9 @@ export interface UseHonchoEditorSingleState {
|
|
|
43
45
|
export interface UseHonchoEditorSingleActions {
|
|
44
46
|
navigateNext: () => void;
|
|
45
47
|
navigatePrev: () => void;
|
|
48
|
+
navigateToIndex: (index: number) => void;
|
|
49
|
+
removeImageFromList: (imageId: string) => Promise<void>;
|
|
50
|
+
refreshAndGoToTop: () => Promise<void>;
|
|
46
51
|
updateAdjustment: (field: keyof AdjustmentState, value: number) => void;
|
|
47
52
|
setBatchMode: (enabled: boolean) => void;
|
|
48
53
|
startBatchMode: () => void;
|
|
@@ -41,6 +41,15 @@ export function useHonchoEditorSingle({ controller, initImageId, firebaseUid })
|
|
|
41
41
|
gallerySwipe.onSwipePrev();
|
|
42
42
|
}
|
|
43
43
|
}, [gallerySwipe.isPrevAvailable, gallerySwipe.onSwipePrev]);
|
|
44
|
+
const navigateToIndex = useCallback((index) => {
|
|
45
|
+
gallerySwipe.onSwipeToIndex(index);
|
|
46
|
+
}, [gallerySwipe.onSwipeToIndex]);
|
|
47
|
+
const removeImageFromList = useCallback(async (imageId) => {
|
|
48
|
+
await gallerySwipe.removeImageFromList(imageId);
|
|
49
|
+
}, [gallerySwipe.removeImageFromList]);
|
|
50
|
+
const refreshAndGoToTop = useCallback(async () => {
|
|
51
|
+
await gallerySwipe.refreshAndGoToTop();
|
|
52
|
+
}, [gallerySwipe.refreshAndGoToTop]);
|
|
44
53
|
const updateAdjustment = useCallback((field, value) => {
|
|
45
54
|
// Apply specific clamping for sharpness (0-100), others use -100 to 100
|
|
46
55
|
let clampedValue = value;
|
|
@@ -108,7 +117,6 @@ export function useHonchoEditorSingle({ controller, initImageId, firebaseUid })
|
|
|
108
117
|
};
|
|
109
118
|
log.debug({ presetName: preset.name }, `Applying preset:`);
|
|
110
119
|
log.debug({ adjustmentState }, `with adjustments:`);
|
|
111
|
-
// 'with adjustments:', adjustmentState);
|
|
112
120
|
// Always apply preset and add to history (this automatically syncs to backend via batch mode)
|
|
113
121
|
await adjustmentHistory.config.setBatchMode(true);
|
|
114
122
|
adjustmentHistory.actions.pushState(adjustmentState);
|
|
@@ -173,6 +181,9 @@ export function useHonchoEditorSingle({ controller, initImageId, firebaseUid })
|
|
|
173
181
|
// Navigation
|
|
174
182
|
navigateNext,
|
|
175
183
|
navigatePrev,
|
|
184
|
+
navigateToIndex,
|
|
185
|
+
removeImageFromList,
|
|
186
|
+
refreshAndGoToTop,
|
|
176
187
|
// Adjustments
|
|
177
188
|
updateAdjustment,
|
|
178
189
|
setBatchMode,
|
|
@@ -199,6 +210,8 @@ export function useHonchoEditorSingle({ controller, initImageId, firebaseUid })
|
|
|
199
210
|
currentImageData: gallerySwipe.currentImageData,
|
|
200
211
|
isGalleryLoading: gallerySwipe.isLoading,
|
|
201
212
|
galleryError: gallerySwipe.error,
|
|
213
|
+
imageList: gallerySwipe.imageList,
|
|
214
|
+
currentIndex: gallerySwipe.currentIndex,
|
|
202
215
|
// Adjustment state
|
|
203
216
|
currentAdjustments: adjustmentHistory.currentState,
|
|
204
217
|
isBatchMode: adjustmentHistory.historyInfo.isBatchMode,
|
|
@@ -23,6 +23,11 @@ interface UseGallerySwipeReturn {
|
|
|
23
23
|
isReady: boolean;
|
|
24
24
|
/** Indicates if there was an error during initialization */
|
|
25
25
|
hasError: boolean;
|
|
26
|
+
imageList: Gallery[];
|
|
27
|
+
currentIndex: number;
|
|
28
|
+
onSwipeToIndex: (index: number) => Promise<void>;
|
|
29
|
+
removeImageFromList: (imageId: string) => Promise<void>;
|
|
30
|
+
refreshAndGoToTop: () => Promise<void>;
|
|
26
31
|
}
|
|
27
32
|
/**
|
|
28
33
|
* Custom hook for handling image gallery navigation with automatic pagination
|
|
@@ -29,6 +29,11 @@ export function useGallerySwipe(firebaseUid, initImageId, controller) {
|
|
|
29
29
|
// This prevents the hook from re-initializing when the same values are passed
|
|
30
30
|
const prevFirebaseUid = useRef(null);
|
|
31
31
|
const prevInitImageId = useRef(null);
|
|
32
|
+
const currentImageListRef = useRef([]);
|
|
33
|
+
const currentImageIdRef = useRef(null);
|
|
34
|
+
// Keep refs in sync with state
|
|
35
|
+
useEffect(() => { currentImageListRef.current = currentImageList; }, [currentImageList]);
|
|
36
|
+
useEffect(() => { currentImageIdRef.current = currentImageId; }, [currentImageId]);
|
|
32
37
|
/**
|
|
33
38
|
* Get the index of the current image in the loaded image list
|
|
34
39
|
* Returns -1 if the current image is not found in the list
|
|
@@ -283,6 +288,94 @@ export function useGallerySwipe(firebaseUid, initImageId, controller) {
|
|
|
283
288
|
setIsLoading(false);
|
|
284
289
|
}
|
|
285
290
|
}, [currentImageId, isLoading, getCurrentImageIndex, currentImageList, controller, firebaseUid]);
|
|
291
|
+
const onSwipeToIndex = useCallback(async (index) => {
|
|
292
|
+
if (isLoading || index < 0 || index >= currentImageList.length)
|
|
293
|
+
return;
|
|
294
|
+
setIsLoading(true);
|
|
295
|
+
setError(null);
|
|
296
|
+
try {
|
|
297
|
+
const targetImage = currentImageList[index];
|
|
298
|
+
setCurrentImageId(targetImage.id);
|
|
299
|
+
const imageData = await controller.onGetImage(firebaseUid, targetImage.id);
|
|
300
|
+
if (imageData) {
|
|
301
|
+
setCurrentImageData(imageData);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
catch (err) {
|
|
305
|
+
const errorMessage = err instanceof Error ? err.message : 'Error navigating to index';
|
|
306
|
+
setError(errorMessage);
|
|
307
|
+
log.error({ err }, 'Error in onSwipeToIndex');
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
setIsLoading(false);
|
|
311
|
+
}
|
|
312
|
+
}, [isLoading, currentImageList, controller, firebaseUid]);
|
|
313
|
+
const removeImageFromList = useCallback(async (imageId) => {
|
|
314
|
+
const list = currentImageListRef.current; // ← always fresh
|
|
315
|
+
const currentId = currentImageIdRef.current; // ← always fresh
|
|
316
|
+
const indexToRemove = list.findIndex(img => img.id === imageId);
|
|
317
|
+
if (indexToRemove === -1)
|
|
318
|
+
return;
|
|
319
|
+
const newList = list.filter(img => img.id !== imageId);
|
|
320
|
+
setCurrentImageList(newList);
|
|
321
|
+
// Only navigate if the removed image was the one being viewed
|
|
322
|
+
if (imageId !== currentId)
|
|
323
|
+
return;
|
|
324
|
+
if (newList.length === 0) {
|
|
325
|
+
setCurrentImageData(null);
|
|
326
|
+
setCurrentImageId(null);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const nextIndex = Math.min(indexToRemove, newList.length - 1);
|
|
330
|
+
const nextImage = newList[nextIndex];
|
|
331
|
+
setIsLoading(true);
|
|
332
|
+
try {
|
|
333
|
+
setCurrentImageId(nextImage.id);
|
|
334
|
+
const nextImageData = await controller.onGetImage(firebaseUid, nextImage.id);
|
|
335
|
+
if (nextImageData)
|
|
336
|
+
setCurrentImageData(nextImageData);
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
log.error({ err }, 'Error fetching next image after removal');
|
|
340
|
+
}
|
|
341
|
+
finally {
|
|
342
|
+
setIsLoading(false);
|
|
343
|
+
}
|
|
344
|
+
}, [controller, firebaseUid]);
|
|
345
|
+
const refreshAndGoToTop = useCallback(async () => {
|
|
346
|
+
if (!firebaseUid || !controller || !currentEventId)
|
|
347
|
+
return;
|
|
348
|
+
setIsLoading(true);
|
|
349
|
+
setError(null);
|
|
350
|
+
try {
|
|
351
|
+
// Fetch the brand new Page 1 with the latest sorting rules applied
|
|
352
|
+
const response = await controller.getImageList(firebaseUid, currentEventId, 1, 20);
|
|
353
|
+
if (response.gallery && response.gallery.length > 0) {
|
|
354
|
+
setCurrentImageList(response.gallery);
|
|
355
|
+
setCurrentPage(1);
|
|
356
|
+
setHasNextPage(response.next_page !== 0 && response.next_page > response.current_page);
|
|
357
|
+
// Grab the true top image
|
|
358
|
+
const firstImage = response.gallery[0];
|
|
359
|
+
setCurrentImageId(firstImage.id);
|
|
360
|
+
const imageData = await controller.onGetImage(firebaseUid, firstImage.id);
|
|
361
|
+
if (imageData) {
|
|
362
|
+
setCurrentImageData(imageData);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
setCurrentImageList([]);
|
|
367
|
+
setCurrentImageData(null);
|
|
368
|
+
setCurrentImageId(null);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
catch (err) {
|
|
372
|
+
setError(err instanceof Error ? err.message : 'Error refreshing list');
|
|
373
|
+
log.error({ err }, 'Error in refreshAndGoToTop');
|
|
374
|
+
}
|
|
375
|
+
finally {
|
|
376
|
+
setIsLoading(false);
|
|
377
|
+
}
|
|
378
|
+
}, [controller, firebaseUid, currentEventId]);
|
|
286
379
|
/**
|
|
287
380
|
* Calculate if next image navigation is available
|
|
288
381
|
* Returns true if:
|
|
@@ -343,6 +436,11 @@ export function useGallerySwipe(firebaseUid, initImageId, controller) {
|
|
|
343
436
|
isPrevAvailable: isPrevAvailable(),
|
|
344
437
|
onSwipeNext,
|
|
345
438
|
onSwipePrev,
|
|
439
|
+
onSwipeToIndex,
|
|
440
|
+
removeImageFromList,
|
|
441
|
+
refreshAndGoToTop,
|
|
442
|
+
imageList: currentImageList,
|
|
443
|
+
currentIndex: getCurrentImageIndex(),
|
|
346
444
|
isLoading,
|
|
347
445
|
error,
|
|
348
446
|
isReady: isInitialized && currentImageData !== null && !isLoading,
|