Files
flipper/desktop/app/src/sandy-chrome/SandyApp.tsx
Michel Weststrate c9b08695d5 Make sure out-of-contents rendering is supported in Sandy
Summary: For RN Debugger an ugly hack is used that roars its head now again; to make sure that the embedded debugger state isn't lost when switching to a different plugin, the chrome devtools are rendered _outside_ the domNode where they should normally appeared, and made invisible rather than removed when becoming invisible. Since at this moment this is the only place where we apply the trick, figured for now to condone it, rather than making a neater abstraction out of it (or kiling it all together)

Reviewed By: passy

Differential Revision: D24786771

fbshipit-source-id: 726617899bc620fc8b9db677d9413b31d5ad7653
2020-11-09 07:23:29 -08:00

154 lines
4.7 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import React, {useEffect, useState, useCallback} from 'react';
import {styled} from '../ui';
import {Layout, Sidebar} from '../ui';
import {theme} from 'flipper-plugin';
import {Logger} from '../fb-interfaces/Logger';
import {LeftRail} from './LeftRail';
import {TemporarilyTitlebar} from './TemporarilyTitlebar';
import {registerStartupTime} from '../App';
import {useStore, useDispatch} from '../utils/useStore';
import {SandyContext} from './SandyContext';
import {ConsoleLogs} from '../chrome/ConsoleLogs';
import {setStaticView} from '../reducers/connections';
import {toggleLeftSidebarVisible} from '../reducers/application';
import {AppInspect} from './appinspect/AppInspect';
import PluginContainer from '../PluginContainer';
import {ContentContainer} from './ContentContainer';
import {Notification} from './notification/Notification';
import {SheetRenderer} from '../chrome/SheetRenderer';
export type ToplevelNavItem =
| 'appinspect'
| 'flipperlogs'
| 'notification'
| undefined;
export type ToplevelProps = {
toplevelSelection: ToplevelNavItem;
setToplevelSelection: (_newSelection: ToplevelNavItem) => void;
};
export function SandyApp({logger}: {logger: Logger}) {
const dispatch = useDispatch();
const leftSidebarVisible = useStore(
(state) => state.application.leftSidebarVisible,
);
const staticView = useStore((state) => state.connections.staticView);
/**
* top level navigation uses two pieces of state, selection stored here, and selection that is based on what is stored in the reducer (which might be influenced by redux action dispatches to different means).
* The logic here is to sync both, but without modifying the navigation related reducers to not break classic Flipper.
* It is possible to simplify this in the future.
*/
const [toplevelSelection, setStoredToplevelSelection] = useState<
ToplevelNavItem
>('appinspect');
// Handle toplevel nav clicks from LeftRail
const setToplevelSelection = useCallback(
(newSelection: ToplevelNavItem) => {
// toggle sidebar visibility if needed
const hasLeftSidebar =
newSelection === 'appinspect' || newSelection === 'notification';
if (hasLeftSidebar) {
if (newSelection === toplevelSelection) {
dispatch(toggleLeftSidebarVisible());
} else {
dispatch(toggleLeftSidebarVisible(true));
}
}
switch (newSelection) {
case 'flipperlogs':
dispatch(setStaticView(ConsoleLogs));
break;
default:
}
setStoredToplevelSelection(newSelection);
},
[dispatch, toplevelSelection],
);
useEffect(() => {
registerStartupTime(logger);
// don't warn about logger, even with a new logger we don't want to re-register
// eslint-disable-next-line
}, []);
const leftMenuContent = !leftSidebarVisible ? null : toplevelSelection ===
'appinspect' ? (
<AppInspect />
) : toplevelSelection === 'notification' ? (
<Notification />
) : null;
return (
<SandyContext.Provider value={true}>
<Layout.Top>
<>
<TemporarilyTitlebar />
<SheetRenderer logger={logger} />
</>
<Layout.Left>
<Layout.Horizontal>
<LeftRail
toplevelSelection={toplevelSelection}
setToplevelSelection={setToplevelSelection}
/>
<Sidebar width={250} minWidth={220} maxWidth={800} gutter>
{leftMenuContent && leftMenuContent}
</Sidebar>
</Layout.Horizontal>
<MainContainer>
{outOfContentsContainer}
{staticView ? (
<ContentContainer>
{React.createElement(staticView, {
logger: logger,
})}
</ContentContainer>
) : (
<PluginContainer logger={logger} isSandy />
)}
</MainContainer>
</Layout.Left>
</Layout.Top>
</SandyContext.Provider>
);
}
const outOfContentsContainer = (
<div
style={{
position: 'relative',
width: '100%',
height: '100%',
display: 'none',
}}>
<div
id="flipper-out-of-contents-container"
style={{
display: 'none',
position: 'absolute',
right: 0,
bottom: 0,
left: 0,
top: 0,
}}
/>
</div>
);
const MainContainer = styled(Layout.Container)({
background: theme.backgroundWash,
padding: `${theme.space.large}px ${theme.space.large}px ${theme.space.large}px 0`,
});