Update existing subscriptions to use sideEffect
Summary: See previous two diffs, this applies the abstraction to our code base Reviewed By: passy Differential Revision: D20679687 fbshipit-source-id: 05e340dca3f832971783a844a78d1ffd553ff9d2
This commit is contained in:
committed by
Facebook GitHub Bot
parent
7a40d3f0a3
commit
8fa4b5ccb2
@@ -26,6 +26,7 @@ import invariant from 'invariant';
|
|||||||
import {flipperRecorderAddEvent} from './utils/pluginStateRecorder';
|
import {flipperRecorderAddEvent} from './utils/pluginStateRecorder';
|
||||||
import {getPluginKey} from './utils/pluginUtils';
|
import {getPluginKey} from './utils/pluginUtils';
|
||||||
import {processMessageLater} from './utils/messageQueue';
|
import {processMessageLater} from './utils/messageQueue';
|
||||||
|
import {sideEffect} from './utils/sideEffect';
|
||||||
|
|
||||||
type Plugins = Array<string>;
|
type Plugins = Array<string>;
|
||||||
|
|
||||||
@@ -207,21 +208,25 @@ export default class Client extends EventEmitter {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
reject(error);
|
reject(error);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
unsubscribe = this.store.subscribe(() => {
|
unsubscribe = sideEffect(
|
||||||
const newDeviceList = this.store.getState().connections.devices;
|
this.store,
|
||||||
if (newDeviceList === this.lastSeenDeviceList) {
|
{name: 'waitForDevice', throttleMs: 100},
|
||||||
return;
|
(state) => state.connections.devices,
|
||||||
}
|
(newDeviceList) => {
|
||||||
this.lastSeenDeviceList = this.store.getState().connections.devices;
|
if (newDeviceList === this.lastSeenDeviceList) {
|
||||||
const matchingDevice = newDeviceList.find(
|
return;
|
||||||
(device) => device.serial === this.query.device_id,
|
}
|
||||||
);
|
this.lastSeenDeviceList = newDeviceList;
|
||||||
if (matchingDevice) {
|
const matchingDevice = newDeviceList.find(
|
||||||
clearTimeout(timeout);
|
(device) => device.serial === this.query.device_id,
|
||||||
resolve(matchingDevice);
|
);
|
||||||
unsubscribe();
|
if (matchingDevice) {
|
||||||
}
|
clearTimeout(timeout);
|
||||||
});
|
resolve(matchingDevice);
|
||||||
|
unsubscribe();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
'client-setMatchingDevice',
|
'client-setMatchingDevice',
|
||||||
).then((device) => {
|
).then((device) => {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import GK from '../fb-stubs/GK';
|
|||||||
import {deconstructPluginKey} from '../utils/clientUtils';
|
import {deconstructPluginKey} from '../utils/clientUtils';
|
||||||
import NotificationScreen from '../chrome/NotificationScreen';
|
import NotificationScreen from '../chrome/NotificationScreen';
|
||||||
import {getPluginTitle} from '../utils/pluginUtils';
|
import {getPluginTitle} from '../utils/pluginUtils';
|
||||||
|
import {sideEffect} from '../utils/sideEffect';
|
||||||
|
|
||||||
type NotificationEvents = 'show' | 'click' | 'close' | 'reply' | 'action';
|
type NotificationEvents = 'show' | 'click' | 'close' | 'reply' | 'action';
|
||||||
const NOTIFICATION_THROTTLE = 5 * 1000; // in milliseconds
|
const NOTIFICATION_THROTTLE = 5 * 1000; // in milliseconds
|
||||||
@@ -84,118 +85,114 @@ export default (store: Store, logger: Logger) => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
store.subscribe(() => {
|
sideEffect(
|
||||||
const {notifications, pluginStates} = store.getState();
|
store,
|
||||||
|
{name: 'notifications', throttleMs: 500},
|
||||||
|
({notifications, pluginStates, plugins}) => ({
|
||||||
|
notifications,
|
||||||
|
pluginStates,
|
||||||
|
devicePlugins: plugins.devicePlugins,
|
||||||
|
clientPlugins: plugins.clientPlugins,
|
||||||
|
}),
|
||||||
|
({notifications, pluginStates, devicePlugins, clientPlugins}, store) => {
|
||||||
|
function getPlugin(name: string) {
|
||||||
|
return devicePlugins.get(name) ?? clientPlugins.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
const clientPlugins: Map<string, typeof FlipperPlugin> = store.getState()
|
Object.keys(pluginStates).forEach((key) => {
|
||||||
.plugins.clientPlugins;
|
if (knownPluginStates.get(key) !== pluginStates[key]) {
|
||||||
|
knownPluginStates.set(key, pluginStates[key]);
|
||||||
|
const plugin = deconstructPluginKey(key);
|
||||||
|
const pluginName = plugin.pluginName;
|
||||||
|
const client = plugin.client;
|
||||||
|
|
||||||
const devicePlugins: Map<
|
if (!pluginName) {
|
||||||
string,
|
return;
|
||||||
typeof FlipperDevicePlugin
|
}
|
||||||
> = store.getState().plugins.devicePlugins;
|
|
||||||
|
|
||||||
const pluginMap: Map<
|
const persistingPlugin:
|
||||||
string,
|
| undefined
|
||||||
typeof FlipperPlugin | typeof FlipperDevicePlugin
|
| typeof FlipperPlugin
|
||||||
> = new Map<string, typeof FlipperDevicePlugin | typeof FlipperPlugin>([
|
| typeof FlipperDevicePlugin = getPlugin(pluginName);
|
||||||
...clientPlugins,
|
if (persistingPlugin && persistingPlugin.getActiveNotifications) {
|
||||||
...devicePlugins,
|
try {
|
||||||
]);
|
const notifications = persistingPlugin.getActiveNotifications(
|
||||||
|
pluginStates[key],
|
||||||
Object.keys(pluginStates).forEach((key) => {
|
);
|
||||||
if (knownPluginStates.get(key) !== pluginStates[key]) {
|
store.dispatch(
|
||||||
knownPluginStates.set(key, pluginStates[key]);
|
setActiveNotifications({
|
||||||
const plugin = deconstructPluginKey(key);
|
notifications,
|
||||||
const pluginName = plugin.pluginName;
|
client,
|
||||||
const client = plugin.client;
|
pluginId: pluginName,
|
||||||
|
}),
|
||||||
if (!pluginName) {
|
);
|
||||||
return;
|
} catch (e) {
|
||||||
}
|
console.error(
|
||||||
|
'Failed to compute notifications for plugin ' + pluginName,
|
||||||
const persistingPlugin:
|
e,
|
||||||
| undefined
|
);
|
||||||
| typeof FlipperPlugin
|
}
|
||||||
| typeof FlipperDevicePlugin = pluginMap.get(pluginName);
|
|
||||||
if (persistingPlugin && persistingPlugin.getActiveNotifications) {
|
|
||||||
try {
|
|
||||||
const notifications = persistingPlugin.getActiveNotifications(
|
|
||||||
pluginStates[key],
|
|
||||||
);
|
|
||||||
store.dispatch(
|
|
||||||
setActiveNotifications({
|
|
||||||
notifications,
|
|
||||||
client,
|
|
||||||
pluginId: pluginName,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(
|
|
||||||
'Failed to compute notifications for plugin ' + pluginName,
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
activeNotifications,
|
activeNotifications,
|
||||||
blacklistedPlugins,
|
blacklistedPlugins,
|
||||||
blacklistedCategories,
|
blacklistedCategories,
|
||||||
} = notifications;
|
} = notifications;
|
||||||
|
|
||||||
activeNotifications.forEach((n: PluginNotification) => {
|
|
||||||
if (
|
|
||||||
!isHeadless() &&
|
|
||||||
store.getState().connections.selectedPlugin !== 'notifications' &&
|
|
||||||
!knownNotifications.has(n.notification.id) &&
|
|
||||||
blacklistedPlugins.indexOf(n.pluginId) === -1 &&
|
|
||||||
(!n.notification.category ||
|
|
||||||
blacklistedCategories.indexOf(n.notification.category) === -1)
|
|
||||||
) {
|
|
||||||
const prevNotificationTime: number =
|
|
||||||
lastNotificationTime.get(n.pluginId) || 0;
|
|
||||||
lastNotificationTime.set(n.pluginId, new Date().getTime());
|
|
||||||
knownNotifications.add(n.notification.id);
|
|
||||||
|
|
||||||
|
activeNotifications.forEach((n: PluginNotification) => {
|
||||||
if (
|
if (
|
||||||
new Date().getTime() - prevNotificationTime <
|
!isHeadless() &&
|
||||||
NOTIFICATION_THROTTLE
|
store.getState().connections.selectedPlugin !== 'notifications' &&
|
||||||
|
!knownNotifications.has(n.notification.id) &&
|
||||||
|
blacklistedPlugins.indexOf(n.pluginId) === -1 &&
|
||||||
|
(!n.notification.category ||
|
||||||
|
blacklistedCategories.indexOf(n.notification.category) === -1)
|
||||||
) {
|
) {
|
||||||
// Don't send a notification if the plugin has sent a notification
|
const prevNotificationTime: number =
|
||||||
// within the NOTIFICATION_THROTTLE.
|
lastNotificationTime.get(n.pluginId) || 0;
|
||||||
return;
|
lastNotificationTime.set(n.pluginId, new Date().getTime());
|
||||||
|
knownNotifications.add(n.notification.id);
|
||||||
|
|
||||||
|
if (
|
||||||
|
new Date().getTime() - prevNotificationTime <
|
||||||
|
NOTIFICATION_THROTTLE
|
||||||
|
) {
|
||||||
|
// Don't send a notification if the plugin has sent a notification
|
||||||
|
// within the NOTIFICATION_THROTTLE.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const plugin = getPlugin(n.pluginId);
|
||||||
|
ipcRenderer.send('sendNotification', {
|
||||||
|
payload: {
|
||||||
|
title: n.notification.title,
|
||||||
|
body: textContent(n.notification.message),
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: 'Show',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: 'Hide similar',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: `Hide all ${
|
||||||
|
plugin != null ? getPluginTitle(plugin) : ''
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
closeButtonText: 'Hide',
|
||||||
|
},
|
||||||
|
closeAfter: 10000,
|
||||||
|
pluginNotification: n,
|
||||||
|
});
|
||||||
|
logger.track('usage', 'native-notification', n.notification);
|
||||||
}
|
}
|
||||||
const plugin = pluginMap.get(n.pluginId);
|
});
|
||||||
ipcRenderer.send('sendNotification', {
|
},
|
||||||
payload: {
|
);
|
||||||
title: n.notification.title,
|
|
||||||
body: textContent(n.notification.message),
|
|
||||||
actions: [
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
text: 'Show',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
text: 'Hide similar',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
text: `Hide all ${
|
|
||||||
plugin != null ? getPluginTitle(plugin) : ''
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
closeButtonText: 'Hide',
|
|
||||||
},
|
|
||||||
closeAfter: 10000,
|
|
||||||
pluginNotification: n,
|
|
||||||
});
|
|
||||||
logger.track('usage', 'native-notification', n.notification);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import path from 'path';
|
|||||||
import {default as config} from '../utils/processConfig';
|
import {default as config} from '../utils/processConfig';
|
||||||
import isProduction from '../utils/isProduction';
|
import isProduction from '../utils/isProduction';
|
||||||
import {notNull} from '../utils/typeUtils';
|
import {notNull} from '../utils/typeUtils';
|
||||||
|
import {sideEffect} from '../utils/sideEffect';
|
||||||
|
|
||||||
export type PluginDefinition = {
|
export type PluginDefinition = {
|
||||||
id?: string;
|
id?: string;
|
||||||
@@ -63,20 +64,17 @@ export default (store: Store, _logger: Logger) => {
|
|||||||
store.dispatch(addFailedPlugins(failedPlugins));
|
store.dispatch(addFailedPlugins(failedPlugins));
|
||||||
store.dispatch(registerPlugins(initialPlugins));
|
store.dispatch(registerPlugins(initialPlugins));
|
||||||
|
|
||||||
let state: State | null = null;
|
sideEffect(
|
||||||
store.subscribe(() => {
|
store,
|
||||||
const newState = store.getState().plugins;
|
{name: 'setupMenuBar', throttleMs: 100},
|
||||||
if (state !== newState) {
|
(state) => state.plugins,
|
||||||
|
(plugins, store) => {
|
||||||
setupMenuBar(
|
setupMenuBar(
|
||||||
[
|
[...plugins.devicePlugins.values(), ...plugins.clientPlugins.values()],
|
||||||
...newState.devicePlugins.values(),
|
|
||||||
...newState.clientPlugins.values(),
|
|
||||||
],
|
|
||||||
store,
|
store,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
state = newState;
|
);
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function getBundledPlugins(): Array<PluginDefinition> {
|
function getBundledPlugins(): Array<PluginDefinition> {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {Store} from '../reducers/index';
|
|||||||
import {Logger} from '../fb-interfaces/Logger';
|
import {Logger} from '../fb-interfaces/Logger';
|
||||||
import {login, logout} from '../reducers/user';
|
import {login, logout} from '../reducers/user';
|
||||||
import {getUser, logoutUser} from '../fb-stubs/user';
|
import {getUser, logoutUser} from '../fb-stubs/user';
|
||||||
|
import {sideEffect} from '../utils/sideEffect';
|
||||||
|
|
||||||
export default (store: Store, _logger: Logger) => {
|
export default (store: Store, _logger: Logger) => {
|
||||||
getUser()
|
getUser()
|
||||||
@@ -23,10 +24,15 @@ export default (store: Store, _logger: Logger) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let prevUserName = store.getState().user.name;
|
let prevUserName = store.getState().user.name;
|
||||||
store.subscribe(() => {
|
sideEffect(
|
||||||
if (prevUserName && !store.getState().user.name) {
|
store,
|
||||||
logoutUser();
|
{name: 'logout', throttleMs: 500},
|
||||||
}
|
(state) => state.user.name,
|
||||||
prevUserName = store.getState().user.name;
|
(userName) => {
|
||||||
});
|
if (prevUserName && !userName) {
|
||||||
|
logoutUser();
|
||||||
|
}
|
||||||
|
prevUserName = userName;
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user