Share sheet for the file export
Summary: This diff shows an export sheet when one exports the Flipper data in a file. It also shows if any error happens. Look at the video in test case. Reviewed By: danielbuechele Differential Revision: D14624194 fbshipit-source-id: dea0179a83e626e49593e5dde1d5ff128048db02
This commit is contained in:
committed by
Facebook Github Bot
parent
2dacea8541
commit
45999a5292
12
src/App.js
12
src/App.js
@@ -15,6 +15,7 @@ import BugReporterDialog from './chrome/BugReporterDialog.js';
|
||||
import ErrorBar from './chrome/ErrorBar.js';
|
||||
import ShareSheet from './chrome/ShareSheet.js';
|
||||
import SignInSheet from './chrome/SignInSheet.js';
|
||||
import ShareSheetExportFile from './chrome/ShareSheetExportFile.js';
|
||||
import PluginContainer from './PluginContainer.js';
|
||||
import Sheet from './chrome/Sheet.js';
|
||||
import {ipcRenderer, remote} from 'electron';
|
||||
@@ -24,6 +25,7 @@ import {
|
||||
ACTIVE_SHEET_PLUGIN_DEBUGGER,
|
||||
ACTIVE_SHEET_SHARE_DATA,
|
||||
ACTIVE_SHEET_SIGN_IN,
|
||||
ACTIVE_SHEET_SHARE_DATA_IN_FILE,
|
||||
} from './reducers/application.js';
|
||||
|
||||
import type {Logger} from './fb-interfaces/Logger.js';
|
||||
@@ -44,6 +46,7 @@ type Props = {|
|
||||
selectedDevice: ?BaseDevice,
|
||||
error: ?string,
|
||||
activeSheet: ActiveSheet,
|
||||
exportFile: ?string,
|
||||
|};
|
||||
|
||||
export class App extends React.Component<Props> {
|
||||
@@ -76,6 +79,12 @@ export class App extends React.Component<Props> {
|
||||
return <ShareSheet onHide={onHide} />;
|
||||
} else if (this.props.activeSheet === ACTIVE_SHEET_SIGN_IN) {
|
||||
return <SignInSheet onHide={onHide} />;
|
||||
} else if (this.props.activeSheet === ACTIVE_SHEET_SHARE_DATA_IN_FILE) {
|
||||
const {exportFile} = this.props;
|
||||
if (!exportFile) {
|
||||
throw new Error('Tried to export data without passing the file path');
|
||||
}
|
||||
return <ShareSheetExportFile onHide={onHide} file={exportFile} />;
|
||||
} else {
|
||||
// contents are added via React.Portal
|
||||
return null;
|
||||
@@ -103,12 +112,13 @@ export class App extends React.Component<Props> {
|
||||
|
||||
export default connect<Props, OwnProps, _, _, _, _>(
|
||||
({
|
||||
application: {leftSidebarVisible, activeSheet},
|
||||
application: {leftSidebarVisible, activeSheet, exportFile},
|
||||
connections: {selectedDevice, error},
|
||||
}) => ({
|
||||
leftSidebarVisible,
|
||||
selectedDevice,
|
||||
activeSheet,
|
||||
exportFile,
|
||||
error,
|
||||
}),
|
||||
)(App);
|
||||
|
||||
@@ -6,22 +6,20 @@
|
||||
*/
|
||||
|
||||
import type {FlipperPlugin, FlipperDevicePlugin} from './plugin.js';
|
||||
import {showOpenDialog} from './utils/exportData.js';
|
||||
import {
|
||||
exportStoreToFile,
|
||||
showOpenDialog,
|
||||
EXPORT_FLIPPER_TRACE_EVENT,
|
||||
} from './utils/exportData.js';
|
||||
import {setActiveSheet, ACTIVE_SHEET_SHARE_DATA} from './reducers/application';
|
||||
setExportDataToFileActiveSheet,
|
||||
setActiveSheet,
|
||||
ACTIVE_SHEET_SHARE_DATA,
|
||||
} from './reducers/application';
|
||||
import type {Store} from './reducers/';
|
||||
import electron from 'electron';
|
||||
import {ENABLE_SHAREABLE_LINK} from 'flipper';
|
||||
import {remote} from 'electron';
|
||||
const {dialog} = remote;
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import {reportPlatformFailures} from './utils/metrics';
|
||||
export type DefaultKeyboardAction = 'clear' | 'goToBottom' | 'createPaste';
|
||||
export type TopLevelMenu = 'Edit' | 'View' | 'Window' | 'Help';
|
||||
const {dialog} = electron.remote;
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
type MenuItem = {|
|
||||
label?: string,
|
||||
@@ -199,11 +197,11 @@ function getTemplate(
|
||||
title: 'FlipperExport',
|
||||
defaultPath: path.join(os.homedir(), 'FlipperExport.flipper'),
|
||||
},
|
||||
file => {
|
||||
reportPlatformFailures(
|
||||
exportStoreToFile(file, store),
|
||||
`${EXPORT_FLIPPER_TRACE_EVENT}:UI`,
|
||||
);
|
||||
async file => {
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
store.dispatch(setExportDataToFileActiveSheet(file));
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -29,6 +29,7 @@ test('Empty app state matches snapshot', () => {
|
||||
selectedDevice={null}
|
||||
error={null}
|
||||
activeSheet={null}
|
||||
exportFile={null}
|
||||
/>
|
||||
</Provider>,
|
||||
);
|
||||
|
||||
143
src/chrome/ShareSheetExportFile.js
Normal file
143
src/chrome/ShareSheetExportFile.js
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* Copyright 2018-present Facebook.
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
* @format
|
||||
*/
|
||||
import {
|
||||
FlexColumn,
|
||||
Button,
|
||||
styled,
|
||||
colors,
|
||||
Text,
|
||||
LoadingIndicator,
|
||||
Component,
|
||||
FlexRow,
|
||||
Spacer,
|
||||
} from 'flipper';
|
||||
import {reportPlatformFailures} from '../utils/metrics';
|
||||
import {
|
||||
exportStoreToFile,
|
||||
EXPORT_FLIPPER_TRACE_EVENT,
|
||||
} from '../utils/exportData.js';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const Container = styled(FlexColumn)({
|
||||
padding: 20,
|
||||
width: 500,
|
||||
});
|
||||
|
||||
const Center = styled(FlexColumn)({
|
||||
alignItems: 'center',
|
||||
paddingTop: 50,
|
||||
paddingBottom: 50,
|
||||
});
|
||||
|
||||
const Uploading = styled(Text)({
|
||||
marginTop: 15,
|
||||
});
|
||||
|
||||
const ErrorMessage = styled(Text)({
|
||||
display: 'block',
|
||||
marginTop: 6,
|
||||
wordBreak: 'break-all',
|
||||
whiteSpace: 'pre-line',
|
||||
lineHeight: 1.35,
|
||||
});
|
||||
|
||||
const Title = styled(Text)({
|
||||
marginBottom: 6,
|
||||
});
|
||||
|
||||
const InfoText = styled(Text)({
|
||||
lineHeight: 1.35,
|
||||
marginBottom: 15,
|
||||
});
|
||||
|
||||
type Props = {
|
||||
onHide: () => mixed,
|
||||
file: string,
|
||||
};
|
||||
type State = {
|
||||
result: ?{
|
||||
success: boolean,
|
||||
error: ?Error,
|
||||
},
|
||||
};
|
||||
|
||||
export default class ShareSheetExportFile extends Component<Props, State> {
|
||||
static contextTypes = {
|
||||
store: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
result: null,
|
||||
};
|
||||
|
||||
async componentDidMount() {
|
||||
try {
|
||||
await reportPlatformFailures(
|
||||
exportStoreToFile(this.props.file, this.context.store),
|
||||
`${EXPORT_FLIPPER_TRACE_EVENT}:UI`,
|
||||
);
|
||||
this.setState({result: {success: true, error: null}});
|
||||
} catch (err) {
|
||||
this.setState({result: {success: false, error: err}});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {result} = this.state;
|
||||
if (result) {
|
||||
const {success, error} = result;
|
||||
if (success) {
|
||||
return (
|
||||
<Container>
|
||||
<FlexColumn>
|
||||
<Title bold>Data Exported Successfully</Title>
|
||||
<InfoText>
|
||||
When sharing your Flipper data, consider that the captured data
|
||||
might contain sensitive information like access tokens used in
|
||||
network requests.
|
||||
</InfoText>
|
||||
</FlexColumn>
|
||||
<FlexRow>
|
||||
<Spacer />
|
||||
<Button compact padded onClick={this.props.onHide}>
|
||||
Close
|
||||
</Button>
|
||||
</FlexRow>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
if (error) {
|
||||
return (
|
||||
<Container>
|
||||
<Title bold>Error</Title>
|
||||
<ErrorMessage code>
|
||||
{error?.message || 'File could not be saved.'}
|
||||
</ErrorMessage>
|
||||
<FlexRow>
|
||||
<Spacer />
|
||||
<Button compact padded onClick={this.props.onHide}>
|
||||
Close
|
||||
</Button>
|
||||
</FlexRow>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
return (
|
||||
<Container>
|
||||
<Center>
|
||||
<LoadingIndicator size={30} />
|
||||
<Uploading bold color={colors.macOSTitleBarIcon}>
|
||||
Exporting Flipper trace...
|
||||
</Uploading>
|
||||
</Center>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@ export const ACTIVE_SHEET_PLUGIN_DEBUGGER: 'PLUGIN_DEBUGGER' =
|
||||
'PLUGIN_DEBUGGER';
|
||||
export const ACTIVE_SHEET_SHARE_DATA: 'SHARE_DATA' = 'SHARE_DATA';
|
||||
export const ACTIVE_SHEET_SIGN_IN: 'SIGN_IN' = 'SIGN_IN';
|
||||
export const ACTIVE_SHEET_SHARE_DATA_IN_FILE: 'SHARE_DATA_IN_FILE' =
|
||||
'SHARE_DATA_IN_FILE';
|
||||
|
||||
export type ActiveSheet =
|
||||
| typeof ACTIVE_SHEET_PLUGIN_SHEET
|
||||
@@ -21,6 +23,7 @@ export type ActiveSheet =
|
||||
| typeof ACTIVE_SHEET_PLUGIN_DEBUGGER
|
||||
| typeof ACTIVE_SHEET_SHARE_DATA
|
||||
| typeof ACTIVE_SHEET_SIGN_IN
|
||||
| typeof ACTIVE_SHEET_SHARE_DATA_IN_FILE
|
||||
| null;
|
||||
|
||||
export type State = {
|
||||
@@ -29,6 +32,7 @@ export type State = {
|
||||
rightSidebarAvailable: boolean,
|
||||
windowIsFocused: boolean,
|
||||
activeSheet: ActiveSheet,
|
||||
exportFile: ?string,
|
||||
sessionId: ?string,
|
||||
serverPorts: {
|
||||
insecure: number,
|
||||
@@ -53,6 +57,10 @@ export type Action =
|
||||
type: 'SET_ACTIVE_SHEET',
|
||||
payload: ActiveSheet,
|
||||
}
|
||||
| {
|
||||
type: typeof ACTIVE_SHEET_SHARE_DATA_IN_FILE,
|
||||
payload: {file: string},
|
||||
}
|
||||
| {
|
||||
type: 'SET_SERVER_PORTS',
|
||||
payload: {
|
||||
@@ -67,6 +75,7 @@ const initialState: () => State = () => ({
|
||||
rightSidebarAvailable: false,
|
||||
windowIsFocused: remote.getCurrentWindow().isFocused(),
|
||||
activeSheet: null,
|
||||
exportFile: null,
|
||||
sessionId: uuidv1(),
|
||||
serverPorts: {
|
||||
insecure: 8089,
|
||||
@@ -103,6 +112,12 @@ export default function reducer(state: State, action: Action): State {
|
||||
...state,
|
||||
activeSheet: action.payload,
|
||||
};
|
||||
} else if (action.type === ACTIVE_SHEET_SHARE_DATA_IN_FILE) {
|
||||
return {
|
||||
...state,
|
||||
activeSheet: ACTIVE_SHEET_SHARE_DATA_IN_FILE,
|
||||
exportFile: action.payload.file,
|
||||
};
|
||||
}
|
||||
if (action.type === 'SET_SERVER_PORTS') {
|
||||
return {
|
||||
@@ -122,6 +137,11 @@ export const toggleAction = (
|
||||
payload,
|
||||
});
|
||||
|
||||
export const setExportDataToFileActiveSheet = (file: string): Action => ({
|
||||
type: ACTIVE_SHEET_SHARE_DATA_IN_FILE,
|
||||
payload: {file},
|
||||
});
|
||||
|
||||
export const setActiveSheet = (payload: ActiveSheet): Action => ({
|
||||
type: 'SET_ACTIVE_SHEET',
|
||||
payload,
|
||||
|
||||
Reference in New Issue
Block a user