export button

Reviewed By: lblasa

Differential Revision: D47439113

fbshipit-source-id: 551daf5e36463bf54ff8191e313b43dd96003b97
This commit is contained in:
Anton Kastritskiy
2023-07-18 03:52:34 -07:00
committed by Facebook GitHub Bot
parent af73e5a2b4
commit cb183cc354
2 changed files with 153 additions and 146 deletions

View File

@@ -8,8 +8,8 @@
*/ */
import React, {cloneElement, useState, useCallback} from 'react'; import React, {cloneElement, useState, useCallback} from 'react';
import {Button, Divider, Badge, Tooltip, Menu, Modal} from 'antd'; import {Button, Divider, Badge, Tooltip, Menu} from 'antd';
import {SettingOutlined, BugOutlined} from '@ant-design/icons'; import {SettingOutlined} from '@ant-design/icons';
import {useStore} from '../utils/useStore'; import {useStore} from '../utils/useStore';
import { import {
theme, theme,
@@ -20,7 +20,6 @@ import {
} from 'flipper-plugin'; } from 'flipper-plugin';
import SettingsSheet from '../chrome/SettingsSheet'; import SettingsSheet from '../chrome/SettingsSheet';
import WelcomeScreen from './WelcomeScreen'; import WelcomeScreen from './WelcomeScreen';
import config from '../fb-stubs/config';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import {setStaticView} from '../reducers/connections'; import {setStaticView} from '../reducers/connections';
import {SandyRatingButton} from '../chrome/RatingButton'; import {SandyRatingButton} from '../chrome/RatingButton';
@@ -29,17 +28,14 @@ import constants from '../fb-stubs/constants';
import { import {
canFileExport, canFileExport,
canOpenDialog, canOpenDialog,
exportEverythingEverywhereAllAtOnce,
showOpenDialog, showOpenDialog,
startFileExport, startFileExport,
startLinkExport, startLinkExport,
ExportEverythingEverywhereAllAtOnceStatus,
} from '../utils/exportData'; } from '../utils/exportData';
import {openDeeplinkDialog} from '../deeplink'; import {openDeeplinkDialog} from '../deeplink';
import {css} from '@emotion/css'; import {css} from '@emotion/css';
import {getRenderHostInstance} from 'flipper-frontend-core'; import {getRenderHostInstance} from 'flipper-frontend-core';
import {StyleGuide} from './StyleGuide'; import {StyleGuide} from './StyleGuide';
import {useEffect} from 'react';
const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({ const LeftRailButtonElem = styled(Button)<{kind?: 'small'}>(({kind}) => ({
width: kind === 'small' ? 32 : 36, width: kind === 'small' ? 32 : 36,
@@ -129,7 +125,6 @@ export const LeftRail = withTrackingScope(function LeftRail() {
<Layout.Container center gap={10} padh={6}> <Layout.Container center gap={10} padh={6}>
<UpdateIndicator /> <UpdateIndicator />
<SandyRatingButton /> <SandyRatingButton />
<ExportEverythingEverywhereAllAtOnceButton />
<ExtrasMenu /> <ExtrasMenu />
</Layout.Container> </Layout.Container>
</Layout.Container> </Layout.Container>
@@ -257,139 +252,3 @@ function ExtrasMenu() {
</> </>
); );
} }
function ExportEverythingEverywhereAllAtOnceStatusModal({
status,
setStatus,
}: {
status: ExportEverythingEverywhereAllAtOnceStatus | undefined;
setStatus: (
newStatus: ExportEverythingEverywhereAllAtOnceStatus | undefined,
) => void;
}) {
const [statusMessage, setStatusMessage] = useState<JSX.Element | undefined>();
useEffect(() => {
switch (status?.[0]) {
case 'logs': {
setStatusMessage(<p>Exporting Flipper logs...</p>);
return;
}
case 'files': {
let sheepCount = 0;
const setFileExportMessage = () => {
setStatusMessage(
<>
<p>Exporting Flipper debug files from all devices...</p>
<p>It could take a long time!</p>
<p>Let's count sheep while we wait: {sheepCount++}.</p>
<p>We'll skip it automatically if it exceeds 3 minutes.</p>
</>,
);
};
setFileExportMessage();
const interval = setInterval(setFileExportMessage, 3000);
return () => clearInterval(interval);
}
case 'state': {
let dinosaursCount = 0;
const setStateExportMessage = () => {
setStatusMessage(
<>
<p>Exporting Flipper state...</p>
<p>It also could take a long time!</p>
<p>This time we could count dinosaurs: {dinosaursCount++}.</p>
<p>We'll skip it automatically if it exceeds 2 minutes.</p>
</>,
);
};
setStateExportMessage();
const interval = setInterval(setStateExportMessage, 2000);
return () => clearInterval(interval);
}
case 'archive': {
setStatusMessage(<p>Creating an archive...</p>);
return;
}
case 'upload': {
setStatusMessage(<p>Uploading the archive...</p>);
return;
}
case 'support': {
setStatusMessage(<p>Creating a support request...</p>);
return;
}
case 'error': {
setStatusMessage(
<>
<p>Oops! Something went wrong.</p>
<p>{status[1]}</p>
</>,
);
return;
}
case 'done': {
setStatusMessage(<p>Done!</p>);
return;
}
case 'cancelled': {
setStatusMessage(<p>Cancelled! Why? 😱🤯👏</p>);
return;
}
}
}, [status]);
return (
<Modal
visible={!!status}
centered
onCancel={() => {
setStatus(undefined);
}}
title="Exporting everything everywhere all at once"
footer={null}>
{statusMessage}
</Modal>
);
}
function ExportEverythingEverywhereAllAtOnceButton() {
const store = useStore();
const [status, setStatus] = useState<
ExportEverythingEverywhereAllAtOnceStatus | undefined
>();
const exportEverythingEverywhereAllAtOnceTracked = useTrackedCallback(
'Debug data export',
() =>
exportEverythingEverywhereAllAtOnce(
store,
(...args) => setStatus(args),
config.isFBBuild,
),
[store, setStatus],
);
return (
<>
<ExportEverythingEverywhereAllAtOnceStatusModal
status={status}
setStatus={setStatus}
/>
<NUX title="Press this button if you have issues with Flipper. It will collect Flipper debug data that you can send to the Flipper team to get help.">
<LeftRailButton
icon={<BugOutlined />}
title="Export Flipper debug data"
onClick={() => {
exportEverythingEverywhereAllAtOnceTracked();
}}
small
/>
</NUX>
</>
);
}

View File

@@ -10,23 +10,32 @@
import { import {
Dialog, Dialog,
Layout, Layout,
NUX,
styled, styled,
theme, theme,
useMemoize, useMemoize,
useTrackedCallback,
useValue, useValue,
withTrackingScope, withTrackingScope,
} from 'flipper-plugin'; } from 'flipper-plugin';
import {getRenderHostInstance} from 'flipper-frontend-core'; import {getRenderHostInstance} from 'flipper-frontend-core';
import React, {cloneElement, useCallback, useMemo, useState} from 'react'; import React, {
cloneElement,
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import {useDispatch, useStore} from '../utils/useStore'; import {useDispatch, useStore} from '../utils/useStore';
import config from '../fb-stubs/config'; import config from '../fb-stubs/config';
import {isConnected, currentUser, logoutUser} from '../fb-stubs/user'; import {isConnected, currentUser, logoutUser} from '../fb-stubs/user';
import {showLoginDialog} from '../chrome/fb-stubs/SignInSheet'; import {showLoginDialog} from '../chrome/fb-stubs/SignInSheet';
import {Avatar, Badge, Button, Popover, Tooltip} from 'antd'; import {Avatar, Badge, Button, Modal, Popover, Tooltip} from 'antd';
import { import {
ApiOutlined, ApiOutlined,
AppstoreAddOutlined, AppstoreAddOutlined,
BellOutlined, BellOutlined,
BugOutlined,
CameraOutlined, CameraOutlined,
EllipsisOutlined, EllipsisOutlined,
FileExclamationOutlined, FileExclamationOutlined,
@@ -52,6 +61,10 @@ import FpsGraph from '../chrome/FpsGraph';
import NetworkGraph from '../chrome/NetworkGraph'; import NetworkGraph from '../chrome/NetworkGraph';
import {errorCounterAtom} from '../chrome/ConsoleLogs'; import {errorCounterAtom} from '../chrome/ConsoleLogs';
import {filterNotifications} from './notification/notificationUtils'; import {filterNotifications} from './notification/notificationUtils';
import {
exportEverythingEverywhereAllAtOnce,
ExportEverythingEverywhereAllAtOnceStatus,
} from '../utils/exportData';
import {css} from '@emotion/css'; import {css} from '@emotion/css';
export const Navbar = withTrackingScope(function Navbar({ export const Navbar = withTrackingScope(function Navbar({
@@ -114,6 +127,7 @@ export const Navbar = withTrackingScope(function Navbar({
setToplevelSelection={setToplevelSelection} setToplevelSelection={setToplevelSelection}
/> />
<SetupDoctorButton /> <SetupDoctorButton />
<ExportEverythingEverywhereAllAtOnceButton />
<NavbarButton label="Help" icon={QuestionCircleOutlined} /> <NavbarButton label="Help" icon={QuestionCircleOutlined} />
<NavbarButton label="More" icon={EllipsisOutlined} /> <NavbarButton label="More" icon={EllipsisOutlined} />
<RightSidebarToggleButton /> <RightSidebarToggleButton />
@@ -123,6 +137,140 @@ export const Navbar = withTrackingScope(function Navbar({
); );
}); });
function ExportEverythingEverywhereAllAtOnceButton() {
const store = useStore();
const [status, setStatus] = useState<
ExportEverythingEverywhereAllAtOnceStatus | undefined
>();
const exportEverythingEverywhereAllAtOnceTracked = useTrackedCallback(
'Debug data export',
() =>
exportEverythingEverywhereAllAtOnce(
store,
(...args) => setStatus(args),
config.isFBBuild,
),
[store, setStatus],
);
return (
<>
<ExportEverythingEverywhereAllAtOnceStatusModal
status={status}
setStatus={setStatus}
/>
<NUX title="Press this button if you have issues with Flipper. It will collect Flipper debug data that you can send to the Flipper team to get help.">
<NavbarButton
icon={BugOutlined}
label="Rage"
onClick={() => {
exportEverythingEverywhereAllAtOnceTracked();
}}
/>
</NUX>
</>
);
}
function ExportEverythingEverywhereAllAtOnceStatusModal({
status,
setStatus,
}: {
status: ExportEverythingEverywhereAllAtOnceStatus | undefined;
setStatus: (
newStatus: ExportEverythingEverywhereAllAtOnceStatus | undefined,
) => void;
}) {
const [statusMessage, setStatusMessage] = useState<JSX.Element | undefined>();
useEffect(() => {
switch (status?.[0]) {
case 'logs': {
setStatusMessage(<p>Exporting Flipper logs...</p>);
return;
}
case 'files': {
let sheepCount = 0;
const setFileExportMessage = () => {
setStatusMessage(
<>
<p>Exporting Flipper debug files from all devices...</p>
<p>It could take a long time!</p>
<p>Let's count sheep while we wait: {sheepCount++}.</p>
<p>We'll skip it automatically if it exceeds 3 minutes.</p>
</>,
);
};
setFileExportMessage();
const interval = setInterval(setFileExportMessage, 3000);
return () => clearInterval(interval);
}
case 'state': {
let dinosaursCount = 0;
const setStateExportMessage = () => {
setStatusMessage(
<>
<p>Exporting Flipper state...</p>
<p>It also could take a long time!</p>
<p>This time we could count dinosaurs: {dinosaursCount++}.</p>
<p>We'll skip it automatically if it exceeds 2 minutes.</p>
</>,
);
};
setStateExportMessage();
const interval = setInterval(setStateExportMessage, 2000);
return () => clearInterval(interval);
}
case 'archive': {
setStatusMessage(<p>Creating an archive...</p>);
return;
}
case 'upload': {
setStatusMessage(<p>Uploading the archive...</p>);
return;
}
case 'support': {
setStatusMessage(<p>Creating a support request...</p>);
return;
}
case 'error': {
setStatusMessage(
<>
<p>Oops! Something went wrong.</p>
<p>{status[1]}</p>
</>,
);
return;
}
case 'done': {
setStatusMessage(<p>Done!</p>);
return;
}
case 'cancelled': {
setStatusMessage(<p>Cancelled! Why? 😱🤯👏</p>);
return;
}
}
}, [status]);
return (
<Modal
visible={!!status}
centered
onCancel={() => {
setStatus(undefined);
}}
title="Exporting everything everywhere all at once"
footer={null}>
{statusMessage}
</Modal>
);
}
function ConnectionTroubleshootButton({ function ConnectionTroubleshootButton({
toplevelSelection, toplevelSelection,
setToplevelSelection, setToplevelSelection,
@@ -130,7 +278,7 @@ function ConnectionTroubleshootButton({
return ( return (
<NavbarButton <NavbarButton
icon={ApiOutlined} icon={ApiOutlined}
label="Connection Troubleshoot" label="Troubleshoot"
toggled={toplevelSelection === 'connectivity'} toggled={toplevelSelection === 'connectivity'}
onClick={() => { onClick={() => {
setToplevelSelection('connectivity'); setToplevelSelection('connectivity');