@yogiswara/honcho-editor-ui 2.6.6 → 2.6.8
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/HAccordionPreset.js +30 -30
- package/dist/hooks/demo/HonchoEditorBulkDemo.js +47 -12
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.js +1 -1
- package/dist/hooks/editor/type.d.ts +1 -1
- package/dist/hooks/editor/useHonchoEditorBulk.d.ts +15 -1
- package/dist/hooks/editor/useHonchoEditorBulk.js +88 -15
- package/dist/hooks/editor/useHonchoEditorSingle.d.ts +2 -1
- package/dist/hooks/editor/useHonchoEditorSingle.js +7 -3
- package/dist/hooks/useAdjustmentHistoryBatch.d.ts +2 -0
- package/dist/hooks/useAdjustmentHistoryBatch.js +478 -206
- package/dist/hooks/usePreset.js +35 -23
- package/package.json +1 -1
|
@@ -26,34 +26,34 @@ export default function HAccordionPreset(props) {
|
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
28
|
const isPanelExpanded = (panelName) => props.expandedPanels.includes(panelName);
|
|
29
|
-
return (_jsx(_Fragment, { children:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
29
|
+
return (_jsx(_Fragment, { children: _jsx(Box, { children: _jsxs(Accordion, { sx: accordionStyle, expanded: isPanelExpanded('preset'), onChange: props.onChange('preset'), disableGutters: true, children: [_jsx(AccordionSummary, { sx: { pr: 0 }, children: _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { width: '100%' }, children: [_jsx(Typography, { sx: { ...typography.titleMedium, color: colors.surface }, children: "Preset" }), _jsx(CardMedia, { component: "img", image: isPanelExpanded('preset') ? "/v1/svg/expanded-editor.svg" : "/v1/svg/expand-editor.svg", sx: { width: "11.67px", height: "5.83px" } })] }) }), _jsx(AccordionDetails, { sx: { pr: "4px" }, children: _jsxs(Stack, { direction: "column", gap: "8px", sx: { pt: '0px', pb: '0px', mx: '0px', width: '100%' }, children: [props.presets.map((preset) => (_jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { width: '100%' }, children: [props.selectedPreset != preset.id && (_jsx(Button, { sx: {
|
|
30
|
+
width: '100px',
|
|
31
|
+
textWrap: 'nowrap',
|
|
32
|
+
overflow: 'hidden',
|
|
33
|
+
textOverflow: 'ellipsis',
|
|
34
|
+
display: 'block',
|
|
35
|
+
textTransform: 'none',
|
|
36
|
+
color: colors.surface,
|
|
37
|
+
pr: "120px",
|
|
38
|
+
pl: "0px",
|
|
39
|
+
ml: "0px",
|
|
40
|
+
justifyContent: 'flex-start',
|
|
41
|
+
...typography.bodyMedium
|
|
42
|
+
}, onClick: () => props.onSelectPreset(preset.id), children: preset.name })), props.selectedPreset === preset.id && (_jsx(Button, { sx: {
|
|
43
|
+
width: '84px',
|
|
44
|
+
textWrap: 'nowrap',
|
|
45
|
+
overflow: 'hidden',
|
|
46
|
+
textOverflow: 'ellipsis',
|
|
47
|
+
display: 'block',
|
|
48
|
+
color: colors.surface,
|
|
49
|
+
pr: "82px",
|
|
50
|
+
pl: "0px",
|
|
51
|
+
ml: "0px",
|
|
52
|
+
justifyContent: 'flex-start',
|
|
53
|
+
...typography.bodyMedium
|
|
54
|
+
}, onClick: () => props.onSelectPreset(preset.id), children: preset.name })), _jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [props.selectedPreset === preset.id && (_jsx(CardMedia, { component: "img", image: "v1/svg/check-ratio-editor.svg", sx: { width: "20px", height: "20px" } })), _jsx(IconButton, { "aria-label": preset.name, onClick: (event) => props.onPresetMenuClick(event, preset.id), sx: { padding: "0px", margin: "0px" }, children: _jsx(CardMedia, { component: "img", image: "/v1/svg/dots-editor.svg", alt: "Options", sx: { padding: "0px", margin: "0px" } }) })] })] }, preset.id))), _jsx(Button, { variant: "text", sx: { color: colors.surface, border: "1px solid",
|
|
55
|
+
borderColor: colors.surface,
|
|
56
|
+
borderRadius: "40px",
|
|
57
|
+
textTransform: 'none',
|
|
58
|
+
}, onClick: props.onOpenPresetModal, children: "Create Preset" })] }) })] }) }) }));
|
|
59
59
|
}
|
|
@@ -63,6 +63,7 @@ const createMockGallery = (id, adjustments) => ({
|
|
|
63
63
|
});
|
|
64
64
|
// Mock Controller implementation
|
|
65
65
|
const createMockController = () => {
|
|
66
|
+
console.log('[Controller] 🏭 createMockController() called - Creating new mock controller instance for bulk editor');
|
|
66
67
|
const mockImages = [
|
|
67
68
|
createMockGallery('1', { tempScore: 5, exposureScore: 2 }),
|
|
68
69
|
createMockGallery('2'),
|
|
@@ -77,19 +78,24 @@ const createMockController = () => {
|
|
|
77
78
|
];
|
|
78
79
|
return {
|
|
79
80
|
onGetImage: async (uid, imageId) => {
|
|
81
|
+
console.log(`[Controller] 📷 onGetImage called: uid=${uid}, imageId=${imageId}`);
|
|
80
82
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
81
83
|
const image = mockImages.find(img => img.id === imageId);
|
|
82
|
-
if (!image)
|
|
84
|
+
if (!image) {
|
|
85
|
+
console.error(`[Controller] ❌ Image ${imageId} not found`);
|
|
83
86
|
throw new Error(`Image ${imageId} not found`);
|
|
87
|
+
}
|
|
88
|
+
console.log(`[Controller] 📷 onGetImage returning image:`, image.id);
|
|
84
89
|
return image;
|
|
85
90
|
},
|
|
86
91
|
getImageList: async (uid, eventId, page) => {
|
|
92
|
+
console.log(`[Controller] 📋 getImageList called: uid=${uid}, eventId=${eventId}, page=${page}`);
|
|
87
93
|
await new Promise(resolve => setTimeout(resolve, 800));
|
|
88
94
|
const pageSize = 4;
|
|
89
95
|
const startIndex = (page - 1) * pageSize;
|
|
90
96
|
const endIndex = startIndex + pageSize;
|
|
91
97
|
const pageImages = mockImages.slice(startIndex, endIndex);
|
|
92
|
-
|
|
98
|
+
const result = {
|
|
93
99
|
gallery: pageImages,
|
|
94
100
|
limit: pageSize,
|
|
95
101
|
current_page: page,
|
|
@@ -97,50 +103,72 @@ const createMockController = () => {
|
|
|
97
103
|
next_page: endIndex < mockImages.length ? page + 1 : 0,
|
|
98
104
|
sum_of_image: pageImages.length,
|
|
99
105
|
};
|
|
106
|
+
console.log(`[Controller] 📋 getImageList returning ${pageImages.length} images for page ${page}`, result);
|
|
107
|
+
return result;
|
|
100
108
|
},
|
|
101
109
|
syncConfig: async (uid) => {
|
|
110
|
+
console.log(`[Controller] 🔄 syncConfig called: uid=${uid}`);
|
|
102
111
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
112
|
+
console.log(`[Controller] 🔄 syncConfig completed for uid=${uid}`);
|
|
103
113
|
},
|
|
104
114
|
handleBack: (uid, imageId) => {
|
|
105
|
-
console.log(`
|
|
115
|
+
console.log(`[Controller] ⬅️ handleBack called: uid=${uid}, imageId=${imageId}`);
|
|
116
|
+
console.log(`[Controller] ⬅️ Back to: ${imageId}`);
|
|
106
117
|
},
|
|
107
118
|
getPresets: async (uid) => {
|
|
108
|
-
|
|
119
|
+
console.log(`[Controller] 🎨 getPresets called: uid=${uid}`);
|
|
120
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
121
|
+
const presets = [
|
|
109
122
|
{ id: '1', name: 'Warm Sunset', is_default: false, temperature: 15, tint: 5, saturation: 8, vibrance: 12, exposure: 2, contrast: 5, highlights: -10, shadows: 8, whites: 3, blacks: -5, clarity: 4, sharpness: 6 },
|
|
110
123
|
{ id: '2', name: 'Cool Morning', is_default: false, temperature: -12, tint: -3, saturation: -2, vibrance: 5, exposure: 1, contrast: 3, highlights: -5, shadows: 12, whites: 8, blacks: -8, clarity: 6, sharpness: 4 },
|
|
111
124
|
{ id: '3', name: 'High Contrast', is_default: false, temperature: 0, tint: 0, saturation: 5, vibrance: 8, exposure: 0, contrast: 20, highlights: -15, shadows: 15, whites: 10, blacks: -10, clarity: 15, sharpness: 8 },
|
|
112
125
|
];
|
|
126
|
+
console.log(`[Controller] 🎨 getPresets returning ${presets.length} presets`, presets.map(p => ({ id: p.id, name: p.name })));
|
|
127
|
+
return presets;
|
|
113
128
|
},
|
|
114
129
|
createPreset: async (uid, name, settings) => {
|
|
115
|
-
console.log(`
|
|
130
|
+
console.log(`[Controller] ➕ createPreset called: uid=${uid}, name=${name}`, settings);
|
|
131
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
132
|
+
console.log(`[Controller] ➕ createPreset completed: ${name}`);
|
|
116
133
|
},
|
|
117
134
|
deletePreset: async (uid, presetId) => {
|
|
118
|
-
console.log(`
|
|
135
|
+
console.log(`[Controller] 🗑️ deletePreset called: uid=${uid}, presetId=${presetId}`);
|
|
136
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
137
|
+
console.log(`[Controller] 🗑️ deletePreset completed: ${presetId}`);
|
|
119
138
|
},
|
|
120
139
|
updatePreset: async (uid, data) => {
|
|
121
|
-
console.log(`
|
|
140
|
+
console.log(`[Controller] 🔄 updatePreset called: uid=${uid}`, data);
|
|
141
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
142
|
+
console.log(`[Controller] 🔄 updatePreset completed:`, data.name);
|
|
122
143
|
},
|
|
123
144
|
createEditorConfig: async (uid, payload) => {
|
|
145
|
+
console.log(`[Controller] ⚙️ createEditorConfig called: uid=${uid}`, payload);
|
|
124
146
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
125
|
-
console.log(
|
|
147
|
+
console.log(`[Controller] ⚙️ createEditorConfig completed for gallery_id=${payload.gallery_id}, task_id=${payload.task_id}`);
|
|
126
148
|
},
|
|
127
149
|
getEditorHistory: async (uid, imageId) => {
|
|
150
|
+
console.log(`[Controller] 📚 getEditorHistory called: uid=${uid}, imageId=${imageId}`);
|
|
128
151
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
129
|
-
|
|
130
|
-
return {
|
|
152
|
+
const result = {
|
|
131
153
|
current_task_id: "",
|
|
132
154
|
history: []
|
|
133
155
|
};
|
|
156
|
+
console.log(`[Controller] 📚 getEditorHistory returning empty history for demo:`, result);
|
|
157
|
+
return result;
|
|
134
158
|
},
|
|
135
159
|
getGalleryUpdateTimestamp: async (uid, eventId) => {
|
|
160
|
+
console.log(`[Controller] ⏰ getGalleryUpdateTimestamp called: uid=${uid}, eventId=${eventId}`);
|
|
136
161
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
137
|
-
|
|
162
|
+
const result = {
|
|
138
163
|
gallery: []
|
|
139
164
|
};
|
|
165
|
+
console.log(`[Controller] ⏰ getGalleryUpdateTimestamp returning:`, result);
|
|
166
|
+
return result;
|
|
140
167
|
},
|
|
141
168
|
setHistoryIndex: async (uid, imageId, taskId) => {
|
|
169
|
+
console.log(`[Controller] 📍 setHistoryIndex called: uid=${uid}, imageId=${imageId}, taskId=${taskId}`);
|
|
142
170
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
143
|
-
console.log(`
|
|
171
|
+
console.log(`[Controller] 📍 setHistoryIndex completed - Set history index for image ${imageId} to task ${taskId}`);
|
|
144
172
|
},
|
|
145
173
|
};
|
|
146
174
|
};
|
|
@@ -225,4 +253,11 @@ export const HonchoEditorBulkDemo = () => {
|
|
|
225
253
|
} })] }), adjustments.length > 0 && (_jsx(Box, { mt: 1, children: _jsx(Stack, { direction: "row", spacing: 0.5, flexWrap: "wrap", children: adjustments.map((adj, index) => (_jsx(Chip, { label: adj, size: "small", variant: "outlined", sx: { fontSize: '0.7rem', height: 20 } }, index))) }) }))] })] }) }, image.key));
|
|
226
254
|
}) }), isLoading && imageData.length === 0 && (_jsx(Box, { display: "flex", justifyContent: "center", py: 4, children: _jsx(CircularProgress, {}) })), _jsxs(Box, { mt: 4, children: [_jsx(Divider, {}), _jsx(Typography, { variant: "body2", color: "text.secondary", align: "center", sx: { mt: 2 }, children: "Demo Notes: This uses mock data and simulated API calls. Select images and try the bulk adjustment controls above." })] })] }));
|
|
227
255
|
};
|
|
256
|
+
// Add debugging function to global scope for manual testing
|
|
257
|
+
if (typeof window !== 'undefined') {
|
|
258
|
+
window.testPresetSelection = () => {
|
|
259
|
+
console.log("🧪 Manual preset test - this would normally be called by the UI");
|
|
260
|
+
console.log("🧪 To test properly, use the actual preset dropdown in the UI above");
|
|
261
|
+
};
|
|
262
|
+
}
|
|
228
263
|
export default HonchoEditorBulkDemo;
|
|
@@ -260,7 +260,7 @@ export const HonchoEditorSingleCleanDemo = () => {
|
|
|
260
260
|
if (!newPresetName.trim())
|
|
261
261
|
return;
|
|
262
262
|
try {
|
|
263
|
-
const preset = await actions.createPreset(newPresetName);
|
|
263
|
+
const preset = await actions.createPreset(newPresetName, state.currentAdjustments);
|
|
264
264
|
if (preset) {
|
|
265
265
|
setNewPresetName('');
|
|
266
266
|
console.log('Preset created successfully:', preset);
|
|
@@ -163,7 +163,7 @@ export interface Controller {
|
|
|
163
163
|
updatePreset(firebaseUid: string, data: Preset): Promise<void>;
|
|
164
164
|
createEditorConfig(firebaseUid: string, payload: CreateEditorTaskRequest): Promise<void>;
|
|
165
165
|
getEditorHistory(firebaseUid: string, imageID: string): Promise<GetHistoryResponse>;
|
|
166
|
-
getGalleryUpdateTimestamp(firebaseUid: string, eventID: string): Promise<GetGalleryUpdateTimestampResponse>;
|
|
166
|
+
getGalleryUpdateTimestamp(firebaseUid: string, eventID: string, timestamp: number): Promise<GetGalleryUpdateTimestampResponse>;
|
|
167
167
|
setHistoryIndex(firebaseUid: string, imageID: string, taskID: string): Promise<void>;
|
|
168
168
|
}
|
|
169
169
|
export interface ImageItem {
|
|
@@ -11,6 +11,21 @@ export interface PhotoData {
|
|
|
11
11
|
isSelected: boolean;
|
|
12
12
|
adjustments?: Partial<AdjustmentValues>;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Hook for bulk photo editing with multi-image backend synchronization.
|
|
16
|
+
*
|
|
17
|
+
* **Multi-Image Backend Sync:**
|
|
18
|
+
* - Each selected image maintains its own history and backend state
|
|
19
|
+
* - History operations (undo/redo) trigger separate controller.setHistoryIndex() calls for each selected image
|
|
20
|
+
* - Preset application triggers separate controller.createEditorConfig() calls for each selected image
|
|
21
|
+
* - Adjustment changes trigger separate controller.createEditorConfig() calls for each selected image
|
|
22
|
+
*
|
|
23
|
+
* **Key Features:**
|
|
24
|
+
* - Individual history tracking per image with backend persistence
|
|
25
|
+
* - Bulk operations that respect per-image differences
|
|
26
|
+
* - Automatic backend synchronization for all state changes
|
|
27
|
+
* - Comprehensive logging of multi-image operations
|
|
28
|
+
*/
|
|
14
29
|
export declare function useHonchoEditorBulk(controller: Controller, eventID: string, firebaseUid: string): {
|
|
15
30
|
imageData: PhotoData[];
|
|
16
31
|
isLoading: boolean;
|
|
@@ -22,7 +37,6 @@ export declare function useHonchoEditorBulk(controller: Controller, eventID: str
|
|
|
22
37
|
selectedBulkPreset: string;
|
|
23
38
|
activePreset: Preset | null;
|
|
24
39
|
handleSelectBulkPreset: (event: SelectChangeEvent<string>) => void;
|
|
25
|
-
handleOpenPresetModal: () => void;
|
|
26
40
|
presetActions: import("../usePreset").PresetActions;
|
|
27
41
|
handleToggleImageSelection: (imageId: string) => void;
|
|
28
42
|
handleLoadMore: () => Promise<void>;
|
|
@@ -66,7 +66,23 @@ const adjustmentsMatch = (a, b) => {
|
|
|
66
66
|
];
|
|
67
67
|
return keys.every(key => (a[key] || 0) === (b[key] || 0));
|
|
68
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* Hook for bulk photo editing with multi-image backend synchronization.
|
|
71
|
+
*
|
|
72
|
+
* **Multi-Image Backend Sync:**
|
|
73
|
+
* - Each selected image maintains its own history and backend state
|
|
74
|
+
* - History operations (undo/redo) trigger separate controller.setHistoryIndex() calls for each selected image
|
|
75
|
+
* - Preset application triggers separate controller.createEditorConfig() calls for each selected image
|
|
76
|
+
* - Adjustment changes trigger separate controller.createEditorConfig() calls for each selected image
|
|
77
|
+
*
|
|
78
|
+
* **Key Features:**
|
|
79
|
+
* - Individual history tracking per image with backend persistence
|
|
80
|
+
* - Bulk operations that respect per-image differences
|
|
81
|
+
* - Automatic backend synchronization for all state changes
|
|
82
|
+
* - Comprehensive logging of multi-image operations
|
|
83
|
+
*/
|
|
69
84
|
export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
85
|
+
console.log('[useHonchoEditorBulk] 🏭 Initializing with controller for multi-image backend sync');
|
|
70
86
|
const { currentBatch, selectedIds, actions: batchActions, historyInfo } = useAdjustmentHistoryBatch({
|
|
71
87
|
controller,
|
|
72
88
|
firebaseUid,
|
|
@@ -147,16 +163,30 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
147
163
|
syncAdjustmentRef.current = batchActions.syncAdjustment;
|
|
148
164
|
// Safe sync: Only sync new images to prevent infinite loops
|
|
149
165
|
useEffect(() => {
|
|
166
|
+
console.log('[useHonchoEditorBulk] 🔄 Sync effect triggered:', {
|
|
167
|
+
imagesLength: images.length,
|
|
168
|
+
imageIds: images.map(img => img.id),
|
|
169
|
+
lastSyncedImageIds: Array.from(lastSyncedImageIds.current),
|
|
170
|
+
lastSyncedCount: lastSyncedImageIds.current.size
|
|
171
|
+
});
|
|
150
172
|
if (images.length === 0)
|
|
151
173
|
return;
|
|
152
174
|
// Check if we have new images that haven't been synced
|
|
153
175
|
const currentImageIds = new Set(images.map(img => img.id));
|
|
154
176
|
const hasNewImages = images.some(img => !lastSyncedImageIds.current.has(img.id));
|
|
177
|
+
console.log('[useHonchoEditorBulk] 🔍 New images check:', {
|
|
178
|
+
currentImageIds: Array.from(currentImageIds),
|
|
179
|
+
hasNewImages,
|
|
180
|
+
newImages: images.filter(img => !lastSyncedImageIds.current.has(img.id)).map(img => img.id)
|
|
181
|
+
});
|
|
155
182
|
if (hasNewImages) {
|
|
156
|
-
console.log('[useHonchoEditorBulk] Syncing new images to batch:', images.length);
|
|
183
|
+
console.log('[useHonchoEditorBulk] ⚠️ SYNC TRIGGER: Syncing new images to batch (THIS RESETS HISTORY!):', images.length);
|
|
157
184
|
syncAdjustmentRef.current(images.map(mapToImageAdjustmentConfig));
|
|
158
185
|
lastSyncedImageIds.current = currentImageIds;
|
|
159
186
|
}
|
|
187
|
+
else {
|
|
188
|
+
console.log('[useHonchoEditorBulk] ✅ No new images, skipping sync (history preserved)');
|
|
189
|
+
}
|
|
160
190
|
}, [images]); // Only depend on images, not batchActions
|
|
161
191
|
const handleBackCallbackBulk = useCallback(() => {
|
|
162
192
|
const lastSelectedId = selectedIds.length > 0 ? selectedIds[selectedIds.length - 1] : "";
|
|
@@ -165,20 +195,50 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
165
195
|
const handleSelectBulkPreset = useCallback((event) => {
|
|
166
196
|
const presetId = event.target.value;
|
|
167
197
|
setSelectedBulkPreset(presetId);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
198
|
+
console.log('[useHonchoEditorBulk] 🎨 Preset selection attempt:', {
|
|
199
|
+
presetId,
|
|
200
|
+
selectedImages: selectedIds,
|
|
201
|
+
imageCount: selectedIds.length,
|
|
202
|
+
hasController: !!controller,
|
|
203
|
+
hasFirebaseUid: !!firebaseUid
|
|
204
|
+
});
|
|
205
|
+
if (!presetId) {
|
|
206
|
+
console.log('[useHonchoEditorBulk] ❌ No preset ID provided, skipping backend call');
|
|
207
|
+
return;
|
|
177
208
|
}
|
|
178
|
-
|
|
209
|
+
if (selectedIds.length === 0) {
|
|
210
|
+
console.log('[useHonchoEditorBulk] ❌ No images selected, skipping backend call');
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
console.log('[useHonchoEditorBulk] 🎨 Applying preset to multiple images:', {
|
|
214
|
+
presetId,
|
|
215
|
+
selectedImages: selectedIds,
|
|
216
|
+
imageCount: selectedIds.length
|
|
217
|
+
});
|
|
218
|
+
// Find the preset
|
|
219
|
+
const preset = presets.find(p => p.id === presetId);
|
|
220
|
+
if (!preset) {
|
|
221
|
+
console.log('[useHonchoEditorBulk] ❌ Preset not found in presets list:', presetId);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Convert preset to adjustment state
|
|
225
|
+
const presetAdjustments = presetToAdjustmentState(preset);
|
|
226
|
+
console.log('[useHonchoEditorBulk] 📤 Sending preset adjustments to controller for each image:', presetAdjustments);
|
|
227
|
+
console.log('[useHonchoEditorBulk] 🔄 About to call batchActions.adjustSelectedWithPreset');
|
|
228
|
+
// Apply preset directly to all selected images using the clean action
|
|
229
|
+
// This will trigger backend calls for each selected image via adjustSelectedWithPreset
|
|
230
|
+
batchActions.adjustSelectedWithPreset(presetAdjustments);
|
|
231
|
+
console.log('[useHonchoEditorBulk] ✅ Called batchActions.adjustSelectedWithPreset, backend calls should be triggered');
|
|
232
|
+
}, [presets, selectedIds, batchActions, controller, firebaseUid]);
|
|
179
233
|
// This factory creates functions that adjust a value for all selected images
|
|
180
234
|
const createRelativeAdjuster = useCallback((key, amount) => () => {
|
|
181
|
-
console.debug(
|
|
235
|
+
console.debug(`[useHonchoEditorBulk] 🎛️ Bulk ${key} adjustment:`, {
|
|
236
|
+
key,
|
|
237
|
+
amount,
|
|
238
|
+
selectedImages: selectedIds,
|
|
239
|
+
imageCount: selectedIds.length
|
|
240
|
+
});
|
|
241
|
+
console.debug('[useHonchoEditorBulk] 📤 Sending bulk adjustment to controller for each selected image');
|
|
182
242
|
console.debug("currentBatch.allImages before:", currentBatch.allImages);
|
|
183
243
|
batchActions.adjustSelected({ [key]: amount });
|
|
184
244
|
// Debug after a short delay to see if the state changed
|
|
@@ -290,7 +350,6 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
290
350
|
activePreset,
|
|
291
351
|
handleSelectBulkPreset,
|
|
292
352
|
// Preset creation handlers
|
|
293
|
-
handleOpenPresetModal: () => { }, // TODO: Implement preset modal for bulk editing
|
|
294
353
|
presetActions, // Expose preset actions for create/rename/delete
|
|
295
354
|
handleToggleImageSelection: batchActions.toggleSelection,
|
|
296
355
|
handleLoadMore: actions.loadMore,
|
|
@@ -347,8 +406,22 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
|
|
|
347
406
|
handleBulkSharpnessIncrease,
|
|
348
407
|
handleBulkSharpnessIncreaseMax,
|
|
349
408
|
// History actions
|
|
350
|
-
handleUndo:
|
|
351
|
-
|
|
409
|
+
handleUndo: () => {
|
|
410
|
+
console.log('[useHonchoEditorBulk] ⏪ Undo requested for multiple images:', {
|
|
411
|
+
selectedImages: selectedIds,
|
|
412
|
+
imageCount: selectedIds.length
|
|
413
|
+
});
|
|
414
|
+
console.log('[useHonchoEditorBulk] 📤 Sending undo (setHistoryIndex) to controller for each image');
|
|
415
|
+
return batchActions.undo();
|
|
416
|
+
},
|
|
417
|
+
handleRedo: () => {
|
|
418
|
+
console.log('[useHonchoEditorBulk] ⏩ Redo requested for multiple images:', {
|
|
419
|
+
selectedImages: selectedIds,
|
|
420
|
+
imageCount: selectedIds.length
|
|
421
|
+
});
|
|
422
|
+
console.log('[useHonchoEditorBulk] 📤 Sending redo (setHistoryIndex) to controller for each image');
|
|
423
|
+
return batchActions.redo();
|
|
424
|
+
},
|
|
352
425
|
handleReset: batchActions.reset,
|
|
353
426
|
historyInfo,
|
|
354
427
|
};
|
|
@@ -33,7 +33,8 @@ export interface UseHonchoEditorSingleActions {
|
|
|
33
33
|
reset: () => void;
|
|
34
34
|
loadPresets: () => Promise<void>;
|
|
35
35
|
applyPreset: (preset: Preset) => void;
|
|
36
|
-
createPreset: (name: string) => Promise<Preset | null>;
|
|
36
|
+
createPreset: (name: string, adjustments: AdjustmentState) => Promise<Preset | null>;
|
|
37
|
+
renamePreset: (presetId: string, newName: string) => Promise<boolean>;
|
|
37
38
|
deletePreset: (presetId: string) => Promise<void>;
|
|
38
39
|
getEditorAdjustments: () => AdjustmentValues;
|
|
39
40
|
}
|
|
@@ -87,9 +87,12 @@ export function useHonchoEditorSingle({ controller, initImageId, firebaseUid })
|
|
|
87
87
|
// Then sync to backend
|
|
88
88
|
await adjustmentHistory.config.syncToBackend();
|
|
89
89
|
}, [adjustmentHistory.actions.pushState, adjustmentHistory.config.syncToBackend]);
|
|
90
|
-
const createPreset = useCallback(async (name) => {
|
|
91
|
-
return await presetHook.actions.create(name,
|
|
92
|
-
}, [presetHook.actions.create
|
|
90
|
+
const createPreset = useCallback(async (name, adjustments) => {
|
|
91
|
+
return await presetHook.actions.create(name, adjustments);
|
|
92
|
+
}, [presetHook.actions.create]);
|
|
93
|
+
const renamePreset = useCallback(async (presetId, newName) => {
|
|
94
|
+
return await presetHook.actions.rename(presetId, newName);
|
|
95
|
+
}, [presetHook.actions.rename]);
|
|
93
96
|
const deletePreset = useCallback(async (presetId) => {
|
|
94
97
|
await presetHook.actions.delete(presetId);
|
|
95
98
|
}, [presetHook.actions.delete]);
|
|
@@ -127,6 +130,7 @@ export function useHonchoEditorSingle({ controller, initImageId, firebaseUid })
|
|
|
127
130
|
loadPresets,
|
|
128
131
|
applyPreset,
|
|
129
132
|
createPreset,
|
|
133
|
+
renamePreset,
|
|
130
134
|
deletePreset,
|
|
131
135
|
// Adjustment conversion for editor
|
|
132
136
|
getEditorAdjustments
|
|
@@ -87,6 +87,8 @@ export interface BatchHistoryActions {
|
|
|
87
87
|
setSelection: (configs: ImageAdjustmentConfig[]) => void;
|
|
88
88
|
/** Sync/replace adjustment for images (clears their history) */
|
|
89
89
|
syncAdjustment: (configs: ImageAdjustmentConfig[]) => void;
|
|
90
|
+
/** Check for gallery updates and sync history for updated images */
|
|
91
|
+
syncGalleryUpdates: () => Promise<void>;
|
|
90
92
|
/** Add or remove image from selection */
|
|
91
93
|
toggleSelection: (imageId: string) => void;
|
|
92
94
|
/** Select all images */
|