diff --git a/src/app/App.tsx b/src/app/App.tsx index fbe67409..e2c4905e 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -4,7 +4,7 @@ import 'react-splitter-layout/lib/index.css'; import './app.scss'; import { Button, Classes, Spinner } from '@blueprintjs/core'; -import { Manual } from '@blueprintjs/icons'; +import { Console, Manual } from '@blueprintjs/icons'; import React, { useEffect, useState } from 'react'; type SideView = 'off' | 'docs'; @@ -70,14 +70,81 @@ const Docs: React.FunctionComponent = () => { ); }; +/** + * HACK: react-splitter-layout is an uncontrolled component, so there is no + * clean way to reset its size programmatically. + */ +function resetSplitterSize(className: string, defaultSize: number): void { + const container = document.querySelector(className); + + if (!container) { + return; + } + + const fiberKey = Object.keys(container).find((k) => k.startsWith('__reactFiber')); + if (!fiberKey) { + return; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let fiber: any = (container as any)[fiberKey]; + while (fiber && !fiber.stateNode?.handleMouseMove) { + fiber = fiber.return; + } + + fiber?.stateNode?.setState({ secondaryPaneSize: defaultSize }); +} + const App: React.FunctionComponent = () => { const i18n = useI18n(); const { isDarkMode } = useTernaryDarkMode(); const [sideView, setSideView] = useState('off'); const [isDragging, setIsDragging] = useState(false); - const [docsSplit, setDocsSplit] = useLocalStorage('app-docs-split', 30); - const [terminalSplit, setTerminalSplit] = useLocalStorage('app-terminal-split', 30); + const defaultDocsSplit = 30; + const [docsSplit, setDocsSplit] = useLocalStorage( + 'app-docs-split', + defaultDocsSplit, + ); + + const resetDocsSplit = () => { + setDocsSplit(defaultDocsSplit); + resetSplitterSize( + '.splitter-layout.pb-show-docs, .splitter-layout.pb-hide-docs', + defaultDocsSplit, + ); + }; + + const docsOnClick = () => { + if (sideView === 'docs' && docsSplit < 10) { + resetDocsSplit(); + } else { + setSideView(sideView === 'docs' ? 'off' : 'docs'); + } + }; + + const defaultTerminalSplit = 30; + const [terminalSplit, setTerminalSplit] = useLocalStorage( + 'app-terminal-split', + defaultTerminalSplit, + ); + const [terminalVisible, setTerminalVisible] = useState(true); + + const resetTerminalSplit = () => { + setTerminalSplit(defaultTerminalSplit); + resetSplitterSize( + '.splitter-layout.pb-show-terminal, .splitter-layout.pb-hide-terminal', + defaultTerminalSplit, + ); + }; + + const terminalOnClick = () => { + if (terminalVisible && terminalSplit < 10) { + resetTerminalSplit(); + } else { + setTerminalVisible(!terminalVisible); + } + }; // Classes.DARK has to be applied to body element, otherwise it won't // affect portals @@ -128,6 +195,11 @@ const App: React.FunctionComponent = () => { > { > -