Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/component/hooks/useActiveSpectra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { useChartData } from '../context/ChartContext.js';
import { getActiveSpectra } from '../reducer/helper/getActiveSpectra.js';

export function useActiveSpectra() {
const state = useChartData();
return useMemo(() => getActiveSpectra(state), [state]);
const {
view: { spectra },
} = useChartData();
return useMemo(() => getActiveSpectra(spectra), [spectra]);
}
143 changes: 69 additions & 74 deletions src/component/hooks/useCheckToolsVisibility.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { Info1D, Info2D } from '@zakodium/nmr-types';
import { useCallback } from 'react';

import { useChartData } from '../context/ChartContext.js';
Expand All @@ -7,102 +6,98 @@ import type { MainTool, ToolOptionItem } from '../toolbar/ToolTypes.js';
import { options } from '../toolbar/ToolTypes.js';

import useCheckExperimentalFeature from './useCheckExperimentalFeature.js';
import useSpectrum from './useSpectrum.js';
import { useSelectedSpectra } from './useSelectedSpectra.ts';
import useSpectraByActiveNucleus from './useSpectraPerNucleus.ts';

type SpectrumInfo = Info1D | Info2D;

export interface CheckOptions {
checkSpectrumType?: boolean;
checkMode?: boolean;
extraInfoCheckParameters?: SpectrumInfo;
}

