Process and render messages when a plugin is opened

Summary: This introduces the necessary UI changes, to kick off and render event progressing process where needed

Reviewed By: jknoxville

Differential Revision: D19175450

fbshipit-source-id: 61e3e8f59eeebf97eedbe715fa7db320286543e2
This commit is contained in:
Michel Weststrate
2020-01-02 07:12:06 -08:00
committed by Facebook Github Bot
parent d2a2e2ab75
commit 8c8f360572
6 changed files with 212 additions and 70 deletions

View File

@@ -23,14 +23,21 @@ import {
colors,
styled,
ArchivedDevice,
Glyph,
Label,
VBox,
View,
} from 'flipper';
import {StaticView, setStaticView} from './reducers/connections';
import React, {PureComponent} from 'react';
import {connect} from 'react-redux';
import {connect, ReactReduxContext} from 'react-redux';
import {setPluginState} from './reducers/pluginStates';
import {selectPlugin} from './reducers/connections';
import {State as Store} from './reducers/index';
import {activateMenuItems} from './MenuBar';
import {Message} from './reducers/pluginMessageQueue';
import {Idler} from './utils/Idler';
import {processMessageQueue} from './utils/messageQueue';
const Container = styled(FlexColumn)({
width: 0,
@@ -45,6 +52,36 @@ const SidebarContainer = styled(FlexRow)({
overflow: 'scroll',
});
const Waiting = styled(FlexColumn)({
width: '100%',
height: '100%',
flexGrow: 1,
background: colors.light02,
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
});
function ProgressBar({progress}: {progress: number}) {
return (
<ProgressBarContainer>
<ProgressBarBar progress={progress} />
</ProgressBarContainer>
);
}
const ProgressBarContainer = styled.div({
border: `1px solid ${colors.cyan}`,
borderRadius: 4,
width: 300,
});
const ProgressBarBar = styled.div<{progress: number}>(({progress}) => ({
background: colors.cyan,
width: `${Math.min(100, Math.round(progress * 100))}%`,
height: 8,
}));
type OwnProps = {
logger: Logger;
};
@@ -57,6 +94,7 @@ type StateFromProps = {
deepLinkPayload: string | null;
selectedApp: string | null;
isArchivedDevice: boolean;
pendingMessages: Message[] | undefined;
};
type DispatchFromProps = {
@@ -71,7 +109,13 @@ type DispatchFromProps = {
type Props = StateFromProps & DispatchFromProps & OwnProps;
class PluginContainer extends PureComponent<Props> {
type State = {
progress: {current: number; total: number};
};
class PluginContainer extends PureComponent<Props, State> {
static contextType = ReactReduxContext;
plugin:
| FlipperPlugin<any, any, any>
| FlipperDevicePlugin<any, any, any>
@@ -97,14 +141,102 @@ class PluginContainer extends PureComponent<Props> {
}
};
idler?: Idler;
pluginBeingProcessed: string = '';
state = {progress: {current: 0, total: 0}};
componentWillUnmount() {
if (this.plugin) {
this.plugin._teardown();
this.plugin = null;
}
this.cancelCurrentQueue();
}
componentDidMount() {
this.processMessageQueue();
}
componentDidUpdate() {
this.processMessageQueue();
}
processMessageQueue() {
const {pluginKey, pendingMessages, activePlugin} = this.props;
if (pluginKey !== this.pluginBeingProcessed) {
this.pluginBeingProcessed = pluginKey ?? '';
this.cancelCurrentQueue();
this.setState({progress: {current: 0, total: 0}});
if (
activePlugin &&
activePlugin.persistedStateReducer &&
pluginKey &&
pendingMessages?.length
) {
// this.setState({progress: {current: 0, total: 0}});
this.idler = new Idler();
processMessageQueue(
activePlugin,
pluginKey,
this.context.store,
progress => {
this.setState({progress});
},
this.idler,
);
}
}
}
cancelCurrentQueue() {
if (this.idler && !this.idler.isCancelled()) {
this.idler.cancel();
}
}
render() {
const {activePlugin, pluginKey, target, pendingMessages} = this.props;
if (!activePlugin || !target || !pluginKey) {
console.warn(`No selected plugin. Rendering empty!`);
return null;
}
if (!pendingMessages || pendingMessages.length === 0) {
return this.renderPlugin();
} else {
return this.renderPluginLoader();
}
}
renderPluginLoader() {
return (
<View grow>
<Waiting>
<VBox>
<Glyph
name="dashboard"
variant="outline"
size={24}
color={colors.light30}
/>
</VBox>
<VBox>
<Label>
Processing {this.state.progress.total} events for{' '}
{this.props.activePlugin?.id ?? 'plugin'}
</Label>
</VBox>
<VBox>
<ProgressBar
progress={this.state.progress.current / this.state.progress.total}
/>
</VBox>
</Waiting>
</View>
);
}
renderPlugin() {
const {
pluginState,
setPluginState,
@@ -186,6 +318,7 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
},
pluginStates,
plugins: {devicePlugins, clientPlugins},
pluginMessageQueue,
}) => {
let pluginKey = null;
let target = null;
@@ -212,6 +345,10 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
? false
: selectedDevice instanceof ArchivedDevice;
const pendingMessages = pluginKey
? pluginMessageQueue[pluginKey]
: undefined;
const s: StateFromProps = {
pluginState: pluginStates[pluginKey as string],
activePlugin: activePlugin,
@@ -220,6 +357,7 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
pluginKey,
isArchivedDevice,
selectedApp: selectedApp || null,
pendingMessages,
};
return s;
},