Skip to content

Commit 407416b

Browse files
authored
feat: supports ProcessingOperatorUI.Tool (#4287)
Experimental: true
1 parent 7bc184e commit 407416b

18 files changed

Lines changed: 486 additions & 246 deletions

package-lock.json

Lines changed: 31 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@
7070
"@tanstack/react-store": "^0.11.0",
7171
"@tanstack/react-table": "^8.21.3",
7272
"@zakodium/nmr-types": "^0.5.21",
73-
"@zakodium/nmrium-core": "^0.7.49",
74-
"@zakodium/nmrium-core-plugins": "^0.7.65",
73+
"@zakodium/nmrium-core": "^0.7.50",
74+
"@zakodium/nmrium-core-plugins": "^0.7.66",
7575
"@zakodium/pdnd-esm": "^1.1.0",
7676
"@zakodium/utils": "^0.5.0",
7777
"@zip.js/zip.js": "^2.8.33",
@@ -120,6 +120,7 @@
120120
"react-table": "^7.8.0",
121121
"smart-array-filter": "^5.0.0",
122122
"ts-pattern": "^5.9.0",
123+
"usehooks-ts": "^3.1.1",
123124
"yup": "^1.7.1",
124125
"zod": "^4.4.3"
125126
},

src/component/panels/hooks/use_processings_mutation.ts renamed to src/component/context/processings_mutations_context.api.ts

