Made sidebars toggleable

Summary:
Implemented a first button: make main menu collapsible.

Also introduced some additional utilities and hooked up startup performance logging

Reviewed By: cekkaewnumchai

Differential Revision: D23783500

fbshipit-source-id: 2456fd781a52d497facbaccfabe885e4f8c408c5
This commit is contained in:
Michel Weststrate
2020-09-21 11:50:45 -07:00
committed by Facebook GitHub Bot
parent 95638af321
commit e7fdd8332d
5 changed files with 136 additions and 54 deletions

View File

@@ -79,37 +79,36 @@ const PluginContent = styled(FlexRow)({
PluginContent.displayName = 'App:PluginContent';
type Props = StateFromProps & OwnProps & DispatchProps;
export function registerStartupTime(logger: Logger) {
// track time since launch
const [s, ns] = process.hrtime();
const launchEndTime = s * 1e3 + ns / 1e6;
ipcRenderer.on('getLaunchTime', (_: any, launchStartTime: number) => {
logger.track('performance', 'launchTime', launchEndTime - launchStartTime);
QuickPerformanceLogger.markerPoint(
FLIPPER_QPL_EVENTS.STARTUP,
'launchStartTime',
undefined,
0,
launchStartTime,
);
QuickPerformanceLogger.markerEnd(
FLIPPER_QPL_EVENTS.STARTUP,
QuickLogActionType.SUCCESS,
0,
launchEndTime,
);
});
ipcRenderer.send('getLaunchTime');
ipcRenderer.send('componentDidMount');
}
export class App extends React.Component<Props> {
componentDidMount() {
// track time since launch
const [s, ns] = process.hrtime();
const launchEndTime = s * 1e3 + ns / 1e6;
ipcRenderer.on('getLaunchTime', (_: any, launchStartTime: number) => {
this.props.logger.track(
'performance',
'launchTime',
launchEndTime - launchStartTime,
);
QuickPerformanceLogger.markerPoint(
FLIPPER_QPL_EVENTS.STARTUP,
'launchStartTime',
undefined,
0,
launchStartTime,
);
QuickPerformanceLogger.markerEnd(
FLIPPER_QPL_EVENTS.STARTUP,
QuickLogActionType.SUCCESS,
0,
launchEndTime,
);
});
ipcRenderer.send('getLaunchTime');
ipcRenderer.send('componentDidMount');
registerStartupTime(this.props.logger);
if (hasNewChangesToShow(window.localStorage)) {
this.props.setActiveSheet(ACTIVE_SHEET_CHANGELOG_RECENT_ONLY);
}

View File

@@ -22,8 +22,12 @@ import {
MedicineBoxOutlined,
} from '@ant-design/icons';
import {SidebarLeft, SidebarRight} from './SandyIcons';
import {useDispatch, useStore} from '../utils/useStore';
import {toggleLeftSidebarVisible} from '../reducers/application';
import {theme} from './theme';
const LeftRailContainer = styled(FlexColumn)({
background: theme.backgroundDefault,
width: 48,
boxShadow: 'inset -1px 0px 0px rgba(0, 0, 0, 0.1)',
justifyContent: 'space-between',
@@ -36,10 +40,10 @@ const LeftRailSection = styled(FlexColumn)({
});
LeftRailSection.displayName = 'LeftRailSection';
const LeftRailButtonElem = styled(Button)<{margin: number}>(({margin}) => ({
width: 36,
height: 36,
margin,
const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({
width: kind === 'small' ? 32 : 36,
height: kind === 'small' ? 32 : 36,
margin: 6,
padding: '5px 0',
border: 'none',
boxShadow: 'none',
@@ -49,15 +53,19 @@ LeftRailButtonElem.displayName = 'LeftRailButtonElem';
function LeftRailButton({
icon,
small,
active,
selected,
toggled,
count,
title,
onClick,
}: {
icon?: React.ReactElement;
small?: boolean;
active?: boolean;
toggled?: boolean;
selected?: boolean;
count?: number;
title: string;
onClick?: React.MouseEventHandler<HTMLElement>;
}) {
let iconElement =
icon && cloneElement(icon, {style: {fontSize: small ? 16 : 24}});
@@ -67,9 +75,14 @@ function LeftRailButton({
return (
<Tooltip title={title} placement="right">
<LeftRailButtonElem
margin={small ? 2 : 6}
type={active ? 'primary' : 'ghost'}
kind={small ? 'small' : undefined}
type={selected ? 'primary' : 'ghost'}
icon={iconElement}
onClick={onClick}
style={{
color: toggled ? theme.primaryColor : undefined,
background: toggled ? theme.backgroundWash : undefined,
}}
/>
</Tooltip>
);
@@ -86,7 +99,7 @@ export function LeftRail() {
return (
<LeftRailContainer>
<LeftRailSection>
<LeftRailButton icon={<MobileFilled />} active title="App Inspect" />
<LeftRailButton icon={<MobileFilled />} title="App Inspect" />
<LeftRailButton icon={<AppstoreOutlined />} title="Plugin Manager" />
<LeftRailButton
count={8}
@@ -117,17 +130,33 @@ export function LeftRail() {
title="Feedback / Bug Reporter"
/>
<LeftRailButton
icon={<SidebarLeft />}
icon={<SidebarRight />}
small
title="Right Sidebar Toggle"
/>
<LeftRailButton
icon={<SidebarRight />}
small
title="Left Sidebar Toggle"
/>
<LeftSidebarToggleButton />
<LeftRailButton icon={<LoginOutlined />} title="Log In" />
</LeftRailSection>
</LeftRailContainer>
);
}
function LeftSidebarToggleButton() {
const mainMenuVisible = useStore(
(state) => state.application.leftSidebarVisible,
);
const dispatch = useDispatch();
return (
<LeftRailButton
icon={<SidebarLeft />}
small
title="Left Sidebar Toggle"
toggled={mainMenuVisible}
onClick={() => {
dispatch(toggleLeftSidebarVisible());
}}
/>
);
}

View File

@@ -7,23 +7,40 @@
* @format
*/
import React from 'react';
import React, {useEffect} from 'react';
import {styled} from 'flipper';
import {DatePicker} from 'antd';
import {Layout, FlexRow} from '../ui';
import {theme} from './theme';
import {Logger} from '../fb-interfaces/Logger';
import {LeftRail} from './LeftRail';
import {TemporarilyTitlebar} from './TemporarilyTitlebar';
import {registerStartupTime} from '../App';
import {useStore} from '../utils/useStore';
export function SandyApp({logger}: {logger: Logger}) {
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 mainMenuVisible = useStore(
(state) => state.application.leftSidebarVisible,
);
export function SandyApp() {
return (
<Layout.Top>
<TemporarilyTitlebar />
<Layout.Left initialSize={348} minSize={200}>
<LeftMenu>
<Layout.Left
initialSize={mainMenuVisible ? 348 : undefined}
minSize={200}>
<LeftMenu collapsed={!mainMenuVisible}>
<LeftRail />
<div>LeftMenu</div>
{mainMenuVisible && (
<div style={{background: 'white', width: '100%'}}>LeftMenu</div>
)}
</LeftMenu>
<MainContainer>
<Layout.Right initialSize={300} minSize={200}>
@@ -44,11 +61,13 @@ export function SandyApp() {
);
}
const LeftMenu = styled(FlexRow)({
boxShadow: `inset -1px 0px 0px ${theme.dividerColor}`,
const LeftMenu = styled(FlexRow)<{collapsed: boolean}>(({collapsed}) => ({
background: theme.backgroundWash,
boxShadow: collapsed ? undefined : `1px 0px 0px ${theme.dividerColor}`,
paddingRight: collapsed ? theme.space.middle : 0,
height: '100%',
width: '100%',
});
}));
const MainContainer = styled('div')({
display: 'flex',

View File

@@ -9,7 +9,7 @@
import React from 'react';
export const SidebarLeft = (props: React.SVGProps<SVGSVGElement>) => (
export const SidebarRight = (props: React.SVGProps<SVGSVGElement>) => (
<svg width={16} height={16} viewBox="0 0 16 16" fill="none" {...props}>
<path
fillRule="evenodd"
@@ -24,7 +24,7 @@ export const SidebarLeft = (props: React.SVGProps<SVGSVGElement>) => (
</svg>
);
export const SidebarRight = (props: React.SVGProps<SVGSVGElement>) => (
export const SidebarLeft = (props: React.SVGProps<SVGSVGElement>) => (
<svg width={16} height={16} viewBox="0 0 16 16" fill="none" {...props}>
<path
fillRule="evenodd"

View File

@@ -0,0 +1,35 @@
/**
* 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 {
useSelector,
shallowEqual,
useDispatch as useDispatchBase,
} from 'react-redux';
import {Dispatch} from 'redux';
import {State, Actions} from '../reducers/index';
/**
* Strongly typed wrapper or Redux's useSelector.
*
* Equality defaults to shallowEquality
*/
export function useStore<Selected>(
selector: (state: State) => Selected,
equalityFn: (left: Selected, right: Selected) => boolean = shallowEqual,
): Selected {
return useSelector(selector, equalityFn);
}
/**
* Strongly typed useDispatch wrapper for the Flipper redux store.
*/
export function useDispatch(): Dispatch<Actions> {
return useDispatchBase();
}