OHIF-276: Fix UI performance issues related to ToolbarService (#1969)
This commit is contained in:
parent
e4092d0349
commit
ae3d05ebf7
@ -4,56 +4,10 @@ import { SidePanel, ErrorBoundary } from '@ohif/ui';
|
|||||||
import Header from './Header.jsx';
|
import Header from './Header.jsx';
|
||||||
import NestedMenu from './ToolbarButtonNestedMenu.jsx';
|
import NestedMenu from './ToolbarButtonNestedMenu.jsx';
|
||||||
|
|
||||||
function ViewerLayout({
|
// TODO: Having ToolbarPrimary and ToolbarSecondary is ugly, but
|
||||||
// From Extension Module Params
|
// these are going to be unified shortly so this is good enough for now.
|
||||||
extensionManager,
|
function ToolbarPrimary({servicesManager}) {
|
||||||
servicesManager,
|
|
||||||
commandsManager,
|
|
||||||
// From Modes
|
|
||||||
leftPanels,
|
|
||||||
rightPanels,
|
|
||||||
viewports,
|
|
||||||
children,
|
|
||||||
ViewportGridComp,
|
|
||||||
}) {
|
|
||||||
const { ToolBarService } = servicesManager.services;
|
const { ToolBarService } = servicesManager.services;
|
||||||
/**
|
|
||||||
* Set body classes (tailwindcss) that don't allow vertical
|
|
||||||
* or horizontal overflow (no scrolling). Also guarantee window
|
|
||||||
* is sized to our viewport.
|
|
||||||
*/
|
|
||||||
useEffect(() => {
|
|
||||||
document.body.classList.add('bg-black');
|
|
||||||
document.body.classList.add('overflow-hidden');
|
|
||||||
return () => {
|
|
||||||
document.body.classList.remove('bg-black');
|
|
||||||
document.body.classList.remove('overflow-hidden');
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const getPanelData = id => {
|
|
||||||
const entry = extensionManager.getModuleEntry(id);
|
|
||||||
// TODO, not sure why sidepanel content has to be JSX, and not a children prop?
|
|
||||||
const content = entry.component;
|
|
||||||
|
|
||||||
return {
|
|
||||||
iconName: entry.iconName,
|
|
||||||
iconLabel: entry.iconLabel,
|
|
||||||
label: entry.label,
|
|
||||||
name: entry.name,
|
|
||||||
content,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const getViewportComponentData = viewportComponent => {
|
|
||||||
const entry = extensionManager.getModuleEntry(viewportComponent.namespace);
|
|
||||||
|
|
||||||
return {
|
|
||||||
component: entry.component,
|
|
||||||
displaySetsToDisplay: viewportComponent.displaySetsToDisplay,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultTool = {
|
const defaultTool = {
|
||||||
icon: 'tool-more-menu',
|
icon: 'tool-more-menu',
|
||||||
label: 'More',
|
label: 'More',
|
||||||
@ -99,6 +53,141 @@ function ViewerLayout({
|
|||||||
return unsubscribe;
|
return unsubscribe;
|
||||||
}, [ToolBarService]);
|
}, [ToolBarService]);
|
||||||
|
|
||||||
|
return <>
|
||||||
|
{toolbars.primary.map((toolDef, index) => {
|
||||||
|
const isNested = Array.isArray(toolDef);
|
||||||
|
if (!isNested) {
|
||||||
|
const { id, Component, componentProps } = toolDef;
|
||||||
|
return <Component key={id} id={id} {...componentProps} />;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<NestedMenu
|
||||||
|
key={index}
|
||||||
|
isActive={activeTool.isActive}
|
||||||
|
icon={activeTool.icon}
|
||||||
|
label={activeTool.label}
|
||||||
|
>
|
||||||
|
<div className="flex">
|
||||||
|
{toolDef.map(x => {
|
||||||
|
const { id, Component, componentProps } = x;
|
||||||
|
return (
|
||||||
|
<Component key={id} id={id} {...componentProps} />
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</NestedMenu>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
function ToolbarSecondary({servicesManager}) {
|
||||||
|
const { ToolBarService } = servicesManager.services;
|
||||||
|
const defaultTool = {
|
||||||
|
icon: 'tool-more-menu',
|
||||||
|
label: 'More',
|
||||||
|
isActive: false,
|
||||||
|
};
|
||||||
|
const [toolbars, setToolbars] = useState({ primary: [], secondary: [] });
|
||||||
|
const [activeTool, setActiveTool] = useState(defaultTool);
|
||||||
|
|
||||||
|
const setActiveToolHandler = (tool, isNested) => {
|
||||||
|
setActiveTool(isNested ? tool : defaultTool);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPrimaryClickHandler = (evt, btn) => {
|
||||||
|
if (
|
||||||
|
btn.props &&
|
||||||
|
btn.props.commands &&
|
||||||
|
evt.value &&
|
||||||
|
btn.props.commands[evt.value]
|
||||||
|
) {
|
||||||
|
const { commandName, commandOptions } = btn.props.commands[evt.value];
|
||||||
|
commandsManager.runCommand(commandName, commandOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const { unsubscribe } = ToolBarService.subscribe(
|
||||||
|
ToolBarService.EVENTS.TOOL_BAR_MODIFIED,
|
||||||
|
() => {
|
||||||
|
console.warn('~~~ TOOL BAR MODIFIED EVENT CAUGHT');
|
||||||
|
const updatedToolbars = {
|
||||||
|
primary: ToolBarService.getButtonSection('primary', {
|
||||||
|
onClick: onPrimaryClickHandler,
|
||||||
|
setActiveTool: setActiveToolHandler,
|
||||||
|
}),
|
||||||
|
secondary: ToolBarService.getButtonSection('secondary', {
|
||||||
|
setActiveTool: setActiveToolHandler,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
setToolbars(updatedToolbars);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return unsubscribe;
|
||||||
|
}, [ToolBarService]);
|
||||||
|
|
||||||
|
return <>
|
||||||
|
{toolbars.secondary.map(toolDef => {
|
||||||
|
const { id, Component, componentProps } = toolDef;
|
||||||
|
return <Component key={id} id={id} {...componentProps} />;
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ViewerLayout({
|
||||||
|
// From Extension Module Params
|
||||||
|
extensionManager,
|
||||||
|
servicesManager,
|
||||||
|
commandsManager,
|
||||||
|
// From Modes
|
||||||
|
leftPanels,
|
||||||
|
rightPanels,
|
||||||
|
viewports,
|
||||||
|
children,
|
||||||
|
ViewportGridComp,
|
||||||
|
}) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set body classes (tailwindcss) that don't allow vertical
|
||||||
|
* or horizontal overflow (no scrolling). Also guarantee window
|
||||||
|
* is sized to our viewport.
|
||||||
|
*/
|
||||||
|
useEffect(() => {
|
||||||
|
document.body.classList.add('bg-black');
|
||||||
|
document.body.classList.add('overflow-hidden');
|
||||||
|
return () => {
|
||||||
|
document.body.classList.remove('bg-black');
|
||||||
|
document.body.classList.remove('overflow-hidden');
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getPanelData = id => {
|
||||||
|
const entry = extensionManager.getModuleEntry(id);
|
||||||
|
// TODO, not sure why sidepanel content has to be JSX, and not a children prop?
|
||||||
|
const content = entry.component;
|
||||||
|
|
||||||
|
return {
|
||||||
|
iconName: entry.iconName,
|
||||||
|
iconLabel: entry.iconLabel,
|
||||||
|
label: entry.label,
|
||||||
|
name: entry.name,
|
||||||
|
content,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getViewportComponentData = viewportComponent => {
|
||||||
|
const entry = extensionManager.getModuleEntry(viewportComponent.namespace);
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: entry.component,
|
||||||
|
displaySetsToDisplay: viewportComponent.displaySetsToDisplay,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const leftPanelComponents = leftPanels.map(getPanelData);
|
const leftPanelComponents = leftPanels.map(getPanelData);
|
||||||
const rightPanelComponents = rightPanels.map(getPanelData);
|
const rightPanelComponents = rightPanels.map(getPanelData);
|
||||||
const viewportComponents = viewports.map(getViewportComponentData);
|
const viewportComponents = viewports.map(getViewportComponentData);
|
||||||
@ -108,31 +197,7 @@ function ViewerLayout({
|
|||||||
<Header>
|
<Header>
|
||||||
<ErrorBoundary context="Primary Toolbar">
|
<ErrorBoundary context="Primary Toolbar">
|
||||||
<div className="relative flex justify-center">
|
<div className="relative flex justify-center">
|
||||||
{toolbars.primary.map((toolDef, index) => {
|
<ToolbarPrimary servicesManager={servicesManager}/>
|
||||||
const isNested = Array.isArray(toolDef);
|
|
||||||
if (!isNested) {
|
|
||||||
const { id, Component, componentProps } = toolDef;
|
|
||||||
return <Component key={id} id={id} {...componentProps} />;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<NestedMenu
|
|
||||||
key={index}
|
|
||||||
isActive={activeTool.isActive}
|
|
||||||
icon={activeTool.icon}
|
|
||||||
label={activeTool.label}
|
|
||||||
>
|
|
||||||
<div className="flex">
|
|
||||||
{toolDef.map(x => {
|
|
||||||
const { id, Component, componentProps } = x;
|
|
||||||
return (
|
|
||||||
<Component key={id} id={id} {...componentProps} />
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</NestedMenu>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Header>
|
</Header>
|
||||||
@ -155,10 +220,7 @@ function ViewerLayout({
|
|||||||
<div className="flex h-12 border-b border-transparent flex-2 w-100">
|
<div className="flex h-12 border-b border-transparent flex-2 w-100">
|
||||||
<ErrorBoundary context="Secondary Toolbar">
|
<ErrorBoundary context="Secondary Toolbar">
|
||||||
<div className="flex items-center w-full px-3 bg-primary-dark">
|
<div className="flex items-center w-full px-3 bg-primary-dark">
|
||||||
{toolbars.secondary.map(toolDef => {
|
<ToolbarSecondary servicesManager={servicesManager}/>
|
||||||
const { id, Component, componentProps } = toolDef;
|
|
||||||
return <Component key={id} id={id} {...componentProps} />;
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user