@yogiswara/honcho-editor-ui 2.5.9 → 2.6.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.
- package/dist/components/editor/HBulkPreset.js +12 -2
- package/dist/hooks/demo/HonchoEditorBulkDemo.d.ts +3 -0
- package/dist/hooks/demo/HonchoEditorBulkDemo.js +228 -0
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.d.ts +3 -0
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.js +354 -0
- package/dist/hooks/demo/index.d.ts +2 -0
- package/dist/hooks/demo/index.js +2 -0
- package/dist/hooks/editor/type.d.ts +71 -0
- package/dist/hooks/editor/useHonchoEditorBulk.d.ts +12 -12
- package/dist/hooks/editor/useHonchoEditorBulk.js +155 -42
- package/dist/hooks/editor/useHonchoEditorSingle.d.ts +43 -0
- package/dist/hooks/editor/useHonchoEditorSingle.js +158 -0
- package/dist/hooks/useAdjustmentHistory.d.ts +9 -5
- package/dist/hooks/useAdjustmentHistory.js +187 -31
- package/dist/hooks/useAdjustmentHistoryBatch.d.ts +18 -1
- package/dist/hooks/useAdjustmentHistoryBatch.js +627 -201
- package/dist/hooks/useGallerySwipe.d.ts +1 -1
- package/dist/hooks/usePaging.d.ts +89 -0
- package/dist/hooks/usePaging.js +211 -0
- package/dist/hooks/usePreset.d.ts +1 -1
- package/dist/hooks/usePreset.js +35 -35
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -1
- package/dist/lib/context/EditorContext.d.ts +10 -0
- package/dist/lib/context/EditorContext.js +4 -2
- package/dist/lib/hooks/useEditorHeadless.d.ts +18 -2
- package/dist/lib/hooks/useEditorHeadless.js +142 -63
- package/dist/utils/adjustment.d.ts +2 -1
- package/dist/utils/adjustment.js +16 -0
- package/dist/utils/imageLoader.d.ts +11 -0
- package/dist/utils/imageLoader.js +53 -0
- package/package.json +1 -1
- package/dist/components/editor/GalleryAlbum/SimplifiedAlbumGallery.d.ts +0 -17
- package/dist/components/editor/GalleryAlbum/SimplifiedAlbumGallery.js +0 -14
- package/dist/components/editor/GalleryAlbum/SimplifiedImageItem.d.ts +0 -8
- package/dist/components/editor/GalleryAlbum/SimplifiedImageItem.js +0 -30
- package/dist/components/editor/HImageEditorPage.d.ts +0 -1
- package/dist/components/editor/HImageEditorPage.js +0 -187
- package/dist/hooks/__tests__/useGallerySwipe.test.d.ts +0 -0
- package/dist/hooks/__tests__/useGallerySwipe.test.js +0 -619
- package/dist/hooks/editor/useHonchoEditor.d.ts +0 -203
- package/dist/hooks/editor/useHonchoEditor.js +0 -716
- package/dist/hooks/useAdjustmentHistory.demo.d.ts +0 -8
- package/dist/hooks/useAdjustmentHistory.demo.js +0 -106
- package/dist/hooks/useAdjustmentHistory.example.d.ts +0 -38
- package/dist/hooks/useAdjustmentHistory.example.js +0 -182
- package/dist/hooks/useAdjustmentHistory.syncDemo.d.ts +0 -8
- package/dist/hooks/useAdjustmentHistory.syncDemo.js +0 -180
- package/dist/hooks/useGallerySwipe.example.d.ts +0 -24
- package/dist/hooks/useGallerySwipe.example.js +0 -184
|
@@ -1,4 +1,23 @@
|
|
|
1
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
|
+
};
|
|
2
21
|
/**
|
|
3
22
|
* Compare two AdjustmentState objects for equality
|
|
4
23
|
* Uses JSON.stringify for deep comparison of all adjustment values
|
|
@@ -36,28 +55,38 @@ const compareAdjustmentStates = (a, b) => {
|
|
|
36
55
|
* - Automatic AdjustmentState comparison
|
|
37
56
|
*
|
|
38
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)
|
|
39
61
|
* @param options - Configuration options for history behavior
|
|
40
62
|
* @returns Object with current state, history info, actions, and config
|
|
41
63
|
*/
|
|
42
|
-
export function useAdjustmentHistory(initialState, options = {}) {
|
|
64
|
+
export function useAdjustmentHistory(initialState, controller, firebaseUid, currentImageId, options = {}) {
|
|
43
65
|
// Internal stabilization - prevent re-renders from options object recreation
|
|
44
66
|
const internalOptions = useMemo(() => ({
|
|
45
67
|
maxSize: options.maxSize ?? 'unlimited',
|
|
46
68
|
enableBatching: options.enableBatching ?? false,
|
|
47
|
-
devWarnings: options.devWarnings ?? false
|
|
69
|
+
devWarnings: options.devWarnings ?? false,
|
|
70
|
+
controller: controller,
|
|
71
|
+
firebaseUid: firebaseUid,
|
|
72
|
+
currentImageId: currentImageId
|
|
48
73
|
}), [
|
|
49
74
|
options.maxSize,
|
|
50
75
|
options.enableBatching,
|
|
51
|
-
options.devWarnings
|
|
76
|
+
options.devWarnings,
|
|
77
|
+
controller,
|
|
78
|
+
firebaseUid,
|
|
79
|
+
currentImageId
|
|
52
80
|
]);
|
|
53
81
|
// Core state management
|
|
54
|
-
const [history, setHistory] = useState([initialState]);
|
|
82
|
+
const [history, setHistory] = useState([{ state: initialState }]);
|
|
55
83
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
56
84
|
const [currentState, setCurrentState] = useState(initialState);
|
|
57
85
|
// Batch mode state - ref to avoid triggering effects
|
|
58
86
|
const batchModeRef = useRef(internalOptions.enableBatching);
|
|
59
87
|
const batchStartIndexRef = useRef(null);
|
|
60
88
|
const batchStartStateRef = useRef(null);
|
|
89
|
+
const batchModeProcessingRef = useRef(false); // Guard against double execution
|
|
61
90
|
// Configuration refs - prevent re-renders when config changes
|
|
62
91
|
const maxSizeRef = useRef(internalOptions.maxSize);
|
|
63
92
|
const devWarningsRef = useRef(internalOptions.devWarnings);
|
|
@@ -70,9 +99,9 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
70
99
|
// Sync currentState with history when not in batch mode
|
|
71
100
|
useEffect(() => {
|
|
72
101
|
if (!batchModeRef.current) {
|
|
73
|
-
setCurrentState(history[currentIndex]);
|
|
102
|
+
setCurrentState(history[currentIndex]?.state || initialState);
|
|
74
103
|
}
|
|
75
|
-
}, [history, currentIndex]);
|
|
104
|
+
}, [history, currentIndex, initialState]);
|
|
76
105
|
const getMemoryUsage = useCallback(() => {
|
|
77
106
|
try {
|
|
78
107
|
const historyString = JSON.stringify(history);
|
|
@@ -126,10 +155,6 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
126
155
|
}, [history.length, trimHistoryToSize]);
|
|
127
156
|
// Push new state to history
|
|
128
157
|
const pushState = useCallback((newState) => {
|
|
129
|
-
// Skip if state hasn't changed
|
|
130
|
-
if (compareAdjustmentStates(newState, currentState)) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
158
|
// Always update currentState immediately for smooth UI
|
|
134
159
|
setCurrentState(newState);
|
|
135
160
|
if (batchModeRef.current) {
|
|
@@ -140,17 +165,30 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
140
165
|
// Normal mode: Update history immediately
|
|
141
166
|
setHistory(prevHistory => {
|
|
142
167
|
const truncatedHistory = prevHistory.slice(0, currentIndex + 1);
|
|
143
|
-
const newHistory = [...truncatedHistory, newState];
|
|
168
|
+
const newHistory = [...truncatedHistory, { state: newState }];
|
|
144
169
|
setCurrentIndex(newHistory.length - 1);
|
|
145
170
|
return newHistory;
|
|
146
171
|
});
|
|
147
172
|
}, [currentState, currentIndex]);
|
|
148
173
|
// Undo to previous state
|
|
149
|
-
const undo = useCallback(() => {
|
|
174
|
+
const undo = useCallback(async () => {
|
|
150
175
|
if (currentIndex > 0) {
|
|
151
176
|
const newIndex = currentIndex - 1;
|
|
177
|
+
const historyEntry = history[newIndex];
|
|
178
|
+
const newState = historyEntry.state;
|
|
152
179
|
setCurrentIndex(newIndex);
|
|
153
|
-
setCurrentState(
|
|
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
|
+
}
|
|
154
192
|
// Exit batch mode when undoing
|
|
155
193
|
if (batchModeRef.current) {
|
|
156
194
|
batchModeRef.current = false;
|
|
@@ -158,18 +196,31 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
158
196
|
batchStartStateRef.current = null;
|
|
159
197
|
}
|
|
160
198
|
}
|
|
161
|
-
}, [currentIndex, history]);
|
|
199
|
+
}, [currentIndex, history, internalOptions]);
|
|
162
200
|
// Redo to next state
|
|
163
|
-
const redo = useCallback(() => {
|
|
201
|
+
const redo = useCallback(async () => {
|
|
164
202
|
if (currentIndex < history.length - 1) {
|
|
165
203
|
const newIndex = currentIndex + 1;
|
|
204
|
+
const historyEntry = history[newIndex];
|
|
205
|
+
const newState = historyEntry.state;
|
|
166
206
|
setCurrentIndex(newIndex);
|
|
167
|
-
setCurrentState(
|
|
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
|
+
}
|
|
168
219
|
}
|
|
169
|
-
}, [currentIndex, history]);
|
|
220
|
+
}, [currentIndex, history, internalOptions]);
|
|
170
221
|
// Reset history with new initial state
|
|
171
222
|
const reset = useCallback((newInitialState) => {
|
|
172
|
-
setHistory([newInitialState]);
|
|
223
|
+
setHistory([{ state: newInitialState }]);
|
|
173
224
|
setCurrentIndex(0);
|
|
174
225
|
setCurrentState(newInitialState);
|
|
175
226
|
batchModeRef.current = internalOptions.enableBatching;
|
|
@@ -179,8 +230,10 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
179
230
|
// Jump to specific index in history
|
|
180
231
|
const jumpToIndex = useCallback((index) => {
|
|
181
232
|
if (index >= 0 && index < history.length) {
|
|
233
|
+
const historyEntry = history[index];
|
|
234
|
+
const newState = historyEntry.state;
|
|
182
235
|
setCurrentIndex(index);
|
|
183
|
-
setCurrentState(
|
|
236
|
+
setCurrentState(newState);
|
|
184
237
|
// Exit batch mode when jumping
|
|
185
238
|
if (batchModeRef.current) {
|
|
186
239
|
batchModeRef.current = false;
|
|
@@ -191,7 +244,7 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
191
244
|
}, [history]);
|
|
192
245
|
// Clear all history and start fresh
|
|
193
246
|
const clearHistory = useCallback(() => {
|
|
194
|
-
setHistory([currentState]);
|
|
247
|
+
setHistory([{ state: currentState }]);
|
|
195
248
|
setCurrentIndex(0);
|
|
196
249
|
batchModeRef.current = internalOptions.enableBatching;
|
|
197
250
|
batchStartIndexRef.current = null;
|
|
@@ -199,7 +252,7 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
199
252
|
}, [currentState, internalOptions.enableBatching]);
|
|
200
253
|
// Get copy of entire history
|
|
201
254
|
const getHistory = useCallback(() => {
|
|
202
|
-
return
|
|
255
|
+
return history.map(entry => entry.state);
|
|
203
256
|
}, [history]);
|
|
204
257
|
// Manually trim history
|
|
205
258
|
const trimHistory = useCallback((keepLast) => {
|
|
@@ -239,8 +292,8 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
239
292
|
// Determine target index
|
|
240
293
|
let finalIndex = targetIndex ?? newHistory.length - 1; // Default to last item
|
|
241
294
|
finalIndex = Math.max(0, Math.min(finalIndex, newHistory.length - 1)); // Clamp to valid range
|
|
242
|
-
// Create a copy of the new history to avoid mutations
|
|
243
|
-
const historyToSet = newHistory.map(state => ({ ...state }));
|
|
295
|
+
// Create a copy of the new history to avoid mutations and convert to HistoryEntry format
|
|
296
|
+
const historyToSet = newHistory.map(state => ({ state: { ...state } }));
|
|
244
297
|
// Apply max size limit if needed
|
|
245
298
|
if (maxSizeRef.current !== 'unlimited' && historyToSet.length > maxSizeRef.current) {
|
|
246
299
|
const trimAmount = historyToSet.length - maxSizeRef.current;
|
|
@@ -249,7 +302,7 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
249
302
|
finalIndex = Math.max(0, finalIndex - trimAmount);
|
|
250
303
|
setHistory(trimmedHistory);
|
|
251
304
|
setCurrentIndex(finalIndex);
|
|
252
|
-
setCurrentState(trimmedHistory[finalIndex]);
|
|
305
|
+
setCurrentState(trimmedHistory[finalIndex].state);
|
|
253
306
|
if (devWarningsRef.current) {
|
|
254
307
|
console.warn(`syncHistory: Trimmed ${trimAmount} entries to respect maxSize of ${maxSizeRef.current}`);
|
|
255
308
|
}
|
|
@@ -258,7 +311,7 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
258
311
|
// Set history as-is
|
|
259
312
|
setHistory(historyToSet);
|
|
260
313
|
setCurrentIndex(finalIndex);
|
|
261
|
-
setCurrentState(historyToSet[finalIndex]);
|
|
314
|
+
setCurrentState(historyToSet[finalIndex].state);
|
|
262
315
|
}
|
|
263
316
|
if (devWarningsRef.current) {
|
|
264
317
|
console.log(`syncHistory: Synchronized ${historyToSet.length} states, current index: ${finalIndex}`);
|
|
@@ -271,31 +324,88 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
271
324
|
enforceMaxSize();
|
|
272
325
|
}
|
|
273
326
|
}, [enforceMaxSize]);
|
|
274
|
-
const setBatchMode = useCallback((enabled) => {
|
|
327
|
+
const setBatchMode = useCallback(async (enabled) => {
|
|
275
328
|
const wasInBatch = batchModeRef.current;
|
|
329
|
+
console.log(`🔧 setBatchMode called: enabled=${enabled}, wasInBatch=${wasInBatch}, currentIndex=${currentIndex}, historyLength=${history.length}`);
|
|
276
330
|
if (enabled && !wasInBatch) {
|
|
277
331
|
// Starting batch mode - save current state as batch start
|
|
278
332
|
batchModeRef.current = true;
|
|
279
333
|
batchStartIndexRef.current = currentIndex;
|
|
280
334
|
batchStartStateRef.current = currentState;
|
|
335
|
+
console.log("Current start batch ", currentState, `batchStartIndex=${currentIndex}`);
|
|
281
336
|
}
|
|
282
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
|
+
}
|
|
283
343
|
// Ending batch mode - commit final state to history
|
|
344
|
+
batchModeProcessingRef.current = true;
|
|
284
345
|
batchModeRef.current = false;
|
|
285
346
|
// Only add to history if state actually changed from batch start
|
|
286
347
|
if (batchStartStateRef.current &&
|
|
287
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)}`;
|
|
288
351
|
setHistory(prevHistory => {
|
|
289
|
-
|
|
290
|
-
|
|
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];
|
|
291
362
|
setCurrentIndex(newHistory.length - 1);
|
|
292
363
|
return newHistory;
|
|
293
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
|
+
}
|
|
294
403
|
}
|
|
295
404
|
batchStartIndexRef.current = null;
|
|
296
405
|
batchStartStateRef.current = null;
|
|
406
|
+
batchModeProcessingRef.current = false; // Reset processing flag
|
|
297
407
|
}
|
|
298
|
-
}, [currentIndex, currentState]);
|
|
408
|
+
}, [currentIndex, currentState, internalOptions]);
|
|
299
409
|
// History info object
|
|
300
410
|
const historyInfo = useMemo(() => ({
|
|
301
411
|
canUndo: currentIndex > 0,
|
|
@@ -317,12 +427,58 @@ export function useAdjustmentHistory(initialState, options = {}) {
|
|
|
317
427
|
trimHistory,
|
|
318
428
|
syncHistory
|
|
319
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]);
|
|
320
475
|
// Config object - stabilized with useMemo
|
|
321
476
|
const config = useMemo(() => ({
|
|
322
477
|
setMaxSize,
|
|
323
478
|
setBatchMode,
|
|
324
|
-
getMemoryUsage
|
|
325
|
-
|
|
479
|
+
getMemoryUsage,
|
|
480
|
+
syncToBackend
|
|
481
|
+
}), [setMaxSize, setBatchMode, getMemoryUsage, syncToBackend]);
|
|
326
482
|
// Apply max size enforcement when history changes
|
|
327
483
|
useEffect(() => {
|
|
328
484
|
enforceMaxSize();
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import { AdjustmentState } from './editor/
|
|
1
|
+
import { AdjustmentState, Controller } from './editor/type';
|
|
2
|
+
export interface HistoryAdjustmentBatch {
|
|
3
|
+
imageId: string;
|
|
4
|
+
currentHistoryEntryId: string;
|
|
5
|
+
history: HistoryAdjustmentEntry[];
|
|
6
|
+
}
|
|
7
|
+
export interface HistoryAdjustmentEntry {
|
|
8
|
+
id: string;
|
|
9
|
+
adjustment: AdjustmentState;
|
|
10
|
+
}
|
|
2
11
|
/**
|
|
3
12
|
* Configuration for image with adjustment state
|
|
4
13
|
*/
|
|
@@ -34,6 +43,12 @@ interface BatchHistoryOptions {
|
|
|
34
43
|
devWarnings?: boolean;
|
|
35
44
|
/** Default adjustment state for new images */
|
|
36
45
|
defaultAdjustmentState?: Partial<AdjustmentState>;
|
|
46
|
+
/** Controller for backend operations */
|
|
47
|
+
controller?: Controller;
|
|
48
|
+
/** Firebase UID for backend operations */
|
|
49
|
+
firebaseUid?: string;
|
|
50
|
+
/** Event ID for backend operations */
|
|
51
|
+
eventId?: string;
|
|
37
52
|
}
|
|
38
53
|
/**
|
|
39
54
|
* Information about the current batch history state
|
|
@@ -60,6 +75,8 @@ export interface BatchHistoryInfo {
|
|
|
60
75
|
export interface BatchHistoryActions {
|
|
61
76
|
/** Apply adjustment deltas to selected images */
|
|
62
77
|
adjustSelected: (delta: Partial<AdjustmentState>) => void;
|
|
78
|
+
/** Apply preset values directly to selected images (preserves history) */
|
|
79
|
+
adjustSelectedWithPreset: (presetAdjustments: AdjustmentState) => void;
|
|
63
80
|
/** Undo last changes to selected images */
|
|
64
81
|
undo: () => void;
|
|
65
82
|
/** Redo next changes to selected images */
|