diff --git a/desktop/flipper-ui-core/src/reducers/application.tsx b/desktop/flipper-ui-core/src/reducers/application.tsx index e7980d62e..33cd8159a 100644 --- a/desktop/flipper-ui-core/src/reducers/application.tsx +++ b/desktop/flipper-ui-core/src/reducers/application.tsx @@ -11,6 +11,13 @@ import {v1 as uuidv1} from 'uuid'; import {getRenderHostInstance} from 'flipper-frontend-core'; import {Actions} from './'; +export type ToplevelNavigationItem = + | 'appinspect' + | 'flipperlogs' + | 'notification' + | 'connectivity' + | undefined; + export type LauncherMsg = { message: string; severity: 'warning' | 'error'; @@ -37,6 +44,7 @@ export type ShareType = { } & SubShareType; export type State = { + topLevelSelection: ToplevelNavigationItem; hasLeftSidebar: boolean; leftSidebarVisible: boolean; rightSidebarVisible: boolean; @@ -59,6 +67,10 @@ export type Action = type: BooleanActionType; payload?: boolean; } + | { + type: 'topLevelSelection'; + payload: ToplevelNavigationItem; + } | { type: 'windowIsFocused'; payload: {isFocused: boolean; time: number}; @@ -80,6 +92,7 @@ export type Action = }; export const initialState: () => State = () => ({ + topLevelSelection: 'appinspect', hasLeftSidebar: true, leftSidebarVisible: true, rightSidebarVisible: true, @@ -132,6 +145,19 @@ export default function reducer( [action.type]: newValue, }; } + } else if (action.type === 'topLevelSelection') { + const topLevelSelection = action.payload; + + const hasLeftSidebar = + topLevelSelection === 'appinspect' || + topLevelSelection === 'notification'; + + return { + ...state, + leftSidebarVisible: hasLeftSidebar, + hasLeftSidebar, + topLevelSelection, + }; } else if (action.type === 'windowIsFocused') { return { ...state, @@ -174,6 +200,13 @@ export const toggleAction = ( payload, }); +export const setTopLevelSelection = ( + payload: ToplevelNavigationItem, +): Action => ({ + type: 'topLevelSelection', + payload, +}); + export const toggleLeftSidebarVisible = (payload?: boolean): Action => ({ type: 'leftSidebarVisible', payload, diff --git a/desktop/flipper-ui-core/src/reducers/connections.tsx b/desktop/flipper-ui-core/src/reducers/connections.tsx index 1b608c945..872187243 100644 --- a/desktop/flipper-ui-core/src/reducers/connections.tsx +++ b/desktop/flipper-ui-core/src/reducers/connections.tsx @@ -161,13 +161,12 @@ export type Action = } | RegisterPluginAction; -const DEFAULT_PLUGIN = 'DeviceLogs'; const DEFAULT_DEVICE_BLACKLIST: DeviceOS[] = ['MacOS', 'Metro', 'Windows']; const INITAL_STATE: State = { devices: [], selectedDevice: null, selectedAppId: null, - selectedPlugin: DEFAULT_PLUGIN, + selectedPlugin: null, pluginMenuEntries: [], userPreferredDevice: null, userPreferredPlugin: null, diff --git a/desktop/flipper-ui-core/src/sandy-chrome/Navbar.tsx b/desktop/flipper-ui-core/src/sandy-chrome/Navbar.tsx index 8954f85ca..992b331c4 100644 --- a/desktop/flipper-ui-core/src/sandy-chrome/Navbar.tsx +++ b/desktop/flipper-ui-core/src/sandy-chrome/Navbar.tsx @@ -33,10 +33,11 @@ import { WarningOutlined, } from '@ant-design/icons'; import { + setTopLevelSelection, toggleLeftSidebarVisible, toggleRightSidebarVisible, + ToplevelNavigationItem, } from '../reducers/application'; -import {ToplevelNavItem, ToplevelProps} from './SandyApp'; import PluginManager from '../chrome/plugin-manager/PluginManager'; import {showEmulatorLauncher} from './appinspect/LaunchEmulator'; import SetupDoctorScreen, {checkHasNewProblem} from './SetupDoctorScreen'; @@ -57,11 +58,11 @@ import { import UpdateIndicator from '../chrome/UpdateIndicator'; import {css} from '@emotion/css'; import constants from '../fb-stubs/constants'; -import {setStaticView} from '../reducers/connections'; +import {selectPlugin, setStaticView} from '../reducers/connections'; import {StyleGuide} from './StyleGuide'; import {openDeeplinkDialog} from '../deeplink'; import SettingsSheet from '../chrome/SettingsSheet'; -import WelcomeScreen from './WelcomeScreen'; +import WelcomeScreen, {WelcomeScreenStaticView} from './WelcomeScreen'; import {AppSelector} from './appinspect/AppSelector'; import { NavbarScreenRecordButton, @@ -69,11 +70,21 @@ import { } from '../chrome/ScreenCaptureButtons'; import {StatusMessage} from './appinspect/AppInspect'; import {TroubleshootingGuide} from './appinspect/fb-stubs/TroubleshootingGuide'; +import {FlipperDevTools} from '../chrome/FlipperDevTools'; +import {ConnectivityHub} from '../chrome/ConnectivityHub'; -export const Navbar = withTrackingScope(function Navbar({ - toplevelSelection, - setToplevelSelection, -}: ToplevelProps) { +export const Navbar = withTrackingScope(function Navbar() { + const {topLevelSelection, selectedDevice, selectedAppId, selectedPlugin} = + useStore((state) => { + return { + topLevelSelection: state.application.topLevelSelection, + selectedDevice: state.connections.selectedDevice, + selectedAppId: state.connections.selectedAppId, + selectedPlugin: state.connections.selectedPlugin, + }; + }); + + const dispatch = useDispatch(); return ( { - setToplevelSelection('appinspect'); + dispatch(setTopLevelSelection('appinspect')); + if (selectedPlugin) { + dispatch( + selectPlugin({ + selectedPlugin, + selectedAppId, + selectedDevice: selectedDevice, + }), + ); + } else { + dispatch(setStaticView(WelcomeScreenStaticView)); + } }} /> @@ -110,11 +132,8 @@ export const Navbar = withTrackingScope(function Navbar({ - - + + @@ -224,23 +243,25 @@ function ExportEverythingEverywhereAllAtOnceStatusModal({ } function NotificationButton({ - toplevelSelection, - setToplevelSelection, -}: ToplevelProps) { + topLevelSelection, +}: { + topLevelSelection: ToplevelNavigationItem; +}) { const notifications = useStore((state) => state.notifications); const activeNotifications = useMemoize(filterNotifications, [ notifications.activeNotifications, notifications.blocklistedPlugins, notifications.blocklistedCategories, ]); + const dispatch = useDispatch(); return ( setToplevelSelection('notification')} + onClick={() => dispatch(setTopLevelSelection('notification'))} /> ); } @@ -444,11 +465,7 @@ const submenu = css` const AlertsZIndex = 101; const TroubleShootZIndex = 100; -function TroubleshootMenu({ - setToplevelSelection, -}: { - setToplevelSelection: (x: ToplevelNavItem) => void; -}) { +function TroubleshootMenu() { const store = useStore(); const [status, setStatus] = useState< ExportEverythingEverywhereAllAtOnceStatus | undefined @@ -498,7 +515,10 @@ function TroubleshootMenu({ {getRenderHostInstance().GK('flipper_connection_troubleshoot') && ( setToplevelSelection('connectivity')}> + onClick={() => { + store.dispatch(setTopLevelSelection('connectivity')); + store.dispatch(setStaticView(ConnectivityHub)); + }}> Troubleshoot Connectivity )} @@ -511,7 +531,10 @@ function TroubleshootMenu({ setToplevelSelection('flipperlogs')}> + onClick={() => { + store.dispatch(setTopLevelSelection('flipperlogs')); + store.dispatch(setStaticView(FlipperDevTools)); + }}> Flipper Logs diff --git a/desktop/flipper-ui-core/src/sandy-chrome/SandyApp.tsx b/desktop/flipper-ui-core/src/sandy-chrome/SandyApp.tsx index 6b571efc5..1cc7256bd 100644 --- a/desktop/flipper-ui-core/src/sandy-chrome/SandyApp.tsx +++ b/desktop/flipper-ui-core/src/sandy-chrome/SandyApp.tsx @@ -7,7 +7,7 @@ * @format */ -import React, {useEffect, useState, useCallback} from 'react'; +import React, {useEffect} from 'react'; import { TrackingScope, useLogger, @@ -21,13 +21,7 @@ import {theme} from 'flipper-plugin'; import {Logger} from 'flipper-common'; import {Navbar} from './Navbar'; -import {useStore, useDispatch} from '../utils/useStore'; -import {FlipperDevTools} from '../chrome/FlipperDevTools'; -import {setStaticView} from '../reducers/connections'; -import { - toggleHasLeftSidebar, - toggleLeftSidebarVisible, -} from '../reducers/application'; +import {useStore} from '../utils/useStore'; import {AppInspect} from './appinspect/AppInspect'; import PluginContainer from '../PluginContainer'; import {ContentContainer} from './ContentContainer'; @@ -47,63 +41,16 @@ import {isFBEmployee} from '../utils/fbEmployee'; import {notification} from 'antd'; import isProduction from '../utils/isProduction'; import {getRenderHostInstance} from 'flipper-frontend-core'; -import {ConnectivityHub} from '../chrome/ConnectivityHub'; - -export type ToplevelNavItem = - | 'appinspect' - | 'flipperlogs' - | 'notification' - | 'connectivity' - | undefined; -export type ToplevelProps = { - toplevelSelection: ToplevelNavItem; - setToplevelSelection: (_newSelection: ToplevelNavItem) => void; -}; export function SandyApp() { const logger = useLogger(); - 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('appinspect'); - - // Handle toplevel nav clicks from LeftRail - const setToplevelSelection = useCallback( - (newSelection: ToplevelNavItem) => { - // toggle sidebar visibility if needed - const hasLeftSidebar = - newSelection === 'appinspect' || newSelection === 'notification'; - - dispatch(toggleHasLeftSidebar(hasLeftSidebar)); - if (hasLeftSidebar) { - if (newSelection === toplevelSelection) { - dispatch(toggleLeftSidebarVisible()); - } else { - dispatch(toggleLeftSidebarVisible(true)); - } - } - switch (newSelection) { - case 'flipperlogs': - dispatch(setStaticView(FlipperDevTools)); - break; - case 'connectivity': - dispatch(setStaticView(ConnectivityHub)); - break; - default: - } - setStoredToplevelSelection(newSelection); - }, - [dispatch, toplevelSelection], + const topLevelSelection = useStore( + (state) => state.application.topLevelSelection, ); + const staticView = useStore((state) => state.connections.staticView); useEffect(() => { document.title = `Flipper (${getVersionString()}${ @@ -162,10 +109,10 @@ export function SandyApp() { } }, []); - const leftMenuContent = !leftSidebarVisible ? null : toplevelSelection === + const leftMenuContent = !leftSidebarVisible ? null : topLevelSelection === 'appinspect' ? ( - ) : toplevelSelection === 'notification' ? ( + ) : topLevelSelection === 'notification' ? ( ) : null; @@ -173,10 +120,7 @@ export function SandyApp() { - + <_Sidebar width={250} minWidth={220} maxWidth={800} gutter> {leftMenuContent && ( - + {leftMenuContent} )}