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:
committed by
Facebook GitHub Bot
parent
08371d3a6b
commit
9cceca6d7e
@@ -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',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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
|
<NavbarButton
|
||||||
icon={BellOutlined}
|
icon={BellOutlined}
|
||||||
label="Alerts"
|
label="Alerts"
|
||||||
zIndex={AlertsZIndex}
|
zIndex={AlertsZIndex}
|
||||||
toggled={topLevelSelection === 'notification'}
|
|
||||||
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>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user