Move notifications into a modal and remove app inspect

Summary: Also removing topLevelSelection as it is no longer used in flipper

Reviewed By: aigoncharov

Differential Revision: D48069386

fbshipit-source-id: 6e4cdd6aab67d2cd30ac1884118703520125bf84
This commit is contained in:
Anton Kastritskiy
2023-08-07 03:54:28 -07:00
committed by Facebook GitHub Bot
parent 08371d3a6b
commit 9cceca6d7e
4 changed files with 44 additions and 88 deletions

View File

@@ -11,8 +11,6 @@ import {v1 as uuidv1} from 'uuid';
import {getRenderHostInstance} from 'flipper-frontend-core'; import {getRenderHostInstance} from 'flipper-frontend-core';
import {Actions} from './'; import {Actions} from './';
export type ToplevelNavigationItem = 'appinspect' | 'notification' | undefined;
export type LauncherMsg = { export type LauncherMsg = {
message: string; message: string;
severity: 'warning' | 'error'; severity: 'warning' | 'error';
@@ -39,8 +37,8 @@ export type ShareType = {
} & SubShareType; } & SubShareType;
export type State = { export type State = {
topLevelSelection: ToplevelNavigationItem;
isTroubleshootingModalOpen: boolean; isTroubleshootingModalOpen: boolean;
isNotificationModalOpen: boolean;
leftSidebarVisible: boolean; leftSidebarVisible: boolean;
rightSidebarVisible: boolean; rightSidebarVisible: boolean;
rightSidebarAvailable: boolean; rightSidebarAvailable: boolean;
@@ -54,6 +52,7 @@ export type State = {
type BooleanActionType = type BooleanActionType =
| 'hasLeftSidebar' | 'hasLeftSidebar'
| 'leftSidebarVisible' | 'leftSidebarVisible'
| 'isNotificationModalOpen'
| 'rightSidebarVisible' | 'rightSidebarVisible'
| 'rightSidebarAvailable'; | 'rightSidebarAvailable';
@@ -62,10 +61,6 @@ export type Action =
type: BooleanActionType; type: BooleanActionType;
payload?: boolean; payload?: boolean;
} }
| {
type: 'topLevelSelection';
payload: ToplevelNavigationItem;
}
| { | {
type: 'windowIsFocused'; type: 'windowIsFocused';
payload: {isFocused: boolean; time: number}; payload: {isFocused: boolean; time: number};
@@ -93,6 +88,7 @@ export const initialState: () => State = () => ({
topLevelSelection: 'appinspect', topLevelSelection: 'appinspect',
hasLeftSidebar: true, hasLeftSidebar: true,
isTroubleshootingModalOpen: false, isTroubleshootingModalOpen: false,
isNotificationModalOpen: false,
leftSidebarVisible: true, leftSidebarVisible: true,
rightSidebarVisible: true, rightSidebarVisible: true,
rightSidebarAvailable: false, rightSidebarAvailable: false,
@@ -127,6 +123,7 @@ export default function reducer(
if ( if (
action.type === 'leftSidebarVisible' || action.type === 'leftSidebarVisible' ||
action.type === 'rightSidebarVisible' || action.type === 'rightSidebarVisible' ||
action.type === 'isNotificationModalOpen' ||
action.type === 'rightSidebarAvailable' action.type === 'rightSidebarAvailable'
) { ) {
const newValue = const newValue =
@@ -143,13 +140,6 @@ export default function reducer(
[action.type]: newValue, [action.type]: newValue,
}; };
} }
} else if (action.type === 'topLevelSelection') {
const topLevelSelection = action.payload;
return {
...state,
topLevelSelection,
};
} else if (action.type === 'TOGGLE_CONNECTIVITY_MODAL') { } else if (action.type === 'TOGGLE_CONNECTIVITY_MODAL') {
return { return {
...state, ...state,
@@ -197,13 +187,6 @@ export const toggleAction = (
payload, payload,
}); });
export const setTopLevelSelection = (
payload: ToplevelNavigationItem,
): Action => ({
type: 'topLevelSelection',
payload,
});
export const toggleConnectivityModal = (): Action => ({ export const toggleConnectivityModal = (): Action => ({
type: 'TOGGLE_CONNECTIVITY_MODAL', type: 'TOGGLE_CONNECTIVITY_MODAL',
}); });

View File

@@ -27,17 +27,14 @@ import {
BellOutlined, BellOutlined,
BugOutlined, BugOutlined,
LayoutOutlined, LayoutOutlined,
MobileOutlined,
RocketOutlined, RocketOutlined,
SettingOutlined, SettingOutlined,
WarningOutlined, WarningOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { import {
setTopLevelSelection,
toggleConnectivityModal, toggleConnectivityModal,
toggleLeftSidebarVisible, toggleLeftSidebarVisible,
toggleRightSidebarVisible, toggleRightSidebarVisible,
ToplevelNavigationItem,
} from '../reducers/application'; } from '../reducers/application';
import PluginManager from '../chrome/plugin-manager/PluginManager'; import PluginManager from '../chrome/plugin-manager/PluginManager';
import {showEmulatorLauncher} from './appinspect/LaunchEmulator'; import {showEmulatorLauncher} from './appinspect/LaunchEmulator';
@@ -59,11 +56,11 @@ import {
import UpdateIndicator from '../chrome/UpdateIndicator'; import UpdateIndicator from '../chrome/UpdateIndicator';
import {css} from '@emotion/css'; import {css} from '@emotion/css';
import constants from '../fb-stubs/constants'; import constants from '../fb-stubs/constants';
import {selectPlugin, setStaticView} from '../reducers/connections'; import {setStaticView} from '../reducers/connections';
import {StyleGuide} from './StyleGuide'; import {StyleGuide} from './StyleGuide';
import {openDeeplinkDialog} from '../deeplink'; import {openDeeplinkDialog} from '../deeplink';
import SettingsSheet from '../chrome/SettingsSheet'; import SettingsSheet from '../chrome/SettingsSheet';
import WelcomeScreen, {WelcomeScreenStaticView} from './WelcomeScreen'; import WelcomeScreen from './WelcomeScreen';
import {AppSelector} from './appinspect/AppSelector'; import {AppSelector} from './appinspect/AppSelector';
import { import {
NavbarScreenRecordButton, NavbarScreenRecordButton,
@@ -73,19 +70,9 @@ import {StatusMessage} from './appinspect/AppInspect';
import {TroubleshootingGuide} from './appinspect/fb-stubs/TroubleshootingGuide'; import {TroubleshootingGuide} from './appinspect/fb-stubs/TroubleshootingGuide';
import {FlipperDevTools} from '../chrome/FlipperDevTools'; import {FlipperDevTools} from '../chrome/FlipperDevTools';
import {TroubleshootingHub} from '../chrome/TroubleshootingHub'; import {TroubleshootingHub} from '../chrome/TroubleshootingHub';
import {Notification} from './notification/Notification';
export const Navbar = withTrackingScope(function Navbar() { 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 ( return (
<Layout.Horizontal <Layout.Horizontal
borderBottom borderBottom
@@ -99,25 +86,6 @@ export const Navbar = withTrackingScope(function Navbar() {
}}> }}>
<Layout.Horizontal style={{gap: 6}}> <Layout.Horizontal style={{gap: 6}}>
<LeftSidebarToggleButton /> <LeftSidebarToggleButton />
<NavbarButton
icon={MobileOutlined}
label="App Inspect"
toggled={topLevelSelection === 'appinspect'}
onClick={() => {
dispatch(setTopLevelSelection('appinspect'));
if (selectedPlugin) {
dispatch(
selectPlugin({
selectedPlugin,
selectedAppId,
selectedDevice: selectedDevice,
}),
);
} else {
dispatch(setStaticView(WelcomeScreenStaticView));
}
}}
/>
<AppSelector /> <AppSelector />
<StatusMessage /> <StatusMessage />
<NavbarScreenshotButton /> <NavbarScreenshotButton />
@@ -133,7 +101,7 @@ export const Navbar = withTrackingScope(function Navbar() {
<Layout.Horizontal style={{gap: 6, alignItems: 'center'}}> <Layout.Horizontal style={{gap: 6, alignItems: 'center'}}>
<NoConnectivityWarning /> <NoConnectivityWarning />
<NotificationButton topLevelSelection={topLevelSelection} /> <NotificationButton />
<TroubleshootMenu /> <TroubleshootMenu />
<ExtrasMenu /> <ExtrasMenu />
<RightSidebarToggleButton /> <RightSidebarToggleButton />
@@ -243,27 +211,38 @@ function ExportEverythingEverywhereAllAtOnceStatusModal({
); );
} }
function NotificationButton({ function NotificationButton() {
topLevelSelection, const store = useStore();
}: { const isOpen = useStore((store) => store.application.isNotificationModalOpen);
topLevelSelection: ToplevelNavigationItem;
}) {
const notifications = useStore((state) => state.notifications); const notifications = useStore((state) => state.notifications);
const activeNotifications = useMemoize(filterNotifications, [ const activeNotifications = useMemoize(filterNotifications, [
notifications.activeNotifications, notifications.activeNotifications,
notifications.blocklistedPlugins, notifications.blocklistedPlugins,
notifications.blocklistedCategories, notifications.blocklistedCategories,
]); ]);
const dispatch = useDispatch();
return ( return (
<NavbarButton <>
icon={BellOutlined} <NavbarButton
label="Alerts" icon={BellOutlined}
zIndex={AlertsZIndex} label="Alerts"
toggled={topLevelSelection === 'notification'} zIndex={AlertsZIndex}
count={activeNotifications.length} count={activeNotifications.length}
onClick={() => dispatch(setTopLevelSelection('notification'))} onClick={() => {
/> store.dispatch({type: 'isNotificationModalOpen', payload: true});
}}
/>
<Modal
visible={isOpen}
onCancel={() =>
store.dispatch({type: 'isNotificationModalOpen', payload: false})
}
width="70vw"
footer={null}>
<div style={{minHeight: '80vh', display: 'flex'}}>
<Notification />
</div>
</Modal>
</>
); );
} }

View File

@@ -25,7 +25,6 @@ import {useStore} from '../utils/useStore';
import {AppInspect} from './appinspect/AppInspect'; import {AppInspect} from './appinspect/AppInspect';
import PluginContainer from '../PluginContainer'; import PluginContainer from '../PluginContainer';
import {ContentContainer} from './ContentContainer'; import {ContentContainer} from './ContentContainer';
import {Notification} from './notification/Notification';
import {showChangelog} from '../chrome/ChangelogSheet'; import {showChangelog} from '../chrome/ChangelogSheet';
import PlatformSelectWizard, { import PlatformSelectWizard, {
hasPlatformWizardBeenDone, hasPlatformWizardBeenDone,
@@ -47,9 +46,6 @@ export function SandyApp() {
const leftSidebarVisible = useStore( const leftSidebarVisible = useStore(
(state) => state.application.leftSidebarVisible, (state) => state.application.leftSidebarVisible,
); );
const topLevelSelection = useStore(
(state) => state.application.topLevelSelection,
);
const staticView = useStore((state) => state.connections.staticView); const staticView = useStore((state) => state.connections.staticView);
useEffect(() => { useEffect(() => {
@@ -109,13 +105,6 @@ export function SandyApp() {
} }
}, []); }, []);
const leftMenuContent = !leftSidebarVisible ? null : topLevelSelection ===
'appinspect' ? (
<AppInspect />
) : topLevelSelection === 'notification' ? (
<Notification />
) : null;
return ( return (
<RootElement> <RootElement>
<Layout.Bottom> <Layout.Bottom>
@@ -128,11 +117,7 @@ export function SandyApp() {
}}> }}>
<Layout.Horizontal> <Layout.Horizontal>
<_Sidebar width={250} minWidth={220} maxWidth={800} gutter> <_Sidebar width={250} minWidth={220} maxWidth={800} gutter>
{leftMenuContent && ( {leftSidebarVisible ? <AppInspect /> : null}
<TrackingScope scope={topLevelSelection!}>
{leftMenuContent}
</TrackingScope>
)}
</_Sidebar> </_Sidebar>
</Layout.Horizontal> </Layout.Horizontal>
<MainContainer> <MainContainer>

View File

@@ -115,6 +115,7 @@ function NotificationEntry({notification}: {notification: PluginNotification}) {
pluginName, pluginName,
iconName, iconName,
} = notification; } = notification;
const store = useStore();
const actions = useMemo( const actions = useMemo(
() => ( () => (
@@ -163,7 +164,13 @@ function NotificationEntry({notification}: {notification: PluginNotification}) {
? `${clientName}/${appName}` ? `${clientName}/${appName}`
: clientName ?? appName ?? 'Not Connected'} : clientName ?? appName ?? 'Not Connected'}
</Text> </Text>
<Button style={{width: 'fit-content'}} size="small" onClick={onOpen}> <Button
style={{width: 'fit-content'}}
size="small"
onClick={() => {
onOpen();
store.dispatch({type: 'isNotificationModalOpen', payload: false});
}}>
Open {pluginName} Open {pluginName}
</Button> </Button>
</> </>
@@ -307,6 +314,7 @@ export function Notification() {
export function openNotification(store: Store, noti: PluginNotificationOrig) { export function openNotification(store: Store, noti: PluginNotificationOrig) {
const client = getClientById(store, noti.client); const client = getClientById(store, noti.client);
if (client) { if (client) {
store.dispatch({type: 'isNotificationModalOpen', payload: true});
store.dispatch( store.dispatch(
selectPlugin({ selectPlugin({
selectedPlugin: noti.pluginId, selectedPlugin: noti.pluginId,
@@ -318,6 +326,7 @@ export function openNotification(store: Store, noti: PluginNotificationOrig) {
} else { } else {
const device = getDeviceById(store, noti.client); const device = getDeviceById(store, noti.client);
if (device) { if (device) {
store.dispatch({type: 'isNotificationModalOpen', payload: true});
store.dispatch( store.dispatch(
selectPlugin({ selectPlugin({
selectedPlugin: noti.pluginId, selectedPlugin: noti.pluginId,