Summary: Previously, plugins could relatively safely use `client.call` at any moment in time to fetch some information from / to the client. Except for some raise conditions there was generally speaking a connection available. With this stack it becomes possible to interact with plugins even after an app (unexpectedly) disconnected, which makes Flipper a lot more versatile, especially when it comes to inspect crashes post mortem. (For more explanation see the second diff in this stack) However, this means that it is no longer safe to assume there is always a connection available. For that reason `client.isConnected` has been introduced to safeguard against that. This diff introduces guards on all user interactions that are not super explicitly triggered by the user to avoid a lot of errors being generated. This is mostly in `init()` blocks and implicit user events like selecting or hovering rows. Explicit user interactions like pressing buttons are not guarded by this diff, as ideally failure to communicate with the client should be communicated back to the user more explicitly rather than failing silently. The next diff will introduce a fallback mechanism where a popup is shown in case those calls aren't guarded. Fixed a few key warnings while at it. Reviewed By: nikoant Differential Revision: D26275604 fbshipit-source-id: 5630066cdd9541e448a6dd1f8a21861b5d751ced
119 lines
2.8 KiB
TypeScript
119 lines
2.8 KiB
TypeScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
import {Button, Input, FlipperPlugin, FlexColumn, styled, Text} from 'flipper';
|
|
import React from 'react';
|
|
|
|
type DisplayMessageResponse = {
|
|
greeting: string;
|
|
};
|
|
|
|
type Message = {
|
|
id: number;
|
|
msg: string | null | undefined;
|
|
};
|
|
|
|
type State = {
|
|
prompt: string;
|
|
message: string;
|
|
};
|
|
|
|
type PersistedState = {
|
|
currentNotificationIds: Array<number>;
|
|
receivedMessage: string | null;
|
|
};
|
|
|
|
const Container = styled(FlexColumn)({
|
|
alignItems: 'center',
|
|
justifyContent: 'space-around',
|
|
padding: 20,
|
|
});
|
|
|
|
export default class Example extends FlipperPlugin<State, any, PersistedState> {
|
|
static defaultPersistedState = {
|
|
currentNotificationIds: [],
|
|
receivedMessage: null,
|
|
};
|
|
|
|
state = {
|
|
prompt: 'Type a message below to see it displayed on the mobile app',
|
|
message: '',
|
|
};
|
|
|
|
/*
|
|
* Reducer to process incoming "send" messages from the mobile counterpart.
|
|
*/
|
|
static persistedStateReducer(
|
|
persistedState: PersistedState,
|
|
method: string,
|
|
payload: Message,
|
|
) {
|
|
if (method === 'triggerNotification') {
|
|
return Object.assign({}, persistedState, {
|
|
currentNotificationIds: persistedState.currentNotificationIds.concat([
|
|
payload.id,
|
|
]),
|
|
});
|
|
}
|
|
if (method === 'displayMessage') {
|
|
return Object.assign({}, persistedState, {
|
|
receivedMessage: payload.msg,
|
|
});
|
|
}
|
|
return persistedState;
|
|
}
|
|
|
|
/*
|
|
* Callback to provide the currently active notifications.
|
|
*/
|
|
static getActiveNotifications(persistedState: PersistedState) {
|
|
return persistedState.currentNotificationIds.map((x: number) => {
|
|
return {
|
|
id: 'test-notification:' + x,
|
|
message: 'Example Notification',
|
|
severity: 'warning' as 'warning',
|
|
title: 'Notification: ' + x,
|
|
};
|
|
});
|
|
}
|
|
|
|
/*
|
|
* Call a method of the mobile counterpart, to display a message.
|
|
*/
|
|
sendMessage() {
|
|
if (this.client.isConnected) {
|
|
this.client
|
|
.call('displayMessage', {message: this.state.message || 'Weeeee!'})
|
|
.then((_params: DisplayMessageResponse) => {
|
|
this.setState({
|
|
prompt: 'Nice',
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<Container>
|
|
<Text>{this.state.prompt}</Text>
|
|
<Input
|
|
placeholder="Message"
|
|
onChange={(event) => {
|
|
this.setState({message: event.target.value});
|
|
}}
|
|
/>
|
|
<Button onClick={this.sendMessage.bind(this)}>Send</Button>
|
|
{this.props.persistedState.receivedMessage && (
|
|
<Text> {this.props.persistedState.receivedMessage} </Text>
|
|
)}
|
|
</Container>
|
|
);
|
|
}
|
|
}
|