@yogiswara/honcho-editor-ui 3.8.6 → 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.
@@ -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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yogiswara/honcho-editor-ui",
3
- "version": "3.8.6",
3
+ "version": "3.9.1",
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",