@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,
|
|
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
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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:
|
|
182
|
-
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,
|
|
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
|
-
|
|
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
|
-
//
|
|
299
|
-
const isLoading =
|
|
300
|
-
const error =
|
|
301
|
-
const 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
|
-
|
|
344
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
557
|
-
presetActions, // Expose preset actions for create/rename/delete
|
|
346
|
+
presetActions,
|
|
558
347
|
handleToggleImageSelection: batchActions.toggleSelection,
|
|
559
|
-
handleLoadMore:
|
|
560
|
-
handleRefresh:
|
|
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
|
};
|