Wire up tracking to Sandy Chrome
Summary: Wired up tracking to all chrome sections and some import UI elements Reviewed By: jknoxville Differential Revision: D25219089 fbshipit-source-id: c75bed91894609dafc5fcc6423a5228211fb92d8
This commit is contained in:
committed by
Facebook GitHub Bot
parent
dd6f39c2b3
commit
84c6e05b8a
@@ -26,7 +26,11 @@ import electron, {MenuItemConstructorOptions} from 'electron';
|
||||
import {notNull} from './utils/typeUtils';
|
||||
import constants from './fb-stubs/constants';
|
||||
import {Logger} from './fb-interfaces/Logger';
|
||||
import {NormalizedMenuEntry, _buildInMenuEntries} from 'flipper-plugin';
|
||||
import {
|
||||
NormalizedMenuEntry,
|
||||
_buildInMenuEntries,
|
||||
_wrapInteractionHandler,
|
||||
} from 'flipper-plugin';
|
||||
import {StyleGuide} from './sandy-chrome/StyleGuide';
|
||||
import {showEmulatorLauncher} from './sandy-chrome/appinspect/LaunchEmulator';
|
||||
|
||||
@@ -191,7 +195,13 @@ export function addSandyPluginEntries(entries: NormalizedMenuEntry[]) {
|
||||
if (parent) {
|
||||
const item = new electron.remote.MenuItem({
|
||||
enabled: true,
|
||||
click: () => pluginActionHandler?.(entry.action!),
|
||||
click: _wrapInteractionHandler(
|
||||
() => pluginActionHandler?.(entry.action!),
|
||||
'MenuItem',
|
||||
'onClick',
|
||||
'flipper:menu:' + entry.topLevelMenu,
|
||||
entry.label,
|
||||
),
|
||||
label: entry.label,
|
||||
accelerator: entry.accelerator,
|
||||
});
|
||||
@@ -206,6 +216,20 @@ export function addSandyPluginEntries(entries: NormalizedMenuEntry[]) {
|
||||
}
|
||||
}
|
||||
|
||||
function trackMenuItems(menu: string, items: MenuItemConstructorOptions[]) {
|
||||
items.forEach((item) => {
|
||||
if (item.label && item.click) {
|
||||
item.click = _wrapInteractionHandler(
|
||||
item.click,
|
||||
'MenuItem',
|
||||
'onClick',
|
||||
'flipper:menu:' + menu,
|
||||
item.label,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getTemplate(
|
||||
app: electron.App,
|
||||
shell: electron.Shell,
|
||||
@@ -226,6 +250,8 @@ function getTemplate(
|
||||
click: () => startLinkExport(store.dispatch),
|
||||
});
|
||||
}
|
||||
trackMenuItems('export', exportSubmenu);
|
||||
|
||||
const fileSubmenu: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'Launch Emulator...',
|
||||
@@ -250,6 +276,8 @@ function getTemplate(
|
||||
submenu: exportSubmenu,
|
||||
},
|
||||
];
|
||||
trackMenuItems('file', fileSubmenu);
|
||||
|
||||
const supportRequestSubmenu = [
|
||||
{
|
||||
label: 'Create...',
|
||||
@@ -259,11 +287,101 @@ function getTemplate(
|
||||
},
|
||||
},
|
||||
];
|
||||
trackMenuItems('support', supportRequestSubmenu);
|
||||
|
||||
fileSubmenu.push({
|
||||
label: 'Support Requests',
|
||||
submenu: supportRequestSubmenu,
|
||||
});
|
||||
|
||||
const viewMenu: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click: function (_, focusedWindow: electron.BrowserWindow | undefined) {
|
||||
if (focusedWindow) {
|
||||
logger.track('usage', 'reload');
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: (function () {
|
||||
if (process.platform === 'darwin') {
|
||||
return 'Ctrl+Command+F';
|
||||
} else {
|
||||
return 'F11';
|
||||
}
|
||||
})(),
|
||||
click: function (_, focusedWindow: electron.BrowserWindow | undefined) {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Manage Plugins...',
|
||||
click: function () {
|
||||
store.dispatch(setActiveSheet(ACTIVE_SHEET_PLUGINS));
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Flipper style guide',
|
||||
click() {
|
||||
store.dispatch(setStaticView(StyleGuide));
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: (function () {
|
||||
if (process.platform === 'darwin') {
|
||||
return 'Alt+Command+I';
|
||||
} else {
|
||||
return 'Ctrl+Shift+I';
|
||||
}
|
||||
})(),
|
||||
click: function (_, focusedWindow: electron.BrowserWindow | undefined) {
|
||||
if (focusedWindow) {
|
||||
// @ts-ignore: https://github.com/electron/electron/issues/7832
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'separator',
|
||||
},
|
||||
];
|
||||
trackMenuItems('view', viewMenu);
|
||||
|
||||
const helpMenu: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'Getting started',
|
||||
click: function () {
|
||||
shell.openExternal('https://fbflipper.com/docs/getting-started/index');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Create plugins',
|
||||
click: function () {
|
||||
shell.openExternal('https://fbflipper.com/docs/tutorial/intro');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Report problems',
|
||||
click: function () {
|
||||
shell.openExternal(constants.FEEDBACK_GROUP_LINK);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Changelog',
|
||||
click() {
|
||||
store.dispatch(setActiveSheet(ACTIVE_SHEET_CHANGELOG));
|
||||
},
|
||||
},
|
||||
];
|
||||
trackMenuItems('help', helpMenu);
|
||||
|
||||
const template: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'File',
|
||||
@@ -309,73 +427,7 @@ function getTemplate(
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click: function (
|
||||
_,
|
||||
focusedWindow: electron.BrowserWindow | undefined,
|
||||
) {
|
||||
if (focusedWindow) {
|
||||
logger.track('usage', 'reload');
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: (function () {
|
||||
if (process.platform === 'darwin') {
|
||||
return 'Ctrl+Command+F';
|
||||
} else {
|
||||
return 'F11';
|
||||
}
|
||||
})(),
|
||||
click: function (
|
||||
_,
|
||||
focusedWindow: electron.BrowserWindow | undefined,
|
||||
) {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Manage Plugins...',
|
||||
click: function () {
|
||||
store.dispatch(setActiveSheet(ACTIVE_SHEET_PLUGINS));
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Flipper style guide',
|
||||
click() {
|
||||
store.dispatch(setStaticView(StyleGuide));
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: (function () {
|
||||
if (process.platform === 'darwin') {
|
||||
return 'Alt+Command+I';
|
||||
} else {
|
||||
return 'Ctrl+Shift+I';
|
||||
}
|
||||
})(),
|
||||
click: function (
|
||||
_,
|
||||
focusedWindow: electron.BrowserWindow | undefined,
|
||||
) {
|
||||
if (focusedWindow) {
|
||||
// @ts-ignore: https://github.com/electron/electron/issues/7832
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'separator',
|
||||
},
|
||||
],
|
||||
submenu: viewMenu,
|
||||
},
|
||||
{
|
||||
label: 'Window',
|
||||
@@ -396,36 +448,10 @@ function getTemplate(
|
||||
{
|
||||
label: 'Help',
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Getting started',
|
||||
click: function () {
|
||||
shell.openExternal(
|
||||
'https://fbflipper.com/docs/getting-started/index',
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Create plugins',
|
||||
click: function () {
|
||||
shell.openExternal('https://fbflipper.com/docs/tutorial/intro');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Report problems',
|
||||
click: function () {
|
||||
shell.openExternal(constants.FEEDBACK_GROUP_LINK);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Changelog',
|
||||
click() {
|
||||
store.dispatch(setActiveSheet(ACTIVE_SHEET_CHANGELOG));
|
||||
},
|
||||
},
|
||||
],
|
||||
submenu: helpMenu,
|
||||
},
|
||||
];
|
||||
trackMenuItems('support', supportRequestSubmenu);
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
const name = app.name;
|
||||
|
||||
@@ -48,15 +48,15 @@ export default function ScreenCaptureButtons({useSandy}: {useSandy?: boolean}) {
|
||||
|
||||
const handleScreenshot = useCallback(() => {
|
||||
setIsTakingScreenshot(true);
|
||||
capture(selectedDevice!)
|
||||
.then(openFile)
|
||||
.catch((e) => {
|
||||
const p = capture(selectedDevice!).then(openFile);
|
||||
|
||||
p.catch((e) => {
|
||||
console.error('Taking screenshot failed:', e);
|
||||
message.error('Taking screenshot failed:' + e);
|
||||
})
|
||||
.finally(() => {
|
||||
}).finally(() => {
|
||||
setIsTakingScreenshot(false);
|
||||
});
|
||||
return p;
|
||||
}, [selectedDevice]);
|
||||
const handleRecording = useCallback(() => {
|
||||
if (!selectedDevice) {
|
||||
@@ -65,13 +65,13 @@ export default function ScreenCaptureButtons({useSandy}: {useSandy?: boolean}) {
|
||||
if (!isRecording) {
|
||||
setIsRecording(true);
|
||||
const videoPath = path.join(CAPTURE_LOCATION, getFileName('mp4'));
|
||||
selectedDevice.startScreenCapture(videoPath).catch((e) => {
|
||||
return selectedDevice.startScreenCapture(videoPath).catch((e) => {
|
||||
console.error('Failed to start recording', e);
|
||||
message.error('Failed to start recording' + e);
|
||||
setIsRecording(false);
|
||||
});
|
||||
} else {
|
||||
selectedDevice
|
||||
return selectedDevice
|
||||
.stopScreenCapture()
|
||||
.then(openFile)
|
||||
.catch((e) => {
|
||||
|
||||
@@ -28,7 +28,7 @@ import LauncherSettingsPanel from '../fb-stubs/LauncherSettingsPanel';
|
||||
import SandySettingsPanel from '../fb-stubs/SandySettingsPanel';
|
||||
import {reportUsage} from '../utils/metrics';
|
||||
import {Modal} from 'antd';
|
||||
import {Layout, _NuxManagerContext} from 'flipper-plugin';
|
||||
import {Layout, withTrackingScope, _NuxManagerContext} from 'flipper-plugin';
|
||||
|
||||
const Container = styled(FlexColumn)({
|
||||
padding: 20,
|
||||
@@ -356,7 +356,7 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
||||
isXcodeDetected: application.xcodeCommandLineToolsDetected,
|
||||
}),
|
||||
{updateSettings, updateLauncherSettings},
|
||||
)(SettingsSheet);
|
||||
)(withTrackingScope(SettingsSheet));
|
||||
|
||||
function ResetTooltips() {
|
||||
const nuxManager = useContext(_NuxManagerContext);
|
||||
|
||||
@@ -27,6 +27,7 @@ import ContextMenu from '../ui/components/ContextMenu';
|
||||
import {clipboard} from 'electron';
|
||||
import {reportPlatformFailures} from '../utils/metrics';
|
||||
import {Modal} from 'antd';
|
||||
import {TrackingScope} from 'flipper-plugin';
|
||||
|
||||
const Container = styled(FlexColumn)({
|
||||
padding: 20,
|
||||
@@ -135,6 +136,7 @@ class SignInSheet extends Component<Props, State> {
|
||||
footer: React.ReactElement,
|
||||
) {
|
||||
return (
|
||||
<TrackingScope scope="logindialog">
|
||||
<Modal
|
||||
visible
|
||||
centered
|
||||
@@ -144,6 +146,7 @@ class SignInSheet extends Component<Props, State> {
|
||||
footer={footer}>
|
||||
<FlexColumn>{contents}</FlexColumn>
|
||||
</Modal>
|
||||
</TrackingScope>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ const {shell, remote} = !isHeadless()
|
||||
: {shell: undefined, remote: undefined};
|
||||
import {PureComponent} from 'react';
|
||||
import React from 'react';
|
||||
import {Tracked, TrackingScope} from 'flipper-plugin';
|
||||
|
||||
const Container = styled(FlexColumn)({
|
||||
height: '100%',
|
||||
@@ -127,6 +128,7 @@ export default class WelcomeScreen extends PureComponent<Props, State> {
|
||||
render() {
|
||||
return (
|
||||
<Container>
|
||||
<TrackingScope scope="welcomescreen">
|
||||
<Welcome isMounted={this.state.isMounted}>
|
||||
<Logo src="./icon.png" />
|
||||
<Title>Welcome to Flipper</Title>
|
||||
@@ -135,11 +137,14 @@ export default class WelcomeScreen extends PureComponent<Props, State> {
|
||||
? `Version ${remote.app.getVersion()}`
|
||||
: 'Development Mode'}
|
||||
</Version>
|
||||
<Tracked>
|
||||
<Item
|
||||
onClick={() =>
|
||||
onClick={() => {
|
||||
shell &&
|
||||
shell.openExternal('https://fbflipper.com/docs/features/index')
|
||||
}>
|
||||
shell.openExternal(
|
||||
'https://fbflipper.com/docs/features/index',
|
||||
);
|
||||
}}>
|
||||
<Icon size={20} name="rocket" color={brandColors.Flipper} />
|
||||
<FlexColumn>
|
||||
<ItemTitle>Using Flipper</ItemTitle>
|
||||
@@ -151,7 +156,9 @@ export default class WelcomeScreen extends PureComponent<Props, State> {
|
||||
<Item
|
||||
onClick={() =>
|
||||
shell &&
|
||||
shell.openExternal('https://fbflipper.com/docs/tutorial/intro')
|
||||
shell.openExternal(
|
||||
'https://fbflipper.com/docs/tutorial/intro',
|
||||
)
|
||||
}>
|
||||
<Icon size={20} name="magic-wand" color={brandColors.Flipper} />
|
||||
<FlexColumn>
|
||||
@@ -184,7 +191,9 @@ export default class WelcomeScreen extends PureComponent<Props, State> {
|
||||
</ItemSubTitle>
|
||||
</FlexColumn>
|
||||
</Item>
|
||||
</Tracked>
|
||||
</Welcome>
|
||||
</TrackingScope>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ const demos: PreviewProps[] = [
|
||||
],
|
||||
demos: {
|
||||
'Basic example': (
|
||||
<TrackingScope scope="Tracking scope demo">
|
||||
<TrackingScope scope="tracking scope demo">
|
||||
<Tracked>
|
||||
<Button onClick={() => {}}>Test</Button>
|
||||
</Tracked>
|
||||
@@ -356,6 +356,7 @@ const demos: PreviewProps[] = [
|
||||
function ComponentPreview({title, demos, description, props}: PreviewProps) {
|
||||
return (
|
||||
<Card title={title} size="small" type="inner">
|
||||
<TrackingScope scope={title}>
|
||||
<Layout.Container gap="small">
|
||||
<Text type="secondary">{description}</Text>
|
||||
<Collapse ghost>
|
||||
@@ -415,6 +416,7 @@ function ComponentPreview({title, demos, description, props}: PreviewProps) {
|
||||
</Collapse.Panel>
|
||||
</Collapse>
|
||||
</Layout.Container>
|
||||
</TrackingScope>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import {
|
||||
toggleLeftSidebarVisible,
|
||||
toggleRightSidebarVisible,
|
||||
} from '../reducers/application';
|
||||
import {theme, Layout} from 'flipper-plugin';
|
||||
import {theme, Layout, withTrackingScope} from 'flipper-plugin';
|
||||
import SetupDoctorScreen, {checkHasNewProblem} from './SetupDoctorScreen';
|
||||
import SettingsSheet from '../chrome/SettingsSheet';
|
||||
import WelcomeScreen from './WelcomeScreen';
|
||||
@@ -98,6 +98,7 @@ export function LeftRailButton({
|
||||
return (
|
||||
<Tooltip title={title} placement="right">
|
||||
<LeftRailButtonElem
|
||||
title={title}
|
||||
kind={small ? 'small' : undefined}
|
||||
type={selected ? 'primary' : 'ghost'}
|
||||
icon={iconElement}
|
||||
@@ -119,7 +120,7 @@ const LeftRailDivider = styled(Divider)({
|
||||
});
|
||||
LeftRailDivider.displayName = 'LeftRailDividier';
|
||||
|
||||
export function LeftRail({
|
||||
export const LeftRail = withTrackingScope(function LeftRail({
|
||||
toplevelSelection,
|
||||
setToplevelSelection,
|
||||
}: ToplevelProps) {
|
||||
@@ -167,7 +168,7 @@ export function LeftRail({
|
||||
</Layout.Bottom>
|
||||
</Layout.Container>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
function LeftSidebarToggleButton() {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@@ -127,9 +127,9 @@ export function SandyApp({logger}: {logger: Logger}) {
|
||||
{staticView ? (
|
||||
<TrackingScope
|
||||
scope={
|
||||
staticView.constructor?.name ??
|
||||
staticView.displayName ??
|
||||
staticView.name ??
|
||||
staticView.constructor?.name ??
|
||||
'unknown static view'
|
||||
}>
|
||||
<ContentContainer>
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
CodeOutlined,
|
||||
BugOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import {theme} from 'flipper-plugin';
|
||||
import {theme, Tracked, TrackingScope} from 'flipper-plugin';
|
||||
|
||||
const {Text, Title} = Typography;
|
||||
|
||||
@@ -45,6 +45,7 @@ function Row(props: {
|
||||
onClick?: () => void;
|
||||
}) {
|
||||
return (
|
||||
<Tracked action={props.title}>
|
||||
<RowContainer onClick={props.onClick}>
|
||||
<Space size="middle">
|
||||
{cloneElement(props.icon, {
|
||||
@@ -58,6 +59,7 @@ function Row(props: {
|
||||
</FlexColumn>
|
||||
</Space>
|
||||
</RowContainer>
|
||||
</Tracked>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,6 +116,7 @@ export default function WelcomeScreen({
|
||||
/>
|
||||
}
|
||||
onCancel={onClose}>
|
||||
<TrackingScope scope="welcomescreen">
|
||||
<Space
|
||||
direction="vertical"
|
||||
size="middle"
|
||||
@@ -154,6 +157,7 @@ export default function WelcomeScreen({
|
||||
onClick={openExternal(constants.FEEDBACK_GROUP_LINK)}
|
||||
/>
|
||||
</Space>
|
||||
</TrackingScope>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ import {
|
||||
CaretDownOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import {Glyph, Layout, styled} from '../../ui';
|
||||
import {theme} from 'flipper-plugin';
|
||||
import {theme, useTrackedCallback} from 'flipper-plugin';
|
||||
import {batch} from 'react-redux';
|
||||
import {Dispatch, useDispatch, useStore} from '../../utils/useStore';
|
||||
import {useDispatch, useStore} from '../../utils/useStore';
|
||||
import {
|
||||
canBeDefaultDevice,
|
||||
getAvailableClients,
|
||||
@@ -55,11 +55,34 @@ export function AppSelector() {
|
||||
uninitializedClients,
|
||||
selectedApp,
|
||||
} = useStore((state) => state.connections);
|
||||
|
||||
const onSelectDevice = useTrackedCallback(
|
||||
'select-device',
|
||||
(device: BaseDevice) => {
|
||||
batch(() => {
|
||||
dispatch(selectDevice(device));
|
||||
dispatch(selectClient(null));
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
const onSelectApp = useTrackedCallback(
|
||||
'select-app',
|
||||
(device: BaseDevice, client: Client) => {
|
||||
batch(() => {
|
||||
dispatch(selectDevice(device));
|
||||
dispatch(selectClient(client.id));
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const entries = computeEntries(
|
||||
devices,
|
||||
dispatch,
|
||||
clients,
|
||||
uninitializedClients,
|
||||
onSelectDevice,
|
||||
onSelectApp,
|
||||
);
|
||||
const client = clients.find((client) => client.id === selectedApp);
|
||||
|
||||
@@ -144,9 +167,10 @@ const AppIconContainer = styled.div({
|
||||
|
||||
function computeEntries(
|
||||
devices: BaseDevice[],
|
||||
dispatch: Dispatch,
|
||||
clients: Client[],
|
||||
uninitializedClients: State['connections']['uninitializedClients'],
|
||||
onSelectDevice: (device: BaseDevice) => void,
|
||||
onSelectApp: (device: BaseDevice, client: Client) => void,
|
||||
) {
|
||||
const entries = devices.filter(canBeDefaultDevice).map((device) => {
|
||||
const deviceEntry = (
|
||||
@@ -155,10 +179,7 @@ function computeEntries(
|
||||
key={device.serial}
|
||||
style={{fontWeight: 'bold'}}
|
||||
onClick={() => {
|
||||
batch(() => {
|
||||
dispatch(selectDevice(device));
|
||||
dispatch(selectClient(null));
|
||||
});
|
||||
onSelectDevice(device);
|
||||
}}>
|
||||
{device.displayTitle()}
|
||||
</Menu.Item>
|
||||
@@ -167,10 +188,7 @@ function computeEntries(
|
||||
<Menu.Item
|
||||
key={client.id}
|
||||
onClick={() => {
|
||||
batch(() => {
|
||||
dispatch(selectDevice(device));
|
||||
dispatch(selectClient(client.id));
|
||||
});
|
||||
onSelectApp(device, client);
|
||||
}}>
|
||||
<Radio value={client.id}>{client.query.app}</Radio>
|
||||
</Menu.Item>
|
||||
|
||||
@@ -7,11 +7,17 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import React, {useCallback, useMemo} from 'react';
|
||||
import React, {useMemo} from 'react';
|
||||
import {AutoComplete, Input, Typography} from 'antd';
|
||||
import {StarFilled, StarOutlined} from '@ant-design/icons';
|
||||
import {useStore} from '../../utils/useStore';
|
||||
import {Layout, NUX, useValue} from 'flipper-plugin';
|
||||
import {
|
||||
Layout,
|
||||
NUX,
|
||||
TrackingScope,
|
||||
useTrackedCallback,
|
||||
useValue,
|
||||
} from 'flipper-plugin';
|
||||
import {navPluginStateSelector} from '../../chrome/LocationsButton';
|
||||
|
||||
// eslint-disable-next-line flipper/no-relative-imports-across-packages
|
||||
@@ -25,11 +31,13 @@ export function BookmarkSection() {
|
||||
const navPlugin = useStore(navPluginStateSelector);
|
||||
|
||||
return navPlugin ? (
|
||||
<TrackingScope scope="bookmarks">
|
||||
<NUX
|
||||
title="Use bookmarks to directly navigate to a location in the app."
|
||||
placement="right">
|
||||
<BookmarkSectionInput navPlugin={navPlugin} />
|
||||
</NUX>
|
||||
</TrackingScope>
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -48,7 +56,9 @@ function BookmarkSectionInput({navPlugin}: {navPlugin: NavigationPlugin}) {
|
||||
[currentURI, bookmarks, patterns, 20],
|
||||
);
|
||||
|
||||
const handleBookmarkClick = useCallback(() => {
|
||||
const handleBookmarkClick = useTrackedCallback(
|
||||
'bookmark',
|
||||
() => {
|
||||
if (isBookmarked) {
|
||||
navPlugin.removeBookmark(currentURI);
|
||||
} else if (currentURI) {
|
||||
@@ -57,7 +67,11 @@ function BookmarkSectionInput({navPlugin}: {navPlugin: NavigationPlugin}) {
|
||||
commonName: null,
|
||||
});
|
||||
}
|
||||
}, [navPlugin, currentURI, isBookmarked]);
|
||||
},
|
||||
[navPlugin, currentURI, isBookmarked],
|
||||
);
|
||||
|
||||
const navigate = useTrackedCallback('navigate', navPlugin.navigateTo, []);
|
||||
|
||||
const bookmarkButton = isBookmarked ? (
|
||||
<StarFilled onClick={handleBookmarkClick} />
|
||||
@@ -69,7 +83,7 @@ function BookmarkSectionInput({navPlugin}: {navPlugin: NavigationPlugin}) {
|
||||
<StyledAutoComplete
|
||||
dropdownMatchSelectWidth={500}
|
||||
value={currentURI}
|
||||
onSelect={navPlugin.navigateTo}
|
||||
onSelect={navigate}
|
||||
style={{flex: 1}}
|
||||
options={[
|
||||
{
|
||||
@@ -99,7 +113,7 @@ function BookmarkSectionInput({navPlugin}: {navPlugin: NavigationPlugin}) {
|
||||
navPlugin.currentURI.set(e.target.value);
|
||||
}}
|
||||
onPressEnter={() => {
|
||||
navPlugin.navigateTo(currentURI);
|
||||
navigate(currentURI);
|
||||
}}
|
||||
/>
|
||||
</StyledAutoComplete>
|
||||
|
||||
@@ -13,7 +13,7 @@ import {AndroidOutlined, AppleOutlined} from '@ant-design/icons';
|
||||
import {Store} from '../../reducers';
|
||||
import {useStore} from '../../utils/useStore';
|
||||
import {launchEmulator} from '../../devices/AndroidDevice';
|
||||
import {Layout, renderReactRoot} from 'flipper-plugin';
|
||||
import {Layout, renderReactRoot, withTrackingScope} from 'flipper-plugin';
|
||||
import {Provider} from 'react-redux';
|
||||
import {
|
||||
launchSimulator,
|
||||
@@ -31,16 +31,19 @@ export function showEmulatorLauncher(store: Store) {
|
||||
|
||||
type GetSimulators = typeof getSimulators;
|
||||
|
||||
export function LaunchEmulatorDialog({
|
||||
export const LaunchEmulatorDialog = withTrackingScope(
|
||||
function LaunchEmulatorDialog({
|
||||
onClose,
|
||||
getSimulators,
|
||||
}: {
|
||||
}: {
|
||||
onClose: () => void;
|
||||
getSimulators: GetSimulators;
|
||||
}) {
|
||||
}) {
|
||||
const iosEnabled = useStore((state) => state.settingsState.enableIOS);
|
||||
const androidEmulators = useStore((state) =>
|
||||
state.settingsState.enableAndroid ? state.connections.androidEmulators : [],
|
||||
state.settingsState.enableAndroid
|
||||
? state.connections.androidEmulators
|
||||
: [],
|
||||
);
|
||||
const [iosEmulators, setIosEmulators] = useState<IOSDeviceParams[]>([]);
|
||||
|
||||
@@ -64,14 +67,14 @@ export function LaunchEmulatorDialog({
|
||||
<Button
|
||||
key={name}
|
||||
icon={<AndroidOutlined />}
|
||||
onClick={() => {
|
||||
onClick={() =>
|
||||
launchEmulator(name)
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
message.error('Failed to start emulator: ' + e);
|
||||
})
|
||||
.finally(onClose);
|
||||
}}>
|
||||
.then(onClose)
|
||||
}>
|
||||
{name}
|
||||
</Button>
|
||||
)),
|
||||
@@ -79,14 +82,14 @@ export function LaunchEmulatorDialog({
|
||||
<Button
|
||||
key={device.udid}
|
||||
icon={<AppleOutlined />}
|
||||
onClick={() => {
|
||||
onClick={() =>
|
||||
launchSimulator(device.udid)
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
message.error('Failed to start simulator: ' + e);
|
||||
})
|
||||
.finally(onClose);
|
||||
}}>
|
||||
.then(onClose)
|
||||
}>
|
||||
{device.name}
|
||||
</Button>
|
||||
)),
|
||||
@@ -104,4 +107,5 @@ export function LaunchEmulatorDialog({
|
||||
</Layout.Container>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -12,7 +12,7 @@ import {Badge, Button, Menu, Tooltip, Typography} from 'antd';
|
||||
import {InfoIcon, SidebarTitle} from '../LeftSidebar';
|
||||
import {PlusOutlined, MinusOutlined} from '@ant-design/icons';
|
||||
import {Glyph, Layout, styled} from '../../ui';
|
||||
import {theme, NUX} from 'flipper-plugin';
|
||||
import {theme, NUX, Tracked} from 'flipper-plugin';
|
||||
import {useDispatch, useStore} from '../../utils/useStore';
|
||||
import {getPluginTitle, sortPluginsByName} from '../../utils/pluginUtils';
|
||||
import {ClientPluginDefinition, DevicePluginDefinition} from '../../plugin';
|
||||
@@ -225,8 +225,9 @@ function ActionButton({
|
||||
icon={icon}
|
||||
title={title}
|
||||
style={{border: 'none', color: theme.textColorPrimary}}
|
||||
onClick={() => {
|
||||
onClick={(e) => {
|
||||
onClick(id);
|
||||
e.stopPropagation();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -273,6 +274,7 @@ const PluginEntry = memo(function PluginEntry({
|
||||
}, [active]);
|
||||
|
||||
return (
|
||||
<Tracked action={`open:${plugin.id}`}>
|
||||
<Menu.Item
|
||||
key={plugin.id}
|
||||
active={active}
|
||||
@@ -293,6 +295,7 @@ const PluginEntry = memo(function PluginEntry({
|
||||
{hovering && actions}
|
||||
</Layout.Horizontal>
|
||||
</Menu.Item>
|
||||
</Tracked>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import {useStore} from '../../utils/useStore';
|
||||
import {useIsSandy} from '../../sandy-chrome/SandyContext';
|
||||
import type {ButtonProps} from 'antd/lib/button';
|
||||
import {DownOutlined, CheckOutlined} from '@ant-design/icons';
|
||||
import {theme} from 'flipper-plugin';
|
||||
import {theme, Tracked} from 'flipper-plugin';
|
||||
|
||||
type ButtonType = 'primary' | 'success' | 'warning' | 'danger';
|
||||
|
||||
@@ -366,6 +366,7 @@ function ClassicButton(props: Props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<Tracked>
|
||||
<StyledButton
|
||||
{...restProps}
|
||||
ref={_ref as any}
|
||||
@@ -377,6 +378,7 @@ function ClassicButton(props: Props) {
|
||||
{iconComponent}
|
||||
{children}
|
||||
</StyledButton>
|
||||
</Tracked>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import Tooltip from './Tooltip';
|
||||
import {colors} from './colors';
|
||||
import styled from '@emotion/styled';
|
||||
import React from 'react';
|
||||
import {Tracked} from 'flipper-plugin';
|
||||
|
||||
type Props = React.ComponentProps<typeof ToolbarIconContainer> & {
|
||||
active?: boolean;
|
||||
@@ -30,6 +31,7 @@ const ToolbarIconContainer = styled.div({
|
||||
export default function ToolbarIcon({active, icon, title, ...props}: Props) {
|
||||
return (
|
||||
<Tooltip title={title}>
|
||||
<Tracked action={title}>
|
||||
<ToolbarIconContainer {...props}>
|
||||
<Glyph
|
||||
name={icon}
|
||||
@@ -41,6 +43,7 @@ export default function ToolbarIcon({active, icon, title, ...props}: Props) {
|
||||
}
|
||||
/>
|
||||
</ToolbarIconContainer>
|
||||
</Tracked>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ export {
|
||||
setGlobalInteractionReporter as _setGlobalInteractionReporter,
|
||||
withTrackingScope,
|
||||
useTrackedCallback,
|
||||
wrapInteractionHandler as _wrapInteractionHandler,
|
||||
} from './ui/Tracked';
|
||||
|
||||
export {sleep} from './utils/sleep';
|
||||
|
||||
@@ -21,6 +21,7 @@ import {createHash} from 'crypto';
|
||||
import type {TooltipPlacement} from 'antd/lib/tooltip';
|
||||
import {SandyPluginInstance} from '../plugin/Plugin';
|
||||
import {theme} from './theme';
|
||||
import {Tracked} from './Tracked';
|
||||
|
||||
const {Text} = Typography;
|
||||
|
||||
@@ -121,9 +122,11 @@ export function NUX({
|
||||
style={{color: theme.textColorPrimary}}>
|
||||
<BulbTwoTone style={{fontSize: 24}} />
|
||||
<Text>{title}</Text>
|
||||
<Tracked action={'nux:dismiss:' + title.substr(0, 50)}>
|
||||
<Button size="small" type="default" onClick={dismiss}>
|
||||
Dismiss
|
||||
</Button>
|
||||
</Tracked>
|
||||
</Layout.Container>
|
||||
}>
|
||||
<Pulse />
|
||||
|
||||
@@ -109,7 +109,6 @@ export function useTrackedCallback<T extends Function>(
|
||||
}, deps) as any;
|
||||
}
|
||||
|
||||
// Exported for test
|
||||
export function wrapInteractionHandler<T extends Function>(
|
||||
fn: T,
|
||||
element: React.ReactElement | null | string,
|
||||
|
||||
Reference in New Issue
Block a user