Lines changed: 139 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,37 @@ import {
99
sliceData2D,
1010
sliceSpectrum,
1111
} from '@zakodium/nmrium-core';
12-
import { assertDefined, assertUnreachable, noop } from '@zakodium/utils';
12+
import {
13+
assertDefined,
14+
assertNotNullish,
15+
assertUnreachable,
16+
noop,
17+
} from '@zakodium/utils';
1318
import type { Draft } from 'immer';
14-
15-
import { initializeContoursLevels } from '../../../data/data2d/Spectrum2D/contours.ts';
16-
import { useChartData } from '../../context/ChartContext.tsx';
17-
import { useCore } from '../../context/CoreContext.tsx';
18-
import { useDispatch } from '../../context/DispatchContext.tsx';
19-
import type { State } from '../../reducer/Reducer.ts';
20-
import { setDomain, setMode } from '../../reducer/actions/DomainActions.ts';
21-
import { updateView } from '../../reducer/actions/FiltersActions.ts';
22-
import { resetSelectedTool } from '../../reducer/actions/ToolsActions.ts';
23-
import zoomHistoryManager from '../../reducer/helper/ZoomHistoryManager.ts';
24-
import { getActiveSpectrum } from '../../reducer/helper/getActiveSpectrum.ts';
25-
26-
export type ProcessingsMutations = ReturnType<typeof useProcessingsMutations>;
27-
28-
export function useProcessingsMutations() {
19+
import { useMemo } from 'react';
20+
import { useAccordionControls } from 'react-science/ui';
21+
import { useEventCallback } from 'usehooks-ts';
22+
23+
import { initializeContoursLevels } from '../../data/data2d/Spectrum2D/contours.ts';
24+
import type { State } from '../reducer/Reducer.ts';
25+
import { setDomain, setMode } from '../reducer/actions/DomainActions.ts';
26+
import { updateView } from '../reducer/actions/FiltersActions.ts';
27+
import zoomHistoryManager from '../reducer/helper/ZoomHistoryManager.ts';
28+
import { getActiveSpectrum } from '../reducer/helper/getActiveSpectrum.ts';
29+
30+
import { useChartData } from './ChartContext.tsx';
31+
import { useCore } from './CoreContext.tsx';
32+
import { useDispatch } from './DispatchContext.tsx';
33+
34+
export type ProcessingsMutations = ReturnType<
35+
typeof useProcessingsMutationsAPI
36+
>;
37+
38+
export function useProcessingsMutationsAPI() {
2939
const core = useCore();
3040
const state = useChartData();
3141
const dispatch = useDispatch();
42+
const { open: openPanel } = useAccordionControls();
3243

3344
function setIsLoading(isLoading: boolean) {
3445
dispatch({
@@ -83,9 +94,25 @@ export function useProcessingsMutations() {
8394
});
8495
}
8596

97+
function resetSelectedTool() {
98+
dispatch({
99+
type: 'SELECT_PROCESSING_OPERATOR',
100+
payload: { operatorId: undefined },
101+
});
102+
}
103+
86104
// --- API --- //
87105

88-
async function apply(
106+
const resetLiveChange = useEventCallback(function resetLiveChange() {
107+
dispatch({
108+
type: 'SET_SPECTRUM_LIVE_PROCESSED',
109+
payload: {
110+
spectrumLiveProcessed: undefined,
111+
},
112+
});
113+
});
114+
115+
const apply = useEventCallback(async function apply(
89116
operation: SpectrumProcessingOperation<any, any>,
90117
indexOperation: number,
91118
) {
@@ -96,6 +123,7 @@ export function useProcessingsMutations() {
96123

97124
spectrum.processings[indexOperation] = operation;
98125

126+
resetSelectedTool();
99127
resetLiveChange();
100128
await submit(spectrum, indexSpectrum, (draft) => {
101129
const {
@@ -106,9 +134,12 @@ export function useProcessingsMutations() {
106134
} = core.getOperator(operation.operatorId) ?? {};
107135
updateView(draft, domainUpdateRules);
108136
});
109-
}
137+
});
110138

111-
async function reorder(sourceIndex: number, targetIndex: number) {
139+
const reorder = useEventCallback(async function reorder(
140+
sourceIndex: number,
141+
targetIndex: number,
142+
) {
112143
const { spectrum, indexSpectrum } = getSpectrum();
113144
if (!spectrum?.processings) return;
114145

@@ -118,23 +149,23 @@ export function useProcessingsMutations() {
118149
];
119150

120151
await submit(spectrum, indexSpectrum, noop);
121-
}
152+
});
122153

123-
async function remove(uid: string) {
154+
const remove = useEventCallback(async function remove(uid: string) {
124155
const { spectrum, indexSpectrum } = getSpectrum();
125156
if (!spectrum?.processings) return;
126157

127158
spectrum.processings = spectrum.processings.filter((p) => p.uid !== uid);
128159

129160
await submit(spectrum, indexSpectrum, (draft) => {
130161
draft.toolOptions.data.activeFilterID = null;
131-
resetSelectedTool(draft);
162+
resetSelectedTool();
132163
setDomain(draft);
133164
setMode(draft);
134165
});
135-
}
166+
});
136167

137-
async function removeAll() {
168+
const removeAll = useEventCallback(async function removeAll() {
138169
const { spectrum, indexSpectrum } = getSpectrum();
139170

140171
if (!spectrum?.processings) return;
@@ -144,13 +175,15 @@ export function useProcessingsMutations() {
144175

145176
await submit(spectrum, indexSpectrum, (draft) => {
146177
draft.toolOptions.data.activeFilterID = null;
147-
resetSelectedTool(draft);
178+
resetSelectedTool();
148179
setDomain(draft);
149180
setMode(draft);
150181
});
151-
}
182+
});
152183

153-
async function switchEnabled(uid: string) {
184+
const switchEnabled = useEventCallback(async function switchEnabled(
185+
uid: string,
186+
) {
154187
const { spectrum, indexSpectrum } = getSpectrum();
155188
if (!spectrum?.processings) return;
156189

@@ -166,7 +199,7 @@ export function useProcessingsMutations() {
166199
initializeContoursLevels(processedSpectrum);
167200
}
168201

169-
resetSelectedTool(draft);
202+
resetSelectedTool();
170203
setDomain(draft);
171204
setMode(draft);
172205

@@ -181,10 +214,13 @@ export function useProcessingsMutations() {
181214
draft.yDomain = zoomValue.yDomain;
182215
}
183216
});
184-
}
217+
});
185218

186219
// Related to live update
187-
async function prepareLiveChange(uid: string, shouldProcessAll: boolean) {
220+
const prepareLiveChange = useEventCallback(async function prepareLiveChange(
221+
uid: string,
222+
shouldProcessAll: boolean,
223+
) {
188224
const { spectrum } = getSpectrum();
189225
if (!spectrum?.processings) return;
190226

@@ -237,18 +273,9 @@ export function useProcessingsMutations() {
237273
spectrumLiveProcessed: processedSpectrum,
238274
},
239275
});
240-
}
241-
242-
function resetLiveChange() {
243-
dispatch({
244-
type: 'SET_SPECTRUM_LIVE_PROCESSED',
245-
payload: {
246-
spectrumLiveProcessed: undefined,
247-
},
248-
});
249-
}
276+
});
250277

251-
async function applyLiveChange(
278+
const applyLiveChange = useEventCallback(async function applyLiveChange(
252279
operation: SpectrumProcessingOperation<any, any>,
253280
shouldProcessAll: boolean,
254281
) {
@@ -278,16 +305,76 @@ export function useProcessingsMutations() {
278305
spectrumLiveProcessed: processedSpectrum,
279306
},
280307
});
281-
}
308+
});
309+
310+
const triggerOperation = useEventCallback(async function triggerOperation(
311+
operation: SpectrumProcessingOperation<any, any>,
312+
) {
313+
const { spectrum, indexSpectrum } = getSpectrum();
314+
if (!spectrum) return;
282315

283-
return {
284-
apply,
285-
reorder,
286-
remove,
287-
removeAll,
288-
switchEnabled,
289-
prepareLiveChange,
290-
resetLiveChange,
291-
applyLiveChange,
292-
};
316+
spectrum.processings ??= [];
317+
let operationIndex = spectrum.processings.findIndex(
318+
(processing) =>
319+
processing.uid === operation.uid ||
320+
processing.operatorId === operation.operatorId,
321+
);
322+
323+
if (operationIndex === -1) {
324+
spectrum.processings.push(operation);
325+
operationIndex = spectrum.processings.length - 1;
326+
}
327+
328+
operation = spectrum.processings[operationIndex];
329+
330+
const operatorUI = core.slotOperator(operation.operatorId);
331+
const operator = core.getOperator(operation.operatorId);
332+
assertNotNullish(operatorUI);
333+
assertNotNullish(operator);
334+
335+
openPanel('processingsPanel');
336+
resetLiveChange();
337+
await submit(spectrum, indexSpectrum, (draft) =>
338+
updateView(draft, operator.domainUpdateRules),
339+
);
340+
341+
if (operatorUI.isEditable) {
342+
dispatch({
343+
type: 'SELECT_PROCESSING_OPERATOR',
344+
payload: { operatorId: operation.operatorId },
345+
});
346+
}
347+
348+
if (operatorUI.isLiveEditable) {
349+
await prepareLiveChange(
350+
operation.uid,
351+
operatorUI.defaultShouldProcessAll ?? false,
352+
);
353+
}
354+
});
355+
356+
return useMemo(
357+
() => ({
358+
apply,
359+
reorder,
360+
remove,
361+
removeAll,
362+
switchEnabled,
363+
prepareLiveChange,
364+
resetLiveChange,
365+
applyLiveChange,
366+
triggerOperation,
367+
}),
368+
[
369+
apply,
370+
applyLiveChange,
371+
prepareLiveChange,
372+
remove,
373+
removeAll,
374+
reorder,
375+
resetLiveChange,
376+
switchEnabled,
377+
triggerOperation,
378+
],
379+
);
293380
}

0 commit comments

Comments
 (0)