@yogiswara/honcho-editor-ui 2.7.13 → 2.7.14
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/package.json +1 -1
- package/dist/color.d.ts +0 -9
- package/dist/color.js +0 -9
- package/dist/components/editor/GalleryAlbum/AlbumImageGallery.d.ts +0 -8
- package/dist/components/editor/GalleryAlbum/AlbumImageGallery.js +0 -28
- package/dist/components/editor/GalleryAlbum/ImageItem.d.ts +0 -10
- package/dist/components/editor/GalleryAlbum/ImageItem.js +0 -81
- package/dist/components/editor/HAccordionAspectRatio.d.ts +0 -14
- package/dist/components/editor/HAccordionAspectRatio.js +0 -102
- package/dist/components/editor/HAccordionColor.d.ts +0 -16
- package/dist/components/editor/HAccordionColor.js +0 -282
- package/dist/components/editor/HAccordionColorAdjustment.d.ts +0 -35
- package/dist/components/editor/HAccordionColorAdjustment.js +0 -31
- package/dist/components/editor/HAccordionDetails.d.ts +0 -12
- package/dist/components/editor/HAccordionDetails.js +0 -157
- package/dist/components/editor/HAccordionLight.d.ts +0 -20
- package/dist/components/editor/HAccordionLight.js +0 -414
- package/dist/components/editor/HAccordionPreset.d.ts +0 -23
- package/dist/components/editor/HAccordionPreset.js +0 -50
- package/dist/components/editor/HAlertBox.d.ts +0 -8
- package/dist/components/editor/HAlertBox.js +0 -55
- package/dist/components/editor/HAspectRatioMobile.d.ts +0 -0
- package/dist/components/editor/HAspectRatioMobile.js +0 -1
- package/dist/components/editor/HBulkAccordionColorAdjustment.d.ts +0 -55
- package/dist/components/editor/HBulkAccordionColorAdjustment.js +0 -31
- package/dist/components/editor/HBulkAccordionColorAdjustmentColors.d.ts +0 -20
- package/dist/components/editor/HBulkAccordionColorAdjustmentColors.js +0 -121
- package/dist/components/editor/HBulkAccordionColorAdjustmentDetails.d.ts +0 -12
- package/dist/components/editor/HBulkAccordionColorAdjustmentDetails.js +0 -65
- package/dist/components/editor/HBulkAccordionColorAdjustmentLight.d.ts +0 -28
- package/dist/components/editor/HBulkAccordionColorAdjustmentLight.js +0 -177
- package/dist/components/editor/HBulkColorAdjustmentMobile.d.ts +0 -53
- package/dist/components/editor/HBulkColorAdjustmentMobile.js +0 -16
- package/dist/components/editor/HBulkColorMobile.d.ts +0 -20
- package/dist/components/editor/HBulkColorMobile.js +0 -121
- package/dist/components/editor/HBulkDetailsMobile.d.ts +0 -12
- package/dist/components/editor/HBulkDetailsMobile.js +0 -65
- package/dist/components/editor/HBulkLightMobile.d.ts +0 -28
- package/dist/components/editor/HBulkLightMobile.js +0 -192
- package/dist/components/editor/HBulkPreset.d.ts +0 -24
- package/dist/components/editor/HBulkPreset.js +0 -43
- package/dist/components/editor/HBulkPresetMobile.d.ts +0 -15
- package/dist/components/editor/HBulkPresetMobile.js +0 -26
- package/dist/components/editor/HDialogBox.d.ts +0 -18
- package/dist/components/editor/HDialogBox.js +0 -51
- package/dist/components/editor/HDialogCopy.d.ts +0 -40
- package/dist/components/editor/HDialogCopy.js +0 -80
- package/dist/components/editor/HFooter.d.ts +0 -12
- package/dist/components/editor/HFooter.js +0 -24
- package/dist/components/editor/HHeaderEditor.d.ts +0 -17
- package/dist/components/editor/HHeaderEditor.js +0 -36
- package/dist/components/editor/HImageEditorBulkDekstop.d.ts +0 -15
- package/dist/components/editor/HImageEditorBulkDekstop.js +0 -29
- package/dist/components/editor/HImageEditorBulkMobile.d.ts +0 -72
- package/dist/components/editor/HImageEditorBulkMobile.js +0 -81
- package/dist/components/editor/HImageEditorDekstop.d.ts +0 -15
- package/dist/components/editor/HImageEditorDekstop.js +0 -29
- package/dist/components/editor/HImageEditorMobile.d.ts +0 -51
- package/dist/components/editor/HImageEditorMobile.js +0 -92
- package/dist/components/editor/HImageEditorMobileLayout.d.ts +0 -14
- package/dist/components/editor/HImageEditorMobileLayout.js +0 -58
- package/dist/components/editor/HModalEditorDekstop.d.ts +0 -13
- package/dist/components/editor/HModalEditorDekstop.js +0 -22
- package/dist/components/editor/HModalMobile.d.ts +0 -13
- package/dist/components/editor/HModalMobile.js +0 -7
- package/dist/components/editor/HPresetDelete.d.ts +0 -7
- package/dist/components/editor/HPresetDelete.js +0 -7
- package/dist/components/editor/HPresetOptionMenu.d.ts +0 -9
- package/dist/components/editor/HPresetOptionMenu.js +0 -20
- package/dist/components/editor/HSliderColorMobile.d.ts +0 -16
- package/dist/components/editor/HSliderColorMobile.js +0 -270
- package/dist/components/editor/HSliderDetailsMobile.d.ts +0 -12
- package/dist/components/editor/HSliderDetailsMobile.js +0 -154
- package/dist/components/editor/HSliderLightMobile.d.ts +0 -20
- package/dist/components/editor/HSliderLightMobile.js +0 -420
- package/dist/components/editor/HTabAspectRatioMobile.d.ts +0 -0
- package/dist/components/editor/HTabAspectRatioMobile.js +0 -1
- package/dist/components/editor/HTabColorAdjustmentMobile.d.ts +0 -33
- package/dist/components/editor/HTabColorAdjustmentMobile.js +0 -16
- package/dist/components/editor/HTabPresetMobile.d.ts +0 -14
- package/dist/components/editor/HTabPresetMobile.js +0 -10
- package/dist/components/editor/HTextField.d.ts +0 -14
- package/dist/components/editor/HTextField.js +0 -51
- package/dist/components/editor/HWatermarkView.d.ts +0 -6
- package/dist/components/editor/HWatermarkView.js +0 -16
- package/dist/components/editor/svg/Tick.d.ts +0 -2
- package/dist/components/editor/svg/Tick.js +0 -6
- package/dist/components/modal/HModalDialog.d.ts +0 -12
- package/dist/components/modal/HModalDialog.js +0 -18
- package/dist/components/modal/HModalRename.d.ts +0 -14
- package/dist/components/modal/HModalRename.js +0 -35
- package/dist/hooks/demo/HonchoEditorBulkDemo.d.ts +0 -3
- package/dist/hooks/demo/HonchoEditorBulkDemo.js +0 -410
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.d.ts +0 -3
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.js +0 -354
- package/dist/hooks/demo/index.d.ts +0 -2
- package/dist/hooks/demo/index.js +0 -2
- package/dist/hooks/editor/type.d.ts +0 -174
- package/dist/hooks/editor/type.js +0 -1
- package/dist/hooks/editor/useHonchoEditorBulk.d.ts +0 -96
- package/dist/hooks/editor/useHonchoEditorBulk.js +0 -427
- package/dist/hooks/editor/useHonchoEditorSingle.d.ts +0 -44
- package/dist/hooks/editor/useHonchoEditorSingle.js +0 -162
- package/dist/hooks/useAdjustmentHistory.d.ts +0 -97
- package/dist/hooks/useAdjustmentHistory.js +0 -493
- package/dist/hooks/useAdjustmentHistoryBatch.d.ts +0 -177
- package/dist/hooks/useAdjustmentHistoryBatch.js +0 -1189
- package/dist/hooks/useGallerySwipe.d.ts +0 -36
- package/dist/hooks/useGallerySwipe.js +0 -344
- package/dist/hooks/usePaging.d.ts +0 -89
- package/dist/hooks/usePaging.js +0 -211
- package/dist/hooks/usePreset.d.ts +0 -82
- package/dist/hooks/usePreset.js +0 -344
- package/dist/index.d.ts +0 -41
- package/dist/index.js +0 -44
- package/dist/lib/context/EditorContext.d.ts +0 -28
- package/dist/lib/context/EditorContext.js +0 -60
- package/dist/lib/context/EditorProcessingService.d.ts +0 -36
- package/dist/lib/context/EditorProcessingService.js +0 -249
- package/dist/lib/editor/honcho-editor.d.ts +0 -324
- package/dist/lib/editor/honcho-editor.js +0 -825
- package/dist/lib/hooks/useEditor.d.ts +0 -22
- package/dist/lib/hooks/useEditor.js +0 -35
- package/dist/lib/hooks/useEditorHeadless.d.ts +0 -34
- package/dist/lib/hooks/useEditorHeadless.js +0 -207
- package/dist/lib/hooks/useImageProcessor.d.ts +0 -18
- package/dist/lib/hooks/useImageProcessor.js +0 -113
- package/dist/setupTests.d.ts +0 -1
- package/dist/setupTests.js +0 -1
- package/dist/themes/colors.d.ts +0 -12
- package/dist/themes/colors.js +0 -12
- package/dist/themes/honchoTheme.d.ts +0 -25
- package/dist/themes/honchoTheme.js +0 -94
- package/dist/utils/adjustment.d.ts +0 -6
- package/dist/utils/adjustment.js +0 -48
- package/dist/utils/imageLoader.d.ts +0 -11
- package/dist/utils/imageLoader.js +0 -48
- package/dist/utils/isMobile.d.ts +0 -1
- package/dist/utils/isMobile.js +0 -5
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { AdjustmentState, Controller } from './editor/type';
|
|
2
|
-
/**
|
|
3
|
-
* Configuration options for the adjustment history hook
|
|
4
|
-
*/
|
|
5
|
-
export interface HistoryOptions {
|
|
6
|
-
/** Maximum number of history entries to keep. Use 'unlimited' for no limit */
|
|
7
|
-
maxSize?: number | 'unlimited';
|
|
8
|
-
/** Whether to enable batch mode for grouping multiple changes */
|
|
9
|
-
enableBatching?: boolean;
|
|
10
|
-
/** Enable development warnings for performance issues */
|
|
11
|
-
devWarnings?: boolean;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Information about the current history state
|
|
15
|
-
*/
|
|
16
|
-
export interface HistoryInfo {
|
|
17
|
-
/** Whether undo operation is available */
|
|
18
|
-
canUndo: boolean;
|
|
19
|
-
/** Whether redo operation is available */
|
|
20
|
-
canRedo: boolean;
|
|
21
|
-
/** Current position in history (0-based index) */
|
|
22
|
-
currentIndex: number;
|
|
23
|
-
/** Total number of states in history */
|
|
24
|
-
totalStates: number;
|
|
25
|
-
/** Current size of history in memory */
|
|
26
|
-
historySize: number;
|
|
27
|
-
/** Whether batch mode is currently active */
|
|
28
|
-
isBatchMode: boolean;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Actions available for history management
|
|
32
|
-
*/
|
|
33
|
-
export interface HistoryActions {
|
|
34
|
-
/** Add a new adjustment state to history */
|
|
35
|
-
pushState: (state: AdjustmentState) => void;
|
|
36
|
-
/** Undo to previous adjustment state */
|
|
37
|
-
undo: () => void;
|
|
38
|
-
/** Redo to next adjustment state */
|
|
39
|
-
redo: () => void;
|
|
40
|
-
/** Reset history with new initial adjustment state */
|
|
41
|
-
reset: (newInitialState: AdjustmentState) => void;
|
|
42
|
-
/** Jump to specific index in history */
|
|
43
|
-
jumpToIndex: (index: number) => void;
|
|
44
|
-
/** Clear all history and start fresh */
|
|
45
|
-
clearHistory: () => void;
|
|
46
|
-
/** Get a copy of the entire history array */
|
|
47
|
-
getHistory: () => AdjustmentState[];
|
|
48
|
-
/** Trim history to specified size, keeping most recent entries */
|
|
49
|
-
trimHistory: (keepLast: number) => void;
|
|
50
|
-
/** Replace entire history with new list of adjustment states */
|
|
51
|
-
syncHistory: (newHistory: AdjustmentState[], targetIndex?: number) => void;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Configuration actions for runtime adjustment
|
|
55
|
-
*/
|
|
56
|
-
export interface HistoryConfig {
|
|
57
|
-
/** Set maximum history size */
|
|
58
|
-
setMaxSize: (size: number | 'unlimited') => void;
|
|
59
|
-
/** Enable or disable batch mode */
|
|
60
|
-
setBatchMode: (enabled: boolean) => Promise<void>;
|
|
61
|
-
/** Get current memory usage estimate */
|
|
62
|
-
getMemoryUsage: () => number;
|
|
63
|
-
/** Force sync current state to backend */
|
|
64
|
-
syncToBackend: () => Promise<void>;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Return type for the useAdjustmentHistory hook
|
|
68
|
-
*/
|
|
69
|
-
export interface UseAdjustmentHistoryReturn {
|
|
70
|
-
/** Current adjustment state value */
|
|
71
|
-
currentState: AdjustmentState;
|
|
72
|
-
/** Information about history state */
|
|
73
|
-
historyInfo: HistoryInfo;
|
|
74
|
-
/** Available history actions */
|
|
75
|
-
actions: HistoryActions;
|
|
76
|
-
/** Configuration options */
|
|
77
|
-
config: HistoryConfig;
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Advanced hook for managing AdjustmentState history with undo/redo functionality.
|
|
81
|
-
*
|
|
82
|
-
* Features:
|
|
83
|
-
* - Unlimited or configurable history size
|
|
84
|
-
* - Batch mode for grouping multiple changes into single undo operations
|
|
85
|
-
* - Memory usage monitoring and optimization
|
|
86
|
-
* - Internal stabilization to prevent re-render issues
|
|
87
|
-
* - Jump to any point in history
|
|
88
|
-
* - Automatic AdjustmentState comparison
|
|
89
|
-
*
|
|
90
|
-
* @param initialState - The initial AdjustmentState value
|
|
91
|
-
* @param controller - Controller for backend operations (optional)
|
|
92
|
-
* @param firebaseUid - Firebase UID for backend operations (optional)
|
|
93
|
-
* @param currentImageId - Current image ID for backend operations (optional)
|
|
94
|
-
* @param options - Configuration options for history behavior
|
|
95
|
-
* @returns Object with current state, history info, actions, and config
|
|
96
|
-
*/
|
|
97
|
-
export declare function useAdjustmentHistory(initialState: AdjustmentState, controller?: Controller, firebaseUid?: string, currentImageId?: string, options?: HistoryOptions): UseAdjustmentHistoryReturn;
|
|
@@ -1,493 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback, useMemo, useRef, useEffect } from 'react';
|
|
2
|
-
/**
|
|
3
|
-
* Convert AdjustmentState to ColorAdjustment format for backend
|
|
4
|
-
*/
|
|
5
|
-
const convertAdjustmentStateToColorAdjustment = (adjustmentState) => {
|
|
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,
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Compare two AdjustmentState objects for equality
|
|
23
|
-
* Uses JSON.stringify for deep comparison of all adjustment values
|
|
24
|
-
*/
|
|
25
|
-
const compareAdjustmentStates = (a, b) => {
|
|
26
|
-
try {
|
|
27
|
-
return JSON.stringify(a) === JSON.stringify(b);
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
// Fallback to manual comparison if JSON.stringify fails
|
|
31
|
-
console.warn('Failed to compare adjustment states with JSON.stringify, falling back to manual comparison:', error);
|
|
32
|
-
return (a.tempScore === b.tempScore &&
|
|
33
|
-
a.tintScore === b.tintScore &&
|
|
34
|
-
a.vibranceScore === b.vibranceScore &&
|
|
35
|
-
a.saturationScore === b.saturationScore &&
|
|
36
|
-
a.exposureScore === b.exposureScore &&
|
|
37
|
-
a.highlightsScore === b.highlightsScore &&
|
|
38
|
-
a.shadowsScore === b.shadowsScore &&
|
|
39
|
-
a.whitesScore === b.whitesScore &&
|
|
40
|
-
a.blacksScore === b.blacksScore &&
|
|
41
|
-
a.contrastScore === b.contrastScore &&
|
|
42
|
-
a.clarityScore === b.clarityScore &&
|
|
43
|
-
a.sharpnessScore === b.sharpnessScore);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
/**
|
|
47
|
-
* Advanced hook for managing AdjustmentState history with undo/redo functionality.
|
|
48
|
-
*
|
|
49
|
-
* Features:
|
|
50
|
-
* - Unlimited or configurable history size
|
|
51
|
-
* - Batch mode for grouping multiple changes into single undo operations
|
|
52
|
-
* - Memory usage monitoring and optimization
|
|
53
|
-
* - Internal stabilization to prevent re-render issues
|
|
54
|
-
* - Jump to any point in history
|
|
55
|
-
* - Automatic AdjustmentState comparison
|
|
56
|
-
*
|
|
57
|
-
* @param initialState - The initial AdjustmentState value
|
|
58
|
-
* @param controller - Controller for backend operations (optional)
|
|
59
|
-
* @param firebaseUid - Firebase UID for backend operations (optional)
|
|
60
|
-
* @param currentImageId - Current image ID for backend operations (optional)
|
|
61
|
-
* @param options - Configuration options for history behavior
|
|
62
|
-
* @returns Object with current state, history info, actions, and config
|
|
63
|
-
*/
|
|
64
|
-
export function useAdjustmentHistory(initialState, controller, firebaseUid, currentImageId, options = {}) {
|
|
65
|
-
// Internal stabilization - prevent re-renders from options object recreation
|
|
66
|
-
const internalOptions = useMemo(() => ({
|
|
67
|
-
maxSize: options.maxSize ?? 'unlimited',
|
|
68
|
-
enableBatching: options.enableBatching ?? false,
|
|
69
|
-
devWarnings: options.devWarnings ?? false,
|
|
70
|
-
controller: controller,
|
|
71
|
-
firebaseUid: firebaseUid,
|
|
72
|
-
currentImageId: currentImageId
|
|
73
|
-
}), [
|
|
74
|
-
options.maxSize,
|
|
75
|
-
options.enableBatching,
|
|
76
|
-
options.devWarnings,
|
|
77
|
-
controller,
|
|
78
|
-
firebaseUid,
|
|
79
|
-
currentImageId
|
|
80
|
-
]);
|
|
81
|
-
// Core state management
|
|
82
|
-
const [history, setHistory] = useState([{ state: initialState }]);
|
|
83
|
-
const [currentIndex, setCurrentIndex] = useState(0);
|
|
84
|
-
const [currentState, setCurrentState] = useState(initialState);
|
|
85
|
-
// Batch mode state - ref to avoid triggering effects
|
|
86
|
-
const batchModeRef = useRef(internalOptions.enableBatching);
|
|
87
|
-
const batchStartIndexRef = useRef(null);
|
|
88
|
-
const batchStartStateRef = useRef(null);
|
|
89
|
-
const batchModeProcessingRef = useRef(false); // Guard against double execution
|
|
90
|
-
// Configuration refs - prevent re-renders when config changes
|
|
91
|
-
const maxSizeRef = useRef(internalOptions.maxSize);
|
|
92
|
-
const devWarningsRef = useRef(internalOptions.devWarnings);
|
|
93
|
-
// Performance monitoring
|
|
94
|
-
const performanceRef = useRef({
|
|
95
|
-
lastHistorySize: 1,
|
|
96
|
-
lastUpdateTime: Date.now(),
|
|
97
|
-
largeHistoryWarningShown: false
|
|
98
|
-
});
|
|
99
|
-
// Sync currentState with history when not in batch mode
|
|
100
|
-
useEffect(() => {
|
|
101
|
-
if (!batchModeRef.current) {
|
|
102
|
-
setCurrentState(history[currentIndex]?.state || initialState);
|
|
103
|
-
}
|
|
104
|
-
}, [history, currentIndex, initialState]);
|
|
105
|
-
const getMemoryUsage = useCallback(() => {
|
|
106
|
-
try {
|
|
107
|
-
const historyString = JSON.stringify(history);
|
|
108
|
-
return historyString.length * 2; // Rough estimate: 2 bytes per character
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
console.warn('Failed to estimate memory usage:', error);
|
|
112
|
-
return history.length * 1000; // Fallback estimate
|
|
113
|
-
}
|
|
114
|
-
}, [history]);
|
|
115
|
-
// Development warnings for performance
|
|
116
|
-
const checkPerformance = useCallback(() => {
|
|
117
|
-
if (!devWarningsRef.current)
|
|
118
|
-
return;
|
|
119
|
-
const now = Date.now();
|
|
120
|
-
const perfData = performanceRef.current;
|
|
121
|
-
// Warn about large history sizes
|
|
122
|
-
if (history.length > 1000 && !perfData.largeHistoryWarningShown) {
|
|
123
|
-
console.warn(`useAdjustmentHistory: Large history size detected (${history.length} entries). Consider setting a maxSize limit.`);
|
|
124
|
-
perfData.largeHistoryWarningShown = true;
|
|
125
|
-
}
|
|
126
|
-
// Update performance tracking
|
|
127
|
-
perfData.lastHistorySize = history.length;
|
|
128
|
-
perfData.lastUpdateTime = now;
|
|
129
|
-
}, [history.length]);
|
|
130
|
-
// Trim history to specified size, keeping most recent entries
|
|
131
|
-
const trimHistoryToSize = useCallback((size) => {
|
|
132
|
-
if (size <= 0)
|
|
133
|
-
return;
|
|
134
|
-
setHistory(prevHistory => {
|
|
135
|
-
if (prevHistory.length <= size)
|
|
136
|
-
return prevHistory;
|
|
137
|
-
const startIndex = Math.max(0, prevHistory.length - size);
|
|
138
|
-
const trimmedHistory = prevHistory.slice(startIndex);
|
|
139
|
-
// Adjust current index to maintain relative position
|
|
140
|
-
setCurrentIndex(prevIndex => {
|
|
141
|
-
const adjustedIndex = prevIndex - startIndex;
|
|
142
|
-
return Math.max(0, Math.min(adjustedIndex, trimmedHistory.length - 1));
|
|
143
|
-
});
|
|
144
|
-
return trimmedHistory;
|
|
145
|
-
});
|
|
146
|
-
}, []);
|
|
147
|
-
// Apply max size limit when history grows
|
|
148
|
-
const enforceMaxSize = useCallback(() => {
|
|
149
|
-
if (maxSizeRef.current === 'unlimited')
|
|
150
|
-
return;
|
|
151
|
-
const maxSize = maxSizeRef.current;
|
|
152
|
-
if (history.length > maxSize) {
|
|
153
|
-
trimHistoryToSize(maxSize);
|
|
154
|
-
}
|
|
155
|
-
}, [history.length, trimHistoryToSize]);
|
|
156
|
-
// Push new state to history
|
|
157
|
-
const pushState = useCallback((newState) => {
|
|
158
|
-
// Always update currentState immediately for smooth UI
|
|
159
|
-
setCurrentState(newState);
|
|
160
|
-
if (batchModeRef.current) {
|
|
161
|
-
// In batch mode: Don't update history yet, just update UI state
|
|
162
|
-
// History will be updated when batch mode ends
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
// Normal mode: Update history immediately
|
|
166
|
-
setHistory(prevHistory => {
|
|
167
|
-
const truncatedHistory = prevHistory.slice(0, currentIndex + 1);
|
|
168
|
-
const newHistory = [...truncatedHistory, { state: newState }];
|
|
169
|
-
setCurrentIndex(newHistory.length - 1);
|
|
170
|
-
return newHistory;
|
|
171
|
-
});
|
|
172
|
-
}, [currentState, currentIndex]);
|
|
173
|
-
// Undo to previous state
|
|
174
|
-
const undo = useCallback(async () => {
|
|
175
|
-
if (currentIndex > 0) {
|
|
176
|
-
const newIndex = currentIndex - 1;
|
|
177
|
-
const historyEntry = history[newIndex];
|
|
178
|
-
const newState = historyEntry.state;
|
|
179
|
-
setCurrentIndex(newIndex);
|
|
180
|
-
setCurrentState(newState);
|
|
181
|
-
// Call controller to set history index in backend if taskId exists
|
|
182
|
-
if (historyEntry.taskId && internalOptions.controller && internalOptions.firebaseUid && internalOptions.currentImageId) {
|
|
183
|
-
try {
|
|
184
|
-
console.log(`🔙 Undo: Setting history index to taskId: ${historyEntry.taskId}`);
|
|
185
|
-
await internalOptions.controller.setHistoryIndex(internalOptions.firebaseUid, internalOptions.currentImageId, historyEntry.taskId);
|
|
186
|
-
console.log('✅ Successfully set history index for undo');
|
|
187
|
-
}
|
|
188
|
-
catch (error) {
|
|
189
|
-
console.error('❌ Failed to set history index for undo:', error);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
// Exit batch mode when undoing
|
|
193
|
-
if (batchModeRef.current) {
|
|
194
|
-
batchModeRef.current = false;
|
|
195
|
-
batchStartIndexRef.current = null;
|
|
196
|
-
batchStartStateRef.current = null;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}, [currentIndex, history, internalOptions]);
|
|
200
|
-
// Redo to next state
|
|
201
|
-
const redo = useCallback(async () => {
|
|
202
|
-
if (currentIndex < history.length - 1) {
|
|
203
|
-
const newIndex = currentIndex + 1;
|
|
204
|
-
const historyEntry = history[newIndex];
|
|
205
|
-
const newState = historyEntry.state;
|
|
206
|
-
setCurrentIndex(newIndex);
|
|
207
|
-
setCurrentState(newState);
|
|
208
|
-
// Call controller to set history index in backend if taskId exists
|
|
209
|
-
if (historyEntry.taskId && internalOptions.controller && internalOptions.firebaseUid && internalOptions.currentImageId) {
|
|
210
|
-
try {
|
|
211
|
-
console.log(`🔄 Redo: Setting history index to taskId: ${historyEntry.taskId}`);
|
|
212
|
-
await internalOptions.controller.setHistoryIndex(internalOptions.firebaseUid, internalOptions.currentImageId, historyEntry.taskId);
|
|
213
|
-
console.log('✅ Successfully set history index for redo');
|
|
214
|
-
}
|
|
215
|
-
catch (error) {
|
|
216
|
-
console.error('❌ Failed to set history index for redo:', error);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}, [currentIndex, history, internalOptions]);
|
|
221
|
-
// Reset history with new initial state
|
|
222
|
-
const reset = useCallback((newInitialState) => {
|
|
223
|
-
setHistory([{ state: newInitialState }]);
|
|
224
|
-
setCurrentIndex(0);
|
|
225
|
-
setCurrentState(newInitialState);
|
|
226
|
-
batchModeRef.current = internalOptions.enableBatching;
|
|
227
|
-
batchStartIndexRef.current = null;
|
|
228
|
-
batchStartStateRef.current = null;
|
|
229
|
-
}, [internalOptions.enableBatching]);
|
|
230
|
-
// Jump to specific index in history
|
|
231
|
-
const jumpToIndex = useCallback((index) => {
|
|
232
|
-
if (index >= 0 && index < history.length) {
|
|
233
|
-
const historyEntry = history[index];
|
|
234
|
-
const newState = historyEntry.state;
|
|
235
|
-
setCurrentIndex(index);
|
|
236
|
-
setCurrentState(newState);
|
|
237
|
-
// Exit batch mode when jumping
|
|
238
|
-
if (batchModeRef.current) {
|
|
239
|
-
batchModeRef.current = false;
|
|
240
|
-
batchStartIndexRef.current = null;
|
|
241
|
-
batchStartStateRef.current = null;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}, [history]);
|
|
245
|
-
// Clear all history and start fresh
|
|
246
|
-
const clearHistory = useCallback(() => {
|
|
247
|
-
setHistory([{ state: currentState }]);
|
|
248
|
-
setCurrentIndex(0);
|
|
249
|
-
batchModeRef.current = internalOptions.enableBatching;
|
|
250
|
-
batchStartIndexRef.current = null;
|
|
251
|
-
batchStartStateRef.current = null;
|
|
252
|
-
}, [currentState, internalOptions.enableBatching]);
|
|
253
|
-
// Get copy of entire history
|
|
254
|
-
const getHistory = useCallback(() => {
|
|
255
|
-
return history.map(entry => entry.state);
|
|
256
|
-
}, [history]);
|
|
257
|
-
// Manually trim history
|
|
258
|
-
const trimHistory = useCallback((keepLast) => {
|
|
259
|
-
trimHistoryToSize(keepLast);
|
|
260
|
-
}, [trimHistoryToSize]);
|
|
261
|
-
// Sync/replace entire history with new list
|
|
262
|
-
const syncHistory = useCallback((newHistory, targetIndex) => {
|
|
263
|
-
// Validate input
|
|
264
|
-
if (!Array.isArray(newHistory) || newHistory.length === 0) {
|
|
265
|
-
console.warn('syncHistory: newHistory must be a non-empty array');
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
// Validate all items are AdjustmentState objects
|
|
269
|
-
const isValidHistory = newHistory.every(state => state && typeof state === 'object' &&
|
|
270
|
-
typeof state.tempScore === 'number' &&
|
|
271
|
-
typeof state.tintScore === 'number' &&
|
|
272
|
-
typeof state.vibranceScore === 'number' &&
|
|
273
|
-
typeof state.saturationScore === 'number' &&
|
|
274
|
-
typeof state.exposureScore === 'number' &&
|
|
275
|
-
typeof state.highlightsScore === 'number' &&
|
|
276
|
-
typeof state.shadowsScore === 'number' &&
|
|
277
|
-
typeof state.whitesScore === 'number' &&
|
|
278
|
-
typeof state.blacksScore === 'number' &&
|
|
279
|
-
typeof state.contrastScore === 'number' &&
|
|
280
|
-
typeof state.clarityScore === 'number' &&
|
|
281
|
-
typeof state.sharpnessScore === 'number');
|
|
282
|
-
if (!isValidHistory) {
|
|
283
|
-
console.warn('syncHistory: All items in newHistory must be valid AdjustmentState objects');
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
// Exit batch mode if active
|
|
287
|
-
if (batchModeRef.current) {
|
|
288
|
-
batchModeRef.current = false;
|
|
289
|
-
batchStartIndexRef.current = null;
|
|
290
|
-
batchStartStateRef.current = null;
|
|
291
|
-
}
|
|
292
|
-
// Determine target index
|
|
293
|
-
let finalIndex = targetIndex ?? newHistory.length - 1; // Default to last item
|
|
294
|
-
finalIndex = Math.max(0, Math.min(finalIndex, newHistory.length - 1)); // Clamp to valid range
|
|
295
|
-
// Create a copy of the new history to avoid mutations and convert to HistoryEntry format
|
|
296
|
-
const historyToSet = newHistory.map(state => ({ state: { ...state } }));
|
|
297
|
-
// Apply max size limit if needed
|
|
298
|
-
if (maxSizeRef.current !== 'unlimited' && historyToSet.length > maxSizeRef.current) {
|
|
299
|
-
const trimAmount = historyToSet.length - maxSizeRef.current;
|
|
300
|
-
const trimmedHistory = historyToSet.slice(trimAmount);
|
|
301
|
-
// Adjust target index
|
|
302
|
-
finalIndex = Math.max(0, finalIndex - trimAmount);
|
|
303
|
-
setHistory(trimmedHistory);
|
|
304
|
-
setCurrentIndex(finalIndex);
|
|
305
|
-
setCurrentState(trimmedHistory[finalIndex].state);
|
|
306
|
-
if (devWarningsRef.current) {
|
|
307
|
-
console.warn(`syncHistory: Trimmed ${trimAmount} entries to respect maxSize of ${maxSizeRef.current}`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
else {
|
|
311
|
-
// Set history as-is
|
|
312
|
-
setHistory(historyToSet);
|
|
313
|
-
setCurrentIndex(finalIndex);
|
|
314
|
-
setCurrentState(historyToSet[finalIndex].state);
|
|
315
|
-
}
|
|
316
|
-
if (devWarningsRef.current) {
|
|
317
|
-
console.log(`syncHistory: Synchronized ${historyToSet.length} states, current index: ${finalIndex}`);
|
|
318
|
-
}
|
|
319
|
-
}, []);
|
|
320
|
-
// Configuration setters
|
|
321
|
-
const setMaxSize = useCallback((size) => {
|
|
322
|
-
maxSizeRef.current = size;
|
|
323
|
-
if (size !== 'unlimited') {
|
|
324
|
-
enforceMaxSize();
|
|
325
|
-
}
|
|
326
|
-
}, [enforceMaxSize]);
|
|
327
|
-
const setBatchMode = useCallback(async (enabled) => {
|
|
328
|
-
const wasInBatch = batchModeRef.current;
|
|
329
|
-
console.log(`🔧 setBatchMode called: enabled=${enabled}, wasInBatch=${wasInBatch}, currentIndex=${currentIndex}, historyLength=${history.length}`);
|
|
330
|
-
if (enabled && !wasInBatch) {
|
|
331
|
-
// Starting batch mode - save current state as batch start
|
|
332
|
-
batchModeRef.current = true;
|
|
333
|
-
batchStartIndexRef.current = currentIndex;
|
|
334
|
-
batchStartStateRef.current = currentState;
|
|
335
|
-
console.log("Current start batch ", currentState, `batchStartIndex=${currentIndex}`);
|
|
336
|
-
}
|
|
337
|
-
else if (!enabled && wasInBatch) {
|
|
338
|
-
// Guard against double execution
|
|
339
|
-
if (batchModeProcessingRef.current) {
|
|
340
|
-
console.log("⚠️ setBatchMode(false) already processing, skipping duplicate call");
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
// Ending batch mode - commit final state to history
|
|
344
|
-
batchModeProcessingRef.current = true;
|
|
345
|
-
batchModeRef.current = false;
|
|
346
|
-
// Only add to history if state actually changed from batch start
|
|
347
|
-
if (batchStartStateRef.current &&
|
|
348
|
-
!compareAdjustmentStates(currentState, batchStartStateRef.current)) {
|
|
349
|
-
// Generate a unique task ID for this history entry
|
|
350
|
-
const taskId = `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
351
|
-
setHistory(prevHistory => {
|
|
352
|
-
// Check if we were in the middle of history BEFORE any truncation
|
|
353
|
-
// Handle case where batchStartIndexRef.current might be null (e.g., after undo)
|
|
354
|
-
const batchStartIndex = batchStartIndexRef.current ?? currentIndex;
|
|
355
|
-
const wasInMiddleOfHistory = batchStartIndex < prevHistory.length - 1;
|
|
356
|
-
const truncatedHistory = prevHistory.slice(0, batchStartIndex + 1);
|
|
357
|
-
const newHistoryEntry = {
|
|
358
|
-
state: currentState,
|
|
359
|
-
taskId: taskId
|
|
360
|
-
};
|
|
361
|
-
const newHistory = [...truncatedHistory, newHistoryEntry];
|
|
362
|
-
setCurrentIndex(newHistory.length - 1);
|
|
363
|
-
return newHistory;
|
|
364
|
-
});
|
|
365
|
-
// Call controller to create history in backend - OUTSIDE of setHistory callback
|
|
366
|
-
if (internalOptions.controller && internalOptions.firebaseUid && internalOptions.currentImageId) {
|
|
367
|
-
try {
|
|
368
|
-
console.log('🔄 Creating editor history in backend for batch mode end');
|
|
369
|
-
let replaceFromTaskId;
|
|
370
|
-
const batchStartIndex = batchStartIndexRef.current ?? currentIndex;
|
|
371
|
-
const wasInMiddleOfHistory = batchStartIndex < history.length - 1;
|
|
372
|
-
if (wasInMiddleOfHistory) {
|
|
373
|
-
// Get the task_id from the original history entry to use as replace_from
|
|
374
|
-
const currentHistoryEntry = history[batchStartIndex];
|
|
375
|
-
replaceFromTaskId = currentHistoryEntry?.taskId;
|
|
376
|
-
console.log(`📍 Was in middle of history (index ${batchStartIndex}), using replace_from: ${replaceFromTaskId}`);
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
console.log(`📍 At latest history (index ${batchStartIndex}), no replace_from needed`);
|
|
380
|
-
}
|
|
381
|
-
const createEditorConfigPayload = {
|
|
382
|
-
gallery_id: internalOptions.currentImageId,
|
|
383
|
-
task_id: taskId,
|
|
384
|
-
color_adjustment: convertAdjustmentStateToColorAdjustment(currentState),
|
|
385
|
-
...(replaceFromTaskId && { replace_from: replaceFromTaskId })
|
|
386
|
-
};
|
|
387
|
-
// Create editor config with current adjustments
|
|
388
|
-
internalOptions.controller.createEditorConfig(internalOptions.firebaseUid, createEditorConfigPayload).then(() => {
|
|
389
|
-
console.log('✅ Successfully created editor history in backend');
|
|
390
|
-
}).catch((error) => {
|
|
391
|
-
console.error('❌ Failed to create editor history in backend:', error);
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
catch (error) {
|
|
395
|
-
console.error('❌ Error calling controller.createEditorConfig:', error);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
if (internalOptions.devWarnings) {
|
|
400
|
-
console.warn('⚠️ Controller, firebaseUid, or currentImageId not provided - skipping backend history creation');
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
batchStartIndexRef.current = null;
|
|
405
|
-
batchStartStateRef.current = null;
|
|
406
|
-
batchModeProcessingRef.current = false; // Reset processing flag
|
|
407
|
-
}
|
|
408
|
-
}, [currentIndex, currentState, internalOptions]);
|
|
409
|
-
// History info object
|
|
410
|
-
const historyInfo = useMemo(() => ({
|
|
411
|
-
canUndo: currentIndex > 0,
|
|
412
|
-
canRedo: currentIndex < history.length - 1,
|
|
413
|
-
currentIndex,
|
|
414
|
-
totalStates: history.length,
|
|
415
|
-
historySize: getMemoryUsage(),
|
|
416
|
-
isBatchMode: batchModeRef.current
|
|
417
|
-
}), [currentIndex, history.length, getMemoryUsage]);
|
|
418
|
-
// Actions object - stabilized with useMemo
|
|
419
|
-
const actions = useMemo(() => ({
|
|
420
|
-
pushState,
|
|
421
|
-
undo,
|
|
422
|
-
redo,
|
|
423
|
-
reset,
|
|
424
|
-
jumpToIndex,
|
|
425
|
-
clearHistory,
|
|
426
|
-
getHistory,
|
|
427
|
-
trimHistory,
|
|
428
|
-
syncHistory
|
|
429
|
-
}), [pushState, undo, redo, reset, jumpToIndex, clearHistory, getHistory, trimHistory, syncHistory]);
|
|
430
|
-
// Force sync current state to backend
|
|
431
|
-
const syncToBackend = useCallback(async () => {
|
|
432
|
-
if (internalOptions.controller && internalOptions.firebaseUid && internalOptions.currentImageId) {
|
|
433
|
-
try {
|
|
434
|
-
console.log('🔄 Force syncing current state to backend');
|
|
435
|
-
// Check if we're in middle of history (not at the latest)
|
|
436
|
-
const wasInMiddleOfHistory = currentIndex < history.length - 1;
|
|
437
|
-
let replaceFromTaskId;
|
|
438
|
-
if (wasInMiddleOfHistory) {
|
|
439
|
-
// Get the task_id from the current history entry to use as replace_from
|
|
440
|
-
const currentHistoryEntry = history[currentIndex];
|
|
441
|
-
replaceFromTaskId = currentHistoryEntry?.taskId;
|
|
442
|
-
console.log(`📍 In middle of history (index ${currentIndex}), using replace_from: ${replaceFromTaskId}`);
|
|
443
|
-
}
|
|
444
|
-
// Generate a unique task ID for this sync
|
|
445
|
-
const taskId = `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
446
|
-
const createEditorConfigPayload = {
|
|
447
|
-
gallery_id: internalOptions.currentImageId,
|
|
448
|
-
task_id: taskId,
|
|
449
|
-
color_adjustment: convertAdjustmentStateToColorAdjustment(currentState),
|
|
450
|
-
...(replaceFromTaskId && { replace_from: replaceFromTaskId })
|
|
451
|
-
};
|
|
452
|
-
await internalOptions.controller.createEditorConfig(internalOptions.firebaseUid, createEditorConfigPayload);
|
|
453
|
-
console.log('✅ Successfully synced current state to backend');
|
|
454
|
-
// Update the current history entry with the new task ID
|
|
455
|
-
setHistory(prevHistory => {
|
|
456
|
-
const newHistory = [...prevHistory];
|
|
457
|
-
if (newHistory[currentIndex]) {
|
|
458
|
-
newHistory[currentIndex] = {
|
|
459
|
-
...newHistory[currentIndex],
|
|
460
|
-
taskId: taskId
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
return newHistory;
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
catch (error) {
|
|
467
|
-
console.error('❌ Failed to sync current state to backend:', error);
|
|
468
|
-
throw error;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
else {
|
|
472
|
-
console.warn('⚠️ Controller, firebaseUid, or currentImageId not provided - skipping backend sync');
|
|
473
|
-
}
|
|
474
|
-
}, [currentState, currentIndex, history, internalOptions]);
|
|
475
|
-
// Config object - stabilized with useMemo
|
|
476
|
-
const config = useMemo(() => ({
|
|
477
|
-
setMaxSize,
|
|
478
|
-
setBatchMode,
|
|
479
|
-
getMemoryUsage,
|
|
480
|
-
syncToBackend
|
|
481
|
-
}), [setMaxSize, setBatchMode, getMemoryUsage, syncToBackend]);
|
|
482
|
-
// Apply max size enforcement when history changes
|
|
483
|
-
useEffect(() => {
|
|
484
|
-
enforceMaxSize();
|
|
485
|
-
checkPerformance();
|
|
486
|
-
}, [enforceMaxSize, checkPerformance]);
|
|
487
|
-
return {
|
|
488
|
-
currentState,
|
|
489
|
-
historyInfo,
|
|
490
|
-
actions,
|
|
491
|
-
config
|
|
492
|
-
};
|
|
493
|
-
}
|