mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui): restore all panel hotkeys
This commit is contained in:
@@ -24,53 +24,9 @@ const onLeftPanelCollapse = (isCollapsed: boolean) => $isLeftPanelOpen.set(!isCo
|
||||
const onRightPanelCollapse = (isCollapsed: boolean) => $isRightPanelOpen.set(!isCollapsed);
|
||||
|
||||
export const AppContent = memo(() => {
|
||||
// const tab = useAppSelector(selectActiveTab);
|
||||
const tabIndex = useAppSelector(selectActiveTabIndex);
|
||||
// const imperativePanelGroupRef = useRef<ImperativePanelGroupHandle>(null);
|
||||
useDndMonitor();
|
||||
|
||||
// const withLeftPanel = useAppSelector(selectWithLeftPanel);
|
||||
// const leftPanelUsePanelOptions = useMemo<UsePanelOptions>(
|
||||
// () => ({
|
||||
// id: 'left-panel',
|
||||
// minSizePx: LEFT_PANEL_MIN_SIZE_PX,
|
||||
// defaultSizePx: LEFT_PANEL_MIN_SIZE_PX,
|
||||
// imperativePanelGroupRef,
|
||||
// panelGroupDirection: 'horizontal',
|
||||
// onCollapse: onLeftPanelCollapse,
|
||||
// }),
|
||||
// []
|
||||
// );
|
||||
// const leftPanel = usePanel(leftPanelUsePanelOptions);
|
||||
// useRegisteredHotkeys({
|
||||
// id: 'toggleLeftPanel',
|
||||
// category: 'app',
|
||||
// callback: leftPanel.toggle,
|
||||
// options: { enabled: withLeftPanel },
|
||||
// dependencies: [leftPanel.toggle, withLeftPanel],
|
||||
// });
|
||||
|
||||
// const withRightPanel = useAppSelector(selectWithRightPanel);
|
||||
// const rightPanelUsePanelOptions = useMemo<UsePanelOptions>(
|
||||
// () => ({
|
||||
// id: 'right-panel',
|
||||
// minSizePx: RIGHT_PANEL_MIN_SIZE_PX,
|
||||
// defaultSizePx: RIGHT_PANEL_MIN_SIZE_PX,
|
||||
// imperativePanelGroupRef,
|
||||
// panelGroupDirection: 'horizontal',
|
||||
// onCollapse: onRightPanelCollapse,
|
||||
// }),
|
||||
// []
|
||||
// );
|
||||
// const rightPanel = usePanel(rightPanelUsePanelOptions);
|
||||
// useRegisteredHotkeys({
|
||||
// id: 'toggleRightPanel',
|
||||
// category: 'app',
|
||||
// callback: rightPanel.toggle,
|
||||
// options: { enabled: withRightPanel },
|
||||
// dependencies: [rightPanel.toggle, withRightPanel],
|
||||
// });
|
||||
|
||||
// useRegisteredHotkeys({
|
||||
// id: 'resetPanelLayout',
|
||||
// category: 'app',
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useDeleteAllExceptCurrentQueueItemDialog } from 'features/queue/compone
|
||||
import { InvokeButtonTooltip } from 'features/queue/components/InvokeButtonTooltip/InvokeButtonTooltip';
|
||||
import { useDeleteCurrentQueueItem } from 'features/queue/hooks/useDeleteCurrentQueueItem';
|
||||
import { useInvoke } from 'features/queue/hooks/useInvoke';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { useAutoLayoutContext } from 'features/ui/layouts/auto-layout-context';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -54,11 +53,6 @@ FloatingCanvasLeftPanelButtons.displayName = 'FloatingCanvasLeftPanelButtons';
|
||||
|
||||
const ToggleLeftPanelButton = memo(() => {
|
||||
const { toggleLeftPanel } = useAutoLayoutContext();
|
||||
useRegisteredHotkeys({
|
||||
category: 'app',
|
||||
id: 'toggleLeftPanel',
|
||||
callback: toggleLeftPanel,
|
||||
});
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Tooltip label={t('accessibility.toggleLeftPanel')} placement="end">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Flex, IconButton, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { useAutoLayoutContext } from 'features/ui/layouts/auto-layout-context';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -17,11 +16,6 @@ FloatingRightPanelButtons.displayName = 'FloatingRightPanelButtons';
|
||||
const ToggleRightPanelButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const { toggleRightPanel } = useAutoLayoutContext();
|
||||
useRegisteredHotkeys({
|
||||
category: 'app',
|
||||
id: 'toggleRightPanel',
|
||||
callback: toggleRightPanel,
|
||||
});
|
||||
|
||||
return (
|
||||
<Tooltip label={t('accessibility.toggleRightPanel')} placement="start">
|
||||
|
||||
@@ -1,24 +1,106 @@
|
||||
import type { GridviewApi } from 'dockview';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import type { Atom } from 'nanostores';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { createContext, useContext, useMemo } from 'react';
|
||||
import { createContext, memo, useCallback, useContext, useMemo } from 'react';
|
||||
|
||||
import { LEFT_PANEL_ID, LEFT_PANEL_MIN_SIZE_PX, RIGHT_PANEL_ID, RIGHT_PANEL_MIN_SIZE_PX } from './shared';
|
||||
|
||||
type AutoLayoutContextValue = {
|
||||
$api: Atom<GridviewApi | null>;
|
||||
toggleLeftPanel: () => void;
|
||||
toggleRightPanel: () => void;
|
||||
toggleBothPanels: () => void;
|
||||
resetPanels: () => void;
|
||||
};
|
||||
|
||||
const AutoLayoutContext = createContext<AutoLayoutContextValue | null>(null);
|
||||
|
||||
export const AutoLayoutProvider = (props: PropsWithChildren<AutoLayoutContextValue>) => {
|
||||
const expandPanel = (api: GridviewApi, panelId: string, width: number) => {
|
||||
const panel = api.getPanel(panelId);
|
||||
if (!panel) {
|
||||
return;
|
||||
}
|
||||
panel.api.setConstraints({ maximumWidth: Number.MAX_SAFE_INTEGER, minimumWidth: width });
|
||||
panel.api.setSize({ width: width });
|
||||
};
|
||||
|
||||
const collapsePanel = (api: GridviewApi, panelId: string) => {
|
||||
const panel = api.getPanel(panelId);
|
||||
if (!panel) {
|
||||
return;
|
||||
}
|
||||
panel.api.setConstraints({ maximumWidth: 0, minimumWidth: 0 });
|
||||
panel.api.setSize({ width: 0 });
|
||||
};
|
||||
|
||||
const getIsCollapsed = (api: GridviewApi, panelId: string) => {
|
||||
const panel = api.getPanel(panelId);
|
||||
if (!panel) {
|
||||
return true; // ??
|
||||
}
|
||||
return panel.maximumWidth === 0;
|
||||
};
|
||||
|
||||
export const AutoLayoutProvider = (props: PropsWithChildren<{ $api: Atom<GridviewApi | null> }>) => {
|
||||
const toggleLeftPanel = useCallback(() => {
|
||||
const api = props.$api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
if (getIsCollapsed(api, LEFT_PANEL_ID)) {
|
||||
expandPanel(api, LEFT_PANEL_ID, LEFT_PANEL_MIN_SIZE_PX);
|
||||
} else {
|
||||
collapsePanel(api, LEFT_PANEL_ID);
|
||||
}
|
||||
}, [props.$api]);
|
||||
|
||||
const toggleRightPanel = useCallback(() => {
|
||||
const api = props.$api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
if (getIsCollapsed(api, RIGHT_PANEL_ID)) {
|
||||
expandPanel(api, RIGHT_PANEL_ID, RIGHT_PANEL_MIN_SIZE_PX);
|
||||
} else {
|
||||
collapsePanel(api, RIGHT_PANEL_ID);
|
||||
}
|
||||
}, [props.$api]);
|
||||
|
||||
const toggleBothPanels = useCallback(() => {
|
||||
const api = props.$api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
requestAnimationFrame(() => {
|
||||
if (getIsCollapsed(api, RIGHT_PANEL_ID) || getIsCollapsed(api, LEFT_PANEL_ID)) {
|
||||
expandPanel(api, LEFT_PANEL_ID, LEFT_PANEL_MIN_SIZE_PX);
|
||||
expandPanel(api, RIGHT_PANEL_ID, RIGHT_PANEL_MIN_SIZE_PX);
|
||||
} else {
|
||||
collapsePanel(api, LEFT_PANEL_ID);
|
||||
collapsePanel(api, RIGHT_PANEL_ID);
|
||||
}
|
||||
});
|
||||
}, [props.$api]);
|
||||
|
||||
const resetPanels = useCallback(() => {
|
||||
const api = props.$api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
expandPanel(api, LEFT_PANEL_ID, LEFT_PANEL_MIN_SIZE_PX);
|
||||
expandPanel(api, RIGHT_PANEL_ID, RIGHT_PANEL_MIN_SIZE_PX);
|
||||
}, [props.$api]);
|
||||
|
||||
const value = useMemo<AutoLayoutContextValue>(
|
||||
() => ({
|
||||
$api: props.$api,
|
||||
toggleLeftPanel: props.toggleLeftPanel,
|
||||
toggleRightPanel: props.toggleRightPanel,
|
||||
toggleLeftPanel,
|
||||
toggleRightPanel,
|
||||
toggleBothPanels,
|
||||
resetPanels,
|
||||
}),
|
||||
[props.$api, props.toggleLeftPanel, props.toggleRightPanel]
|
||||
[props.$api, resetPanels, toggleBothPanels, toggleLeftPanel, toggleRightPanel]
|
||||
);
|
||||
return <AutoLayoutContext.Provider value={value}>{props.children}</AutoLayoutContext.Provider>;
|
||||
};
|
||||
@@ -30,3 +112,30 @@ export const useAutoLayoutContext = () => {
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
export const PanelHotkeysLogical = memo(() => {
|
||||
const { toggleBothPanels, resetPanels, toggleLeftPanel, toggleRightPanel } = useAutoLayoutContext();
|
||||
useRegisteredHotkeys({
|
||||
category: 'app',
|
||||
id: 'toggleLeftPanel',
|
||||
callback: toggleLeftPanel,
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
category: 'app',
|
||||
id: 'toggleRightPanel',
|
||||
callback: toggleRightPanel,
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
category: 'app',
|
||||
id: 'resetPanelLayout',
|
||||
callback: resetPanels,
|
||||
});
|
||||
useRegisteredHotkeys({
|
||||
category: 'app',
|
||||
id: 'togglePanels',
|
||||
callback: toggleBothPanels,
|
||||
});
|
||||
|
||||
return null;
|
||||
});
|
||||
PanelHotkeysLogical.displayName = 'PanelHotkeysLogical';
|
||||
|
||||
@@ -6,18 +6,24 @@ import { BoardsPanel } from 'features/gallery/components/BoardsListPanelContent'
|
||||
import { GalleryPanel } from 'features/gallery/components/Gallery';
|
||||
import { GenerationProgressPanel } from 'features/gallery/components/ImageViewer/GenerationProgressPanel';
|
||||
import { ImageViewerPanel } from 'features/gallery/components/ImageViewer/ImageViewerPanel';
|
||||
import { FloatingLeftPanelButtons } from 'features/ui/components/FloatingLeftPanelButtons';
|
||||
import { FloatingCanvasLeftPanelButtons } from 'features/ui/components/FloatingLeftPanelButtons';
|
||||
import { FloatingRightPanelButtons } from 'features/ui/components/FloatingRightPanelButtons';
|
||||
import { AutoLayoutProvider } from 'features/ui/layouts/auto-layout-context';
|
||||
import { AutoLayoutProvider, PanelHotkeysLogical } from 'features/ui/layouts/auto-layout-context';
|
||||
import { TabWithoutCloseButton } from 'features/ui/layouts/TabWithoutCloseButton';
|
||||
import { LEFT_PANEL_MIN_SIZE_PX, RIGHT_PANEL_MIN_SIZE_PX } from 'features/ui/store/uiSlice';
|
||||
import { dockviewTheme } from 'features/ui/styles/theme';
|
||||
import { atom } from 'nanostores';
|
||||
import { memo, useCallback, useRef, useState } from 'react';
|
||||
|
||||
import { CanvasTabLeftPanel } from './CanvasTabLeftPanel';
|
||||
import { CanvasWorkspacePanel } from './CanvasWorkspacePanel';
|
||||
import { useOnFirstVisible } from './use-on-first-visible';
|
||||
import {
|
||||
LEFT_PANEL_ID,
|
||||
LEFT_PANEL_MIN_SIZE_PX,
|
||||
MAIN_PANEL_ID,
|
||||
RIGHT_PANEL_ID,
|
||||
RIGHT_PANEL_MIN_SIZE_PX,
|
||||
} from './shared';
|
||||
import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
|
||||
|
||||
const LAUNCHPAD_PANEL_ID = 'launchpad';
|
||||
const WORKSPACE_PANEL_ID = 'workspace';
|
||||
@@ -97,8 +103,9 @@ const MainPanel = memo(() => {
|
||||
onReady={onReadyMainPanel}
|
||||
theme={dockviewTheme}
|
||||
/>
|
||||
<FloatingLeftPanelButtons />
|
||||
<FloatingCanvasLeftPanelButtons />
|
||||
<FloatingRightPanelButtons />
|
||||
<PanelHotkeysLogical />
|
||||
</>
|
||||
);
|
||||
});
|
||||
@@ -160,10 +167,6 @@ const RightPanel = memo(() => {
|
||||
});
|
||||
RightPanel.displayName = 'RightPanel';
|
||||
|
||||
const LEFT_PANEL_ID = 'left';
|
||||
const MAIN_PANEL_ID = 'main';
|
||||
const RIGHT_PANEL_ID = 'right';
|
||||
|
||||
export const rootComponents: IGridviewReactProps['components'] = {
|
||||
[LEFT_PANEL_ID]: CanvasTabLeftPanel,
|
||||
[MAIN_PANEL_ID]: MainPanel,
|
||||
@@ -209,69 +212,10 @@ export const CanvasTabAutoLayout = memo(() => {
|
||||
},
|
||||
[$api]
|
||||
);
|
||||
const resizeMainPanelOnFirstVisible = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const mainPanel = api.getPanel(MAIN_PANEL_ID);
|
||||
if (!mainPanel) {
|
||||
return;
|
||||
}
|
||||
if (mainPanel.width !== 0) {
|
||||
return;
|
||||
}
|
||||
let count = 0;
|
||||
const setSize = () => {
|
||||
if (count++ > 50) {
|
||||
return;
|
||||
}
|
||||
mainPanel.api.setSize({ width: Number.MAX_SAFE_INTEGER });
|
||||
if (mainPanel.width === 0) {
|
||||
requestAnimationFrame(setSize);
|
||||
return;
|
||||
}
|
||||
};
|
||||
setSize();
|
||||
}, [$api]);
|
||||
useOnFirstVisible(ref, resizeMainPanelOnFirstVisible);
|
||||
const toggleLeftPanel = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const left = api.getPanel(LEFT_PANEL_ID);
|
||||
if (!left) {
|
||||
return;
|
||||
}
|
||||
if (left.maximumWidth === 0) {
|
||||
left.api.setConstraints({ maximumWidth: Number.MAX_SAFE_INTEGER, minimumWidth: LEFT_PANEL_MIN_SIZE_PX });
|
||||
left.api.setSize({ width: LEFT_PANEL_MIN_SIZE_PX });
|
||||
} else {
|
||||
left.api.setConstraints({ maximumWidth: 0, minimumWidth: 0 });
|
||||
left.api.setSize({ width: 0 });
|
||||
}
|
||||
}, [$api]);
|
||||
const toggleRightPanel = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const right = api.getPanel(RIGHT_PANEL_ID);
|
||||
if (!right) {
|
||||
return;
|
||||
}
|
||||
if (right.maximumWidth === 0) {
|
||||
right.api.setConstraints({ maximumWidth: Number.MAX_SAFE_INTEGER, minimumWidth: RIGHT_PANEL_MIN_SIZE_PX });
|
||||
right.api.setSize({ width: RIGHT_PANEL_MIN_SIZE_PX });
|
||||
} else {
|
||||
right.api.setConstraints({ maximumWidth: 0, minimumWidth: 0 });
|
||||
right.api.setSize({ width: 0 });
|
||||
}
|
||||
}, [$api]);
|
||||
useResizeMainPanelOnFirstVisit($api, ref);
|
||||
|
||||
return (
|
||||
<AutoLayoutProvider $api={$api} toggleLeftPanel={toggleLeftPanel} toggleRightPanel={toggleRightPanel}>
|
||||
<AutoLayoutProvider $api={$api}>
|
||||
<GridviewReact
|
||||
ref={ref}
|
||||
className="dockview-theme-invoke"
|
||||
|
||||
@@ -7,15 +7,21 @@ import { GenerationProgressPanel } from 'features/gallery/components/ImageViewer
|
||||
import { ImageViewerPanel } from 'features/gallery/components/ImageViewer/ImageViewerPanel';
|
||||
import { FloatingLeftPanelButtons } from 'features/ui/components/FloatingLeftPanelButtons';
|
||||
import { FloatingRightPanelButtons } from 'features/ui/components/FloatingRightPanelButtons';
|
||||
import { AutoLayoutProvider } from 'features/ui/layouts/auto-layout-context';
|
||||
import { AutoLayoutProvider, PanelHotkeysLogical } from 'features/ui/layouts/auto-layout-context';
|
||||
import { TabWithoutCloseButton } from 'features/ui/layouts/TabWithoutCloseButton';
|
||||
import { LEFT_PANEL_MIN_SIZE_PX, RIGHT_PANEL_MIN_SIZE_PX } from 'features/ui/store/uiSlice';
|
||||
import { dockviewTheme } from 'features/ui/styles/theme';
|
||||
import { atom } from 'nanostores';
|
||||
import { memo, useCallback, useRef, useState } from 'react';
|
||||
|
||||
import { GenerateTabLeftPanel } from './GenerateTabLeftPanel';
|
||||
import { useOnFirstVisible } from './use-on-first-visible';
|
||||
import {
|
||||
LEFT_PANEL_ID,
|
||||
LEFT_PANEL_MIN_SIZE_PX,
|
||||
MAIN_PANEL_ID,
|
||||
RIGHT_PANEL_ID,
|
||||
RIGHT_PANEL_MIN_SIZE_PX,
|
||||
} from './shared';
|
||||
import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
|
||||
|
||||
const LAUNCHPAD_PANEL_ID = 'launchpad';
|
||||
const VIEWER_PANEL_ID = 'viewer';
|
||||
@@ -86,6 +92,7 @@ const MainPanel = memo(() => {
|
||||
/>
|
||||
<FloatingLeftPanelButtons />
|
||||
<FloatingRightPanelButtons />
|
||||
<PanelHotkeysLogical />
|
||||
</>
|
||||
);
|
||||
});
|
||||
@@ -136,10 +143,6 @@ const RightPanel = memo(() => {
|
||||
});
|
||||
RightPanel.displayName = 'RightPanel';
|
||||
|
||||
const LEFT_PANEL_ID = 'left';
|
||||
const MAIN_PANEL_ID = 'main';
|
||||
const RIGHT_PANEL_ID = 'right';
|
||||
|
||||
export const rootComponents: IGridviewReactProps['components'] = {
|
||||
[LEFT_PANEL_ID]: GenerateTabLeftPanel,
|
||||
[MAIN_PANEL_ID]: MainPanel,
|
||||
@@ -185,68 +188,10 @@ export const GenerateTabAutoLayout = memo(() => {
|
||||
},
|
||||
[$api]
|
||||
);
|
||||
const resizeMainPanelOnFirstVisible = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const mainPanel = api.getPanel(MAIN_PANEL_ID);
|
||||
if (!mainPanel) {
|
||||
return;
|
||||
}
|
||||
if (mainPanel.width !== 0) {
|
||||
return;
|
||||
}
|
||||
let count = 0;
|
||||
const setSize = () => {
|
||||
if (count++ > 50) {
|
||||
return;
|
||||
}
|
||||
mainPanel.api.setSize({ width: Number.MAX_SAFE_INTEGER });
|
||||
if (mainPanel.width === 0) {
|
||||
requestAnimationFrame(setSize);
|
||||
return;
|
||||
}
|
||||
};
|
||||
setSize();
|
||||
}, [$api]);
|
||||
useOnFirstVisible(ref, resizeMainPanelOnFirstVisible);
|
||||
const toggleLeftPanel = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const left = api.getPanel(LEFT_PANEL_ID);
|
||||
if (!left) {
|
||||
return;
|
||||
}
|
||||
if (left.maximumWidth === 0) {
|
||||
left.api.setConstraints({ maximumWidth: Number.MAX_SAFE_INTEGER, minimumWidth: LEFT_PANEL_MIN_SIZE_PX });
|
||||
left.api.setSize({ width: LEFT_PANEL_MIN_SIZE_PX });
|
||||
} else {
|
||||
left.api.setConstraints({ maximumWidth: 0, minimumWidth: 0 });
|
||||
left.api.setSize({ width: 0 });
|
||||
}
|
||||
}, [$api]);
|
||||
const toggleRightPanel = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const right = api.getPanel(RIGHT_PANEL_ID);
|
||||
if (!right) {
|
||||
return;
|
||||
}
|
||||
if (right.maximumWidth === 0) {
|
||||
right.api.setConstraints({ maximumWidth: Number.MAX_SAFE_INTEGER, minimumWidth: RIGHT_PANEL_MIN_SIZE_PX });
|
||||
right.api.setSize({ width: RIGHT_PANEL_MIN_SIZE_PX });
|
||||
} else {
|
||||
right.api.setConstraints({ maximumWidth: 0, minimumWidth: 0 });
|
||||
right.api.setSize({ width: 0 });
|
||||
}
|
||||
}, [$api]);
|
||||
useResizeMainPanelOnFirstVisit($api, ref);
|
||||
|
||||
return (
|
||||
<AutoLayoutProvider $api={$api} toggleLeftPanel={toggleLeftPanel} toggleRightPanel={toggleRightPanel}>
|
||||
<AutoLayoutProvider $api={$api}>
|
||||
<GridviewReact
|
||||
ref={ref}
|
||||
className="dockview-theme-invoke"
|
||||
|
||||
6
invokeai/frontend/web/src/features/ui/layouts/shared.ts
Normal file
6
invokeai/frontend/web/src/features/ui/layouts/shared.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const LEFT_PANEL_ID = 'left';
|
||||
export const MAIN_PANEL_ID = 'main';
|
||||
export const RIGHT_PANEL_ID = 'right';
|
||||
|
||||
export const LEFT_PANEL_MIN_SIZE_PX = 420;
|
||||
export const RIGHT_PANEL_MIN_SIZE_PX = 420;
|
||||
@@ -7,15 +7,21 @@ import { GenerationProgressPanel } from 'features/gallery/components/ImageViewer
|
||||
import { ImageViewerPanel } from 'features/gallery/components/ImageViewer/ImageViewerPanel';
|
||||
import { FloatingLeftPanelButtons } from 'features/ui/components/FloatingLeftPanelButtons';
|
||||
import { FloatingRightPanelButtons } from 'features/ui/components/FloatingRightPanelButtons';
|
||||
import { AutoLayoutProvider } from 'features/ui/layouts/auto-layout-context';
|
||||
import { AutoLayoutProvider, PanelHotkeysLogical } from 'features/ui/layouts/auto-layout-context';
|
||||
import { TabWithoutCloseButton } from 'features/ui/layouts/TabWithoutCloseButton';
|
||||
import { LEFT_PANEL_MIN_SIZE_PX, RIGHT_PANEL_MIN_SIZE_PX } from 'features/ui/store/uiSlice';
|
||||
import { dockviewTheme } from 'features/ui/styles/theme';
|
||||
import { atom } from 'nanostores';
|
||||
import { memo, useCallback, useRef, useState } from 'react';
|
||||
|
||||
import {
|
||||
LEFT_PANEL_ID,
|
||||
LEFT_PANEL_MIN_SIZE_PX,
|
||||
MAIN_PANEL_ID,
|
||||
RIGHT_PANEL_ID,
|
||||
RIGHT_PANEL_MIN_SIZE_PX,
|
||||
} from './shared';
|
||||
import { UpscalingTabLeftPanel } from './UpscalingTabLeftPanel';
|
||||
import { useOnFirstVisible } from './use-on-first-visible';
|
||||
import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
|
||||
|
||||
const LAUNCHPAD_PANEL_ID = 'launchpad';
|
||||
const VIEWER_PANEL_ID = 'viewer';
|
||||
@@ -86,6 +92,7 @@ const MainPanel = memo(() => {
|
||||
/>
|
||||
<FloatingLeftPanelButtons />
|
||||
<FloatingRightPanelButtons />
|
||||
<PanelHotkeysLogical />
|
||||
</>
|
||||
);
|
||||
});
|
||||
@@ -136,10 +143,6 @@ const RightPanel = memo(() => {
|
||||
});
|
||||
RightPanel.displayName = 'RightPanel';
|
||||
|
||||
const LEFT_PANEL_ID = 'left';
|
||||
const MAIN_PANEL_ID = 'main';
|
||||
const RIGHT_PANEL_ID = 'right';
|
||||
|
||||
export const rootComponents: IGridviewReactProps['components'] = {
|
||||
[LEFT_PANEL_ID]: UpscalingTabLeftPanel,
|
||||
[MAIN_PANEL_ID]: MainPanel,
|
||||
@@ -185,68 +188,10 @@ export const UpscalingTabAutoLayout = memo(() => {
|
||||
},
|
||||
[$api]
|
||||
);
|
||||
const resizeMainPanelOnFirstVisible = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const mainPanel = api.getPanel(MAIN_PANEL_ID);
|
||||
if (!mainPanel) {
|
||||
return;
|
||||
}
|
||||
if (mainPanel.width !== 0) {
|
||||
return;
|
||||
}
|
||||
let count = 0;
|
||||
const setSize = () => {
|
||||
if (count++ > 50) {
|
||||
return;
|
||||
}
|
||||
mainPanel.api.setSize({ width: Number.MAX_SAFE_INTEGER });
|
||||
if (mainPanel.width === 0) {
|
||||
requestAnimationFrame(setSize);
|
||||
return;
|
||||
}
|
||||
};
|
||||
setSize();
|
||||
}, [$api]);
|
||||
useOnFirstVisible(ref, resizeMainPanelOnFirstVisible);
|
||||
const toggleLeftPanel = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const left = api.getPanel(LEFT_PANEL_ID);
|
||||
if (!left) {
|
||||
return;
|
||||
}
|
||||
if (left.maximumWidth === 0) {
|
||||
left.api.setConstraints({ maximumWidth: Number.MAX_SAFE_INTEGER, minimumWidth: LEFT_PANEL_MIN_SIZE_PX });
|
||||
left.api.setSize({ width: LEFT_PANEL_MIN_SIZE_PX });
|
||||
} else {
|
||||
left.api.setConstraints({ maximumWidth: 0, minimumWidth: 0 });
|
||||
left.api.setSize({ width: 0 });
|
||||
}
|
||||
}, [$api]);
|
||||
const toggleRightPanel = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const right = api.getPanel(RIGHT_PANEL_ID);
|
||||
if (!right) {
|
||||
return;
|
||||
}
|
||||
if (right.maximumWidth === 0) {
|
||||
right.api.setConstraints({ maximumWidth: Number.MAX_SAFE_INTEGER, minimumWidth: RIGHT_PANEL_MIN_SIZE_PX });
|
||||
right.api.setSize({ width: RIGHT_PANEL_MIN_SIZE_PX });
|
||||
} else {
|
||||
right.api.setConstraints({ maximumWidth: 0, minimumWidth: 0 });
|
||||
right.api.setSize({ width: 0 });
|
||||
}
|
||||
}, [$api]);
|
||||
useResizeMainPanelOnFirstVisit($api, ref);
|
||||
|
||||
return (
|
||||
<AutoLayoutProvider $api={$api} toggleLeftPanel={toggleLeftPanel} toggleRightPanel={toggleRightPanel}>
|
||||
<AutoLayoutProvider $api={$api}>
|
||||
<GridviewReact
|
||||
ref={ref}
|
||||
className="dockview-theme-invoke"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import type { GridviewApi } from 'dockview';
|
||||
import type { Atom } from 'nanostores';
|
||||
import type { RefObject } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import { MAIN_PANEL_ID } from './shared';
|
||||
|
||||
export const useOnFirstVisible = (elementRef: RefObject<HTMLElement>, callback: () => void): void => {
|
||||
useEffect(() => {
|
||||
@@ -46,3 +50,32 @@ export const useOnFirstVisible = (elementRef: RefObject<HTMLElement>, callback:
|
||||
};
|
||||
}, [elementRef, callback]);
|
||||
};
|
||||
|
||||
export const useResizeMainPanelOnFirstVisit = ($api: Atom<GridviewApi | null>, ref: RefObject<HTMLElement>) => {
|
||||
const resizeMainPanelOnFirstVisible = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const mainPanel = api.getPanel(MAIN_PANEL_ID);
|
||||
if (!mainPanel) {
|
||||
return;
|
||||
}
|
||||
if (mainPanel.width !== 0) {
|
||||
return;
|
||||
}
|
||||
let count = 0;
|
||||
const setSize = () => {
|
||||
if (count++ > 50) {
|
||||
return;
|
||||
}
|
||||
mainPanel.api.setSize({ width: Number.MAX_SAFE_INTEGER });
|
||||
if (mainPanel.width === 0) {
|
||||
requestAnimationFrame(setSize);
|
||||
return;
|
||||
}
|
||||
};
|
||||
setSize();
|
||||
}, [$api]);
|
||||
useOnFirstVisible(ref, resizeMainPanelOnFirstVisible);
|
||||
};
|
||||
|
||||
@@ -9,14 +9,20 @@ import NodeEditor from 'features/nodes/components/NodeEditor';
|
||||
import WorkflowsTabLeftPanel from 'features/nodes/components/sidePanel/WorkflowsTabLeftPanel';
|
||||
import { FloatingLeftPanelButtons } from 'features/ui/components/FloatingLeftPanelButtons';
|
||||
import { FloatingRightPanelButtons } from 'features/ui/components/FloatingRightPanelButtons';
|
||||
import { AutoLayoutProvider } from 'features/ui/layouts/auto-layout-context';
|
||||
import { AutoLayoutProvider, PanelHotkeysLogical } from 'features/ui/layouts/auto-layout-context';
|
||||
import { TabWithoutCloseButton } from 'features/ui/layouts/TabWithoutCloseButton';
|
||||
import { LEFT_PANEL_MIN_SIZE_PX, RIGHT_PANEL_MIN_SIZE_PX } from 'features/ui/store/uiSlice';
|
||||
import { dockviewTheme } from 'features/ui/styles/theme';
|
||||
import { atom } from 'nanostores';
|
||||
import { memo, useCallback, useRef, useState } from 'react';
|
||||
|
||||
import { useOnFirstVisible } from './use-on-first-visible';
|
||||
import {
|
||||
LEFT_PANEL_ID,
|
||||
LEFT_PANEL_MIN_SIZE_PX,
|
||||
MAIN_PANEL_ID,
|
||||
RIGHT_PANEL_ID,
|
||||
RIGHT_PANEL_MIN_SIZE_PX,
|
||||
} from './shared';
|
||||
import { useResizeMainPanelOnFirstVisit } from './use-on-first-visible';
|
||||
|
||||
const LAUNCHPAD_PANEL_ID = 'launchpad';
|
||||
const WORKSPACE_PANEL_ID = 'workspace';
|
||||
@@ -98,6 +104,7 @@ const MainPanel = memo(() => {
|
||||
/>
|
||||
<FloatingLeftPanelButtons />
|
||||
<FloatingRightPanelButtons />
|
||||
<PanelHotkeysLogical />
|
||||
</>
|
||||
);
|
||||
});
|
||||
@@ -148,10 +155,6 @@ const RightPanel = memo(() => {
|
||||
});
|
||||
RightPanel.displayName = 'RightPanel';
|
||||
|
||||
const LEFT_PANEL_ID = 'left';
|
||||
const MAIN_PANEL_ID = 'main';
|
||||
const RIGHT_PANEL_ID = 'right';
|
||||
|
||||
export const rootComponents: IGridviewReactProps['components'] = {
|
||||
[LEFT_PANEL_ID]: WorkflowsTabLeftPanel,
|
||||
[MAIN_PANEL_ID]: MainPanel,
|
||||
@@ -197,69 +200,10 @@ export const WorkflowsTabAutoLayout = memo(() => {
|
||||
},
|
||||
[$api]
|
||||
);
|
||||
const resizeMainPanelOnFirstVisible = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const mainPanel = api.getPanel(MAIN_PANEL_ID);
|
||||
if (!mainPanel) {
|
||||
return;
|
||||
}
|
||||
if (mainPanel.width !== 0) {
|
||||
return;
|
||||
}
|
||||
let count = 0;
|
||||
const setSize = () => {
|
||||
if (count++ > 50) {
|
||||
return;
|
||||
}
|
||||
mainPanel.api.setSize({ width: Number.MAX_SAFE_INTEGER });
|
||||
if (mainPanel.width === 0) {
|
||||
requestAnimationFrame(setSize);
|
||||
return;
|
||||
}
|
||||
};
|
||||
setSize();
|
||||
}, [$api]);
|
||||
useOnFirstVisible(ref, resizeMainPanelOnFirstVisible);
|
||||
const toggleLeftPanel = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const left = api.getPanel(LEFT_PANEL_ID);
|
||||
if (!left) {
|
||||
return;
|
||||
}
|
||||
if (left.maximumWidth === 0) {
|
||||
left.api.setConstraints({ maximumWidth: Number.MAX_SAFE_INTEGER, minimumWidth: LEFT_PANEL_MIN_SIZE_PX });
|
||||
left.api.setSize({ width: LEFT_PANEL_MIN_SIZE_PX });
|
||||
} else {
|
||||
left.api.setConstraints({ maximumWidth: 0, minimumWidth: 0 });
|
||||
left.api.setSize({ width: 0 });
|
||||
}
|
||||
}, [$api]);
|
||||
const toggleRightPanel = useCallback(() => {
|
||||
const api = $api.get();
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const right = api.getPanel(RIGHT_PANEL_ID);
|
||||
if (!right) {
|
||||
return;
|
||||
}
|
||||
if (right.maximumWidth === 0) {
|
||||
right.api.setConstraints({ maximumWidth: Number.MAX_SAFE_INTEGER, minimumWidth: RIGHT_PANEL_MIN_SIZE_PX });
|
||||
right.api.setSize({ width: RIGHT_PANEL_MIN_SIZE_PX });
|
||||
} else {
|
||||
right.api.setConstraints({ maximumWidth: 0, minimumWidth: 0 });
|
||||
right.api.setSize({ width: 0 });
|
||||
}
|
||||
}, [$api]);
|
||||
useResizeMainPanelOnFirstVisit($api, ref);
|
||||
|
||||
return (
|
||||
<AutoLayoutProvider $api={$api} toggleLeftPanel={toggleLeftPanel} toggleRightPanel={toggleRightPanel}>
|
||||
<AutoLayoutProvider $api={$api}>
|
||||
<GridviewReact
|
||||
ref={ref}
|
||||
className="dockview-theme-invoke"
|
||||
|
||||
Reference in New Issue
Block a user