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 {getPluginKey} from './utils/pluginUtils';
|
||||
import {processMessageLater} from './utils/messageQueue';
|
||||
import {sideEffect} from './utils/sideEffect';
|
||||
|
||||
type Plugins = Array<string>;
|
||||
|
||||
@@ -207,21 +208,25 @@ export default class Client extends EventEmitter {
|
||||
console.error(error);
|
||||
reject(error);
|
||||
}, 5000);
|
||||
unsubscribe = this.store.subscribe(() => {
|
||||
const newDeviceList = this.store.getState().connections.devices;
|
||||
if (newDeviceList === this.lastSeenDeviceList) {
|
||||
return;
|
||||
}
|
||||
this.lastSeenDeviceList = this.store.getState().connections.devices;
|
||||
const matchingDevice = newDeviceList.find(
|
||||
(device) => device.serial === this.query.device_id,
|
||||
);
|
||||
if (matchingDevice) {
|
||||
clearTimeout(timeout);
|
||||
resolve(matchingDevice);
|
||||
unsubscribe();
|
||||
}
|
||||
});
|
||||
unsubscribe = sideEffect(
|
||||
this.store,
|
||||
{name: 'waitForDevice', throttleMs: 100},
|
||||
(state) => state.connections.devices,
|
||||
(newDeviceList) => {
|
||||
if (newDeviceList === this.lastSeenDeviceList) {
|
||||
return;
|
||||
}
|
||||
this.lastSeenDeviceList = newDeviceList;
|
||||
const matchingDevice = newDeviceList.find(
|
||||
(device) => device.serial === this.query.device_id,
|
||||
);
|
||||
if (matchingDevice) {
|
||||
clearTimeout(timeout);
|
||||
resolve(matchingDevice);
|
||||
unsubscribe();
|
||||
}
|
||||
},
|
||||
);
|
||||
}),
|
||||
'client-setMatchingDevice',
|
||||
).then((device) => {
|
||||
|
||||
@@ -24,6 +24,7 @@ import GK from '../fb-stubs/GK';
|
||||
import {deconstructPluginKey} from '../utils/clientUtils';
|
||||
import NotificationScreen from '../chrome/NotificationScreen';
|
||||
import {getPluginTitle} from '../utils/pluginUtils';
|
||||
import {sideEffect} from '../utils/sideEffect';
|
||||
|
||||
type NotificationEvents = 'show' | 'click' | 'close' | 'reply' | 'action';
|
||||
const NOTIFICATION_THROTTLE = 5 * 1000; // in milliseconds
|
||||
@@ -84,118 +85,114 @@ export default (store: Store, logger: Logger) => {
|
||||
},
|
||||
);
|
||||
|
||||
store.subscribe(() => {
|
||||
const {notifications, pluginStates} = store.getState();
|
||||
sideEffect(
|
||||
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()
|
||||
.plugins.clientPlugins;
|
||||
Object.keys(pluginStates).forEach((key) => {
|
||||
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<
|
||||
string,
|
||||
typeof FlipperDevicePlugin
|
||||
> = store.getState().plugins.devicePlugins;
|
||||
if (!pluginName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pluginMap: Map<
|
||||
string,
|
||||
typeof FlipperPlugin | typeof FlipperDevicePlugin
|
||||
> = new Map<string, typeof FlipperDevicePlugin | typeof FlipperPlugin>([
|
||||
...clientPlugins,
|
||||
...devicePlugins,
|
||||
]);
|
||||
|
||||
Object.keys(pluginStates).forEach((key) => {
|
||||
if (knownPluginStates.get(key) !== pluginStates[key]) {
|
||||
knownPluginStates.set(key, pluginStates[key]);
|
||||
const plugin = deconstructPluginKey(key);
|
||||
const pluginName = plugin.pluginName;
|
||||
const client = plugin.client;
|
||||
|
||||
if (!pluginName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const persistingPlugin:
|
||||
| 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 persistingPlugin:
|
||||
| undefined
|
||||
| typeof FlipperPlugin
|
||||
| typeof FlipperDevicePlugin = getPlugin(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 {
|
||||
activeNotifications,
|
||||
blacklistedPlugins,
|
||||
blacklistedCategories,
|
||||
} = 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);
|
||||
const {
|
||||
activeNotifications,
|
||||
blacklistedPlugins,
|
||||
blacklistedCategories,
|
||||
} = notifications;
|
||||
|
||||
activeNotifications.forEach((n: PluginNotification) => {
|
||||
if (
|
||||
new Date().getTime() - prevNotificationTime <
|
||||
NOTIFICATION_THROTTLE
|
||||
!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)
|
||||
) {
|
||||
// Don't send a notification if the plugin has sent a notification
|
||||
// within the NOTIFICATION_THROTTLE.
|
||||
return;
|
||||
const prevNotificationTime: number =
|
||||
lastNotificationTime.get(n.pluginId) || 0;
|
||||
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 isProduction from '../utils/isProduction';
|
||||
import {notNull} from '../utils/typeUtils';
|
||||
import {sideEffect} from '../utils/sideEffect';
|
||||
|
||||
export type PluginDefinition = {
|
||||
id?: string;
|
||||
@@ -63,20 +64,17 @@ export default (store: Store, _logger: Logger) => {
|
||||
store.dispatch(addFailedPlugins(failedPlugins));
|
||||
store.dispatch(registerPlugins(initialPlugins));
|
||||
|
||||
let state: State | null = null;
|
||||
store.subscribe(() => {
|
||||
const newState = store.getState().plugins;
|
||||
if (state !== newState) {
|
||||
sideEffect(
|
||||
store,
|
||||
{name: 'setupMenuBar', throttleMs: 100},
|
||||
(state) => state.plugins,
|
||||
(plugins, store) => {
|
||||
setupMenuBar(
|
||||
[
|
||||
...newState.devicePlugins.values(),
|
||||
...newState.clientPlugins.values(),
|
||||
],
|
||||
[...plugins.devicePlugins.values(), ...plugins.clientPlugins.values()],
|
||||
store,
|
||||
);
|
||||
}
|
||||
state = newState;
|
||||
});
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
function getBundledPlugins(): Array<PluginDefinition> {
|
||||
|
||||
@@ -11,6 +11,7 @@ import {Store} from '../reducers/index';
|
||||
import {Logger} from '../fb-interfaces/Logger';
|
||||
import {login, logout} from '../reducers/user';
|
||||
import {getUser, logoutUser} from '../fb-stubs/user';
|
||||
import {sideEffect} from '../utils/sideEffect';
|
||||
|
||||
export default (store: Store, _logger: Logger) => {
|
||||
getUser()
|
||||
@@ -23,10 +24,15 @@ export default (store: Store, _logger: Logger) => {
|
||||
});
|
||||
|
||||
let prevUserName = store.getState().user.name;
|
||||
store.subscribe(() => {
|
||||
if (prevUserName && !store.getState().user.name) {
|
||||
logoutUser();
|
||||
}
|
||||
prevUserName = store.getState().user.name;
|
||||
});
|
||||
sideEffect(
|
||||
store,
|
||||
{name: 'logout', throttleMs: 500},
|
||||
(state) => state.user.name,
|
||||
(userName) => {
|
||||
if (prevUserName && !userName) {
|
||||
logoutUser();
|
||||
}
|
||||
prevUserName = userName;
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user