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:
committed by
Facebook GitHub Bot
parent
95638af321
commit
e7fdd8332d
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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"
|
||||
|
||||
35
desktop/app/src/utils/useStore.tsx
Normal file
35
desktop/app/src/utils/useStore.tsx
Normal 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();
|
||||
}
|
||||
Reference in New Issue
Block a user