Show a message if a background plugin is not starred

Summary:
Since background plugins don't receive data anymore when not starred, we should hint the user about this.

For this diff, I reused the existing statusbar. Although this solution is quite ugly, I think it is better than introducing yet another notification / warning mechanism. Probably we should revisit the layout of this status bar in the future.

Reviewed By: jknoxville

Differential Revision: D19251588

fbshipit-source-id: 1dfd07be383d4ba318f344ebff4b08ed36194c58
This commit is contained in:
Michel Weststrate
2020-01-02 07:12:06 -08:00
committed by Facebook Github Bot
parent 04fcaddded
commit 9acf23596e
5 changed files with 86 additions and 39 deletions

View File

@@ -33,7 +33,7 @@ import React, {PureComponent} from 'react';
import {connect, ReactReduxContext} from 'react-redux';
import {setPluginState} from './reducers/pluginStates';
import {selectPlugin} from './reducers/connections';
import {State as Store} from './reducers/index';
import {State as Store, MiddlewareAPI} from './reducers/index';
import {activateMenuItems} from './MenuBar';
import {Message} from './reducers/pluginMessageQueue';
import {Idler} from './utils/Idler';
@@ -146,6 +146,10 @@ class PluginContainer extends PureComponent<Props, State> {
state = {progress: {current: 0, total: 0}};
get store(): MiddlewareAPI {
return this.context.store;
}
componentWillUnmount() {
if (this.plugin) {
this.plugin._teardown();
@@ -179,7 +183,7 @@ class PluginContainer extends PureComponent<Props, State> {
processMessageQueue(
activePlugin,
pluginKey,
this.context.store,
this.store,
progress => {
this.setState({progress});
},

View File

@@ -8,11 +8,12 @@
*/
import {colors} from '../ui/components/colors';
import {styled} from '../ui';
import {styled, Glyph} from '../ui';
import {connect} from 'react-redux';
import {State} from '../reducers';
import React, {ReactElement} from 'react';
import Text from '../ui/components/Text';
import {pluginIsStarred} from '../reducers/connections';
const StatusBarContainer = styled(Text)({
backgroundColor: colors.macOSTitleBarBackgroundBlur,
@@ -21,17 +22,18 @@ const StatusBarContainer = styled(Text)({
padding: '0 10px',
textOverflow: 'ellipsis',
overflow: 'hidden',
textAlign: 'center',
});
type Props = {
statusMessage: string | null;
statusMessage: React.ReactNode | string | null;
};
export function statusBarView(props: Props): ReactElement | null {
const {statusMessage} = props;
if (statusMessage) {
return (
<StatusBarContainer italic={true} whiteSpace="nowrap">
<StatusBarContainer whiteSpace="nowrap">
{statusMessage}
</StatusBarContainer>
);
@@ -40,13 +42,45 @@ export function statusBarView(props: Props): ReactElement | null {
}
}
export default connect<Props, void, {}, State>(
({application: {statusMessages}}) => {
if (statusMessages.length > 0) {
return {statusMessage: statusMessages[statusMessages.length - 1]};
}
export default connect<Props, void, {}, State>((state: State) => {
const {
application: {statusMessages},
} = state;
if (statusMessages.length > 0) {
return {statusMessage: statusMessages[statusMessages.length - 1]};
} else if (isPreviewingBackgroundPlugin(state)) {
return {
statusMessage: null,
statusMessage: (
<>
<Glyph
name="caution-triangle"
color={colors.light20}
size={12}
variant="filled"
style={{marginRight: 8}}
/>
The current plugin would like to send messages while it is in the
background. However, since this plugin is not starred, these messages
will be dropped. Star this plugin to unlock its full capabilities.
</>
),
};
},
)(statusBarView);
}
return {
statusMessage: null,
};
})(statusBarView);
function isPreviewingBackgroundPlugin(state: State): boolean {
const {
connections: {selectedApp, selectedPlugin},
} = state;
if (!selectedPlugin || !selectedApp) {
return false;
}
const activePlugin = state.plugins.clientPlugins.get(selectedPlugin);
if (!activePlugin || !activePlugin.persistedStateReducer) {
return false;
}
return !pluginIsStarred(state.connections, selectedPlugin);
}

View File

@@ -7,6 +7,8 @@
* @format
*/
import {produce} from 'immer';
import BaseDevice from '../devices/BaseDevice';
import MacDevice from '../devices/MacDevice';
import Client from '../Client';
@@ -23,7 +25,8 @@ import NotificationScreen from '../chrome/NotificationScreen';
import SupportRequestForm from '../fb-stubs/SupportRequestFormManager';
import SupportRequestFormV2 from '../fb-stubs/SupportRequestFormV2';
import SupportRequestDetails from '../fb-stubs/SupportRequestDetails';
import {produce} from 'immer';
import {getPluginKey} from '../utils/pluginUtils';
import {deconstructClientId} from '../utils/clientUtils';
export type StaticView =
| null
@@ -581,3 +584,23 @@ function updateSelection(state: Readonly<State>): State {
return {...state, ...updates};
}
export function getSelectedPluginKey(state: State): string | undefined {
return state.selectedPlugin
? getPluginKey(
state.selectedApp,
state.selectedDevice,
state.selectedPlugin,
)
: undefined;
}
export function pluginIsStarred(state: State, pluginId: string): boolean {
const {selectedApp} = state;
if (!selectedApp) {
return false;
}
const appInfo = deconstructClientId(selectedApp);
const starred = state.userStarredPlugins[appInfo.app];
return starred && starred.indexOf(pluginId) > -1;
}

View File

@@ -17,8 +17,7 @@ import {
Message,
} from '../reducers/pluginMessageQueue';
import {Idler, BaseIdler} from './Idler';
import {getPluginKey} from './pluginUtils';
import {deconstructClientId} from './clientUtils';
import {pluginIsStarred, getSelectedPluginKey} from '../reducers/connections';
const MAX_BACKGROUND_TASK_TIME = 25;
@@ -138,14 +137,15 @@ export function processMessageLater(
},
message: {method: string; params?: any},
) {
const isSelected = pluginKey === getSelectedPluginKey(store.getState());
const isSelected =
pluginKey === getSelectedPluginKey(store.getState().connections);
switch (true) {
case isSelected && getPendingMessages(store, pluginKey).length === 0:
processMessageImmediately(store, pluginKey, plugin, message);
break;
case isSelected:
case plugin instanceof FlipperDevicePlugin:
case pluginIsStarred(store.getState(), plugin.id):
case pluginIsStarred(store.getState().connections, plugin.id):
store.dispatch(
queueMessage(
pluginKey,
@@ -158,26 +158,6 @@ export function processMessageLater(
}
}
function getSelectedPluginKey(state: State): string | undefined {
return state.connections.selectedPlugin
? getPluginKey(
state.connections.selectedApp,
state.connections.selectedDevice,
state.connections.selectedPlugin,
)
: undefined;
}
function pluginIsStarred(state: State, pluginId: string): boolean {
const {selectedApp} = state.connections;
if (!selectedApp) {
return false;
}
const appInfo = deconstructClientId(selectedApp);
const starred = state.connections.userStarredPlugins[appInfo.app];
return starred && starred.indexOf(pluginId) > -1;
}
export async function processMessageQueue(
plugin: {
defaultPersistedState: any;