diff --git a/src/PluginContainer.js b/src/PluginContainer.js index e008b0ac7..96e533653 100644 --- a/src/PluginContainer.js +++ b/src/PluginContainer.js @@ -11,6 +11,7 @@ import type BaseDevice from './devices/BaseDevice.js'; import type {Props as PluginProps} from './plugin'; import {FlipperDevicePlugin} from './plugin.js'; +import type {Notification} from './plugin.js'; import { ErrorBoundary, Component, @@ -52,6 +53,10 @@ type Props = { pluginKey: string, state: Object, }) => void, + setActiveNotifications: ({ + pluginId: string, + notifications: Array, + }) => void, deepLinkPayload: ?string, }; @@ -125,7 +130,7 @@ class PluginContainer extends Component { }; render() { - const {pluginStates, setPluginState} = this.props; + const {pluginStates, setPluginState, setActiveNotifications} = this.props; const {activePlugin, pluginKey, target} = this.state; if (!activePlugin || !target) { @@ -143,6 +148,11 @@ class PluginContainer extends Component { // same time. setTimeout(() => setPluginState({pluginKey, state}), 0); }, + setActiveNotifications: (notifications: Array) => + setActiveNotifications({ + pluginId: pluginKey, + notifications: notifications, + }), target, deepLinkPayload: this.props.deepLinkPayload, ref: this.refChanged, diff --git a/src/plugin.js b/src/plugin.js index fb485ff89..4cbbf34b9 100644 --- a/src/plugin.js +++ b/src/plugin.js @@ -24,10 +24,21 @@ export type PluginClient = {| type PluginTarget = BaseDevice | Client; +export type Notification = {| + id: string, + title: string, + message: string, + severity: 'warning' | 'error', + timestamp?: number, + category?: string, + action?: string, +|}; + export type Props = { logger: Logger, persistedState: T, setPersistedState: (state: $Shape) => void, + setActiveNotifications: (Array) => void, target: PluginTarget, deepLinkPayload: ?string, }; @@ -64,6 +75,9 @@ export class FlipperBasePlugin< // methods to be overriden by plugins init(): void {} teardown(): void {} + computeNotifications(props: Props<*>, state: State): Array { + return []; + } // methods to be overridden by subclasses _init(): void {} _teardown(): void {} @@ -83,6 +97,10 @@ export class FlipperBasePlugin< throw new TypeError(`Reducer ${actionData.type} isn't a function`); } } + + componentDidUpdate(props: Props<*>, state: State): void { + props.setActiveNotifications(this.computeNotifications(props, state)); + } } export class FlipperDevicePlugin extends FlipperBasePlugin< diff --git a/src/plugins/network/index.js b/src/plugins/network/index.js index 10cf23139..4bb6277f2 100644 --- a/src/plugins/network/index.js +++ b/src/plugins/network/index.js @@ -22,6 +22,7 @@ import { } from 'flipper'; import RequestDetails from './RequestDetails.js'; import {URL} from 'url'; +import type {Notification} from '../../plugin'; type RequestId = string; @@ -159,20 +160,21 @@ export default class extends FlipperPlugin { }; computeNotifications(props: *, state: State) { - const notifications = {}; + const notifications: Array = []; const persistedState = props.persistedState; for (const response in persistedState.responses) { const status = persistedState.responses[response].status; - if (status >= 400) { + const id = persistedState.requests[response]?.id; + if (status >= 400 && id != null) { const url = persistedState.requests[response]?.url; - const startTime = persistedState.requests[response]?.timestamp; const endTime = persistedState.responses[response].timestamp; - notifications[`${url}-${startTime}`] = { + notifications.push({ + id, timestamp: endTime, title: 'Failed network request', message: `Response for ${url} failed with status code ${status}`, severity: 'error', - }; + }); } } return notifications; diff --git a/src/reducers/notifications.js b/src/reducers/notifications.js index 3f9b9d3e4..8abdd0ad2 100644 --- a/src/reducers/notifications.js +++ b/src/reducers/notifications.js @@ -4,17 +4,7 @@ * LICENSE file in the root directory of this source tree. * @format */ -import type {Node} from 'react'; - -export type Notification = {| - id: string, - title: string, - message: Node, - severity: 'warning' | 'error', - timestamp?: number, - category?: string, - action?: string, -|}; +import type {Notification} from '../plugin'; export type PluginNotification = {| notification: Notification,