export function useCheckToolsVisibility(): (
toolKey: MainTool,
checkOptions?: CheckOptions,
) => boolean {
export function useCheckToolsVisibility(): (toolKey: MainTool) => boolean {
const { displayerMode } = useChartData();
const preferences = usePreferences();
const spectrum = useSpectrum(null);
const selectedSpectra = useSelectedSpectra();
const spectra = useSpectraByActiveNucleus();
const isExperimentalFeatureActivated = useCheckExperimentalFeature();
const toolbarButtons = preferences?.current?.display?.toolBarButtons;

return useCallback(
(toolKey: MainTool, checkOptions: CheckOptions = {}) => {
(toolKey: MainTool): boolean => {
const {
checkMode = true,
checkSpectrumType = true,
extraInfoCheckParameters,
} = checkOptions;

const { spectraOptions, mode, isExperimental } = options[toolKey];
spectraFilter,
spectraMatch = 'all',
selectedSpectra: selectionRules = { min: 1, max: 1 },
mode,
isExperimental,
} = options[toolKey];

// TODO: make sure preferences are not a lie and remove the optional chaining.
const flag =
preferences?.current?.display?.toolBarButtons?.[toolKey] ?? false;

const modeFlag =
!checkMode || (checkMode && (!mode || displayerMode === mode));

const spectrumCheckFlag =
!checkSpectrumType ||
(checkSpectrumType && checkSpectrum(spectrum, spectraOptions));
// 1. Tool status
const flag = toolbarButtons?.[toolKey] ?? false;

const isToolActivated =
(flag && !isExperimental) ||
(isExperimental && isExperimentalFeatureActivated);
return !!(
isToolActivated &&
modeFlag &&
spectrumCheckFlag &&
(!extraInfoCheckParameters ||
checkInfo(extraInfoCheckParameters, spectrum?.info))
);
},

[displayerMode, isExperimentalFeatureActivated, preferences, spectrum],
);
}
if (!isToolActivated) return false;

function checkSpectrum(
spectrum: any,
options: ToolOptionItem['spectraOptions'],
) {
let outerConditionResult = false;
// 2. Mode check
if (mode && displayerMode !== mode) return false;

if (!options) {
return true;
}
// 3. No spectra rules, always visible
if (!spectraFilter) return true;

// 4. Resolve spectra source
const spectraToCheck =
selectedSpectra && selectedSpectra.length > 0
? selectedSpectra
: spectra;

for (const option of options) {
let innerConditionFlag = true;
// 5. Selection constraints
if (selectionRules) {
const { min, max } = selectionRules;

if (option.active) {
if (spectrum) {
for (const { key, value } of option.info || []) {
if (spectrum.info[key] !== value) {
innerConditionFlag = false;
}
if (typeof min === 'number' && spectraToCheck.length < min) {
return false;
}

if (typeof max === 'number' && spectraToCheck.length > max) {
return false;
}
} else {
innerConditionFlag = false;
}
}

outerConditionResult = outerConditionResult || innerConditionFlag;
}
// 6. Evaluate spectra filters
const matchCount = spectraToCheck.filter((spectrum) =>
checkSpectrum(spectrum, spectraFilter),
).length;

return outerConditionResult;
// 7. Match strategy
if (spectraMatch === 'any') {
return matchCount > 0;
}

return matchCount === spectraToCheck.length;
},
[
displayerMode,
isExperimentalFeatureActivated,
toolbarButtons,
selectedSpectra,
spectra,
],
);
}

function checkInfo(checkParameters: SpectrumInfo, data: SpectrumInfo) {
for (const key in checkParameters) {
if (
checkParameters[key as keyof SpectrumInfo] !==
data[key as keyof SpectrumInfo]
) {
return false;
}
function checkSpectrum(
spectrum: any,
spectraFilter: ToolOptionItem['spectraFilter'],
): boolean {
if (!spectraFilter) return true;

for (const option of spectraFilter) {
if (!spectrum) continue;

const infoConditionsMet = (option.info ?? []).every(
({ key, value }) => spectrum.info[key] === value,
);

if (infoConditionsMet) return true;
}

return true;
return false;
}
1 change: 0 additions & 1 deletion src/component/hooks/useSelectedSpectra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { useActiveSpectra } from './useActiveSpectra.ts';
export function useSelectedSpectra() {
const activeSpectrum = useActiveSpectra();
const { data } = useChartData();

return useMemo<Spectrum[] | null>(() => {
const spectra = [];

Expand Down
11 changes: 8 additions & 3 deletions src/component/reducer/actions/DomainActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,13 @@ function setDomain(draft: Draft<State>, options?: SetDomainOptions) {
}

function setMode(draft: Draft<State>) {
const { xDomains, view, data, displayerMode } = draft;
const nucleus = view.spectra.activeTab;
const {
xDomains,
view: { spectra },
data,
displayerMode,
} = draft;
const { activeTab: nucleus } = spectra;

if (displayerMode === '1D') {
const spectrum = data.find(
Expand All @@ -282,7 +287,7 @@ function setMode(draft: Draft<State>) {
);
draft.mode = spectrum && isFid1DSpectrum(spectrum) ? 'LTR' : 'RTL';
} else {
const activeSpectra = getActiveSpectra(draft);
const activeSpectra = getActiveSpectra(spectra);
let hasFt: boolean;
if (Array.isArray(activeSpectra) && activeSpectra?.length > 0) {
hasFt = activeSpectra.some((spectrum) =>
Expand Down
14 changes: 9 additions & 5 deletions src/component/reducer/actions/PeaksActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,18 @@ function handleAutoPeakPicking(
action: AutoPeaksPickingAction,
) {
const { options, defaultPeakShape } = action.payload;

const activeSpectra = getActiveSpectra(draft);
const {
view: { spectra },
xDomain,
toolOptions,
} = draft;
const activeSpectra = getActiveSpectra(spectra);

if (!activeSpectra || activeSpectra.length === 0) {
return;
}

const [from, to] = draft.xDomain;
const [from, to] = xDomain;

for (const activeSpectrum of activeSpectra) {
const spectrum = getSpectrum(draft, activeSpectrum.index);
Expand All @@ -205,8 +209,8 @@ function handleAutoPeakPicking(
spectrum.peaks.values = spectrum.peaks.values.concat(peaks);
}

draft.toolOptions.selectedTool = 'zoom';
draft.toolOptions.selectedOptionPanel = null;
toolOptions.selectedTool = 'zoom';
toolOptions.selectedOptionPanel = null;
}

//action
Expand Down
22 changes: 13 additions & 9 deletions src/component/reducer/actions/SpectraActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,14 +295,14 @@ function handleChangeActiveSpectrum(
action: ChangeActiveSpectrumAction,
) {
const {
view: {
spectra: { activeTab, selectReferences, activeSpectra },
},
view: { spectra: viewSpectra },
data,
toolOptions,
} = draft;

const { activeTab, selectReferences, activeSpectra } = viewSpectra;
const { modifier, id, sortedSpectra } = action.payload;
const spectra = getActiveSpectra(draft);
const spectra = getActiveSpectra(viewSpectra);

//get the spectra that its nucleus match the active tab
const spectraPerNucleus = getSpectraByNucleus(
Expand Down Expand Up @@ -472,13 +472,17 @@ function resolveDeleteSpectraIDs(
draft: Draft<State>,
action: DeleteSpectraAction,
): SpectraEntry[] {
const activeSpectra = getActiveSpectra(draft);
const {
view: { spectra },
data,
} = draft;
const activeSpectra = getActiveSpectra(spectra);
const { ids, spectrumSource } = action?.payload || {};
const result: SpectraEntry[] = [];

if (spectrumSource) {
for (let index = 0; index < draft.data.length; index++) {
const { info, id } = draft.data[index];
for (let index = 0; index < data.length; index++) {
const { info, id } = data[index];
if (info?.spectrumSource === spectrumSource) {
result.push({ id, index });
}
Expand All @@ -490,8 +494,8 @@ function resolveDeleteSpectraIDs(
if (ids) {
const remainingIDs = new Set(ids);

for (let index = 0; index < draft.data.length; index++) {
const { id } = draft.data[index];
for (let index = 0; index < data.length; index++) {
const { id } = data[index];
if (remainingIDs.has(id)) {
result.push({ id, index });
remainingIDs.delete(id);
Expand Down
13 changes: 7 additions & 6 deletions src/component/reducer/actions/ToolsActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,10 @@ function handleZoom(draft: Draft<State>, action: ZoomAction) {
}

case '1D': {
const activeSpectra = getActiveSpectra(draft);
const {
view: { spectra },
} = draft;
const activeSpectra = getActiveSpectra(spectra);

// Horizontal zoom in/out 1d spectra by mouse wheel
if (shiftKey || isBidirectionalZoom) {
Expand Down Expand Up @@ -612,12 +615,10 @@ function levelChangeHandler(draft: Draft<State>, action: LevelChangeAction) {
const { deltaY, altKey, invertScroll } = action.payload.options;
const {
data,
view: {
spectraContourLevels,
spectra: { activeTab },
},
view: { spectraContourLevels, spectra: viewSpectra },
} = draft;
const activeSpectra = getActiveSpectra(draft) || [];
const { activeTab } = viewSpectra;
const activeSpectra = getActiveSpectra(viewSpectra) || [];

const activeSpectraObj: Record<string, true> = {};
for (const activeSpectrum of activeSpectra) {
Expand Down
9 changes: 5 additions & 4 deletions src/component/reducer/helper/getActiveSpectra.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { ViewState } from '@zakodium/nmrium-core';
import type { Draft } from 'immer';

import type { State } from '../Reducer.js';

export function getActiveSpectra(state: Draft<State> | State) {
const { activeSpectra, activeTab } = state.view.spectra;
export function getActiveSpectra(
viewSpectraState: Draft<ViewState['spectra']> | ViewState['spectra'],
) {
const { activeSpectra, activeTab } = viewSpectraState;
const spectra = activeSpectra?.[activeTab]?.filter(
(spectrum) => spectrum?.selected,
);
Expand Down
5 changes: 4 additions & 1 deletion src/component/reducer/helper/getActiveSpectraAsObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import { getActiveSpectra } from './getActiveSpectra.js';
export function getActiveSpectraAsObject(
state: Draft<State> | State,
): Record<string, number> | null {
const activeSpectra = getActiveSpectra(state);
const {
view: { spectra },
} = state;
const activeSpectra = getActiveSpectra(spectra);

if (!activeSpectra || activeSpectra?.length === 0) return null;

Expand Down
Loading
Loading