Reload single device plugin on auto-update

Summary: The same as D23729972 (0982dc06a0), but now it is also possible to reload device plugins independently.

Reviewed By: jknoxville

Differential Revision: D23960058

fbshipit-source-id: 01e0edb29a62ed173dfe6f5946466269adee453a
This commit is contained in:
Anton Nikolaev
2020-09-28 04:45:51 -07:00
committed by Facebook GitHub Bot
parent 1b4c08b282
commit 80c7c76ef9
3 changed files with 93 additions and 46 deletions

View File

@@ -18,8 +18,15 @@ import {
isDevicePluginDefinition,
} from './utils/pluginUtils';
import Client from './Client';
import {PluginDefinition} from './plugin';
import {
DevicePluginDefinition,
FlipperPlugin,
PluginDefinition,
} from './plugin';
import {deconstructPluginKey} from './utils/clientUtils';
import {SandyPluginDefinition} from 'flipper-plugin';
import BaseDevice from './devices/BaseDevice';
import {State as PluginStates} from './reducers/pluginStates';
export const store: Store = createStore<StoreState, Actions, any, any>(
rootReducer,
@@ -69,42 +76,12 @@ export function rootReducer(
}
});
} else if (action.type === 'UPDATE_PLUGIN' && state) {
const plugin: PluginDefinition = action.payload;
const clients = state.connections.clients;
return produce(state, (draft) => {
const clientsWithEnabledPlugin = clients.filter((c) => {
return (
c.supportsPlugin(plugin.id) &&
state.connections.userStarredPlugins[c.query.app]?.includes(plugin.id)
);
});
// stop plugin for each client where it is enabled
clientsWithEnabledPlugin.forEach((client) => {
stopPlugin(client, plugin.id, true);
delete draft.pluginMessageQueue[
getPluginKey(client.id, {serial: client.query.device_id}, plugin.id)
];
});
// cleanup classic plugin state
Object.keys(draft.pluginStates).forEach((pluginKey) => {
const pluginKeyParts = deconstructPluginKey(pluginKey);
if (pluginKeyParts.pluginName === plugin.id) {
delete draft.pluginStates[pluginKey];
}
});
// update plugin definition
const {devicePlugins, clientPlugins} = draft.plugins;
const p = action.payload;
if (isDevicePluginDefinition(p)) {
devicePlugins.set(p.id, p);
} else {
clientPlugins.set(p.id, p);
}
// start plugin for each client
clientsWithEnabledPlugin.forEach((client) => {
startPlugin(client, plugin, true);
});
});
const plugin = action.payload;
if (isDevicePluginDefinition(plugin)) {
return updateDevicePlugin(state, plugin);
} else {
return updateClientPlugin(state, plugin);
}
}
// otherwise
@@ -149,3 +126,66 @@ function startPlugin(
client.initPlugin(plugin.id);
}
}
function updateClientPlugin(state: StoreState, plugin: typeof FlipperPlugin) {
const clients = state.connections.clients;
return produce(state, (draft) => {
const clientsWithEnabledPlugin = clients.filter((c) => {
return (
c.supportsPlugin(plugin.id) &&
state.connections.userStarredPlugins[c.query.app]?.includes(plugin.id)
);
});
// stop plugin for each client where it is enabled
clientsWithEnabledPlugin.forEach((client) => {
stopPlugin(client, plugin.id, true);
delete draft.pluginMessageQueue[
getPluginKey(client.id, {serial: client.query.device_id}, plugin.id)
];
});
cleanupPluginStates(draft.pluginStates, plugin.id);
// update plugin definition
draft.plugins.clientPlugins.set(plugin.id, plugin);
// start plugin for each client
clientsWithEnabledPlugin.forEach((client) => {
startPlugin(client, plugin, true);
});
});
}
function updateDevicePlugin(state: StoreState, plugin: DevicePluginDefinition) {
const devices = state.connections.devices;
return produce(state, (draft) => {
const devicesWithEnabledPlugin = devices.filter((d) =>
supportsDevice(plugin, d),
);
devicesWithEnabledPlugin.forEach((d) => {
d.unloadDevicePlugin(plugin.id);
});
cleanupPluginStates(draft.pluginStates, plugin.id);
draft.plugins.devicePlugins.set(plugin.id, plugin);
devicesWithEnabledPlugin.forEach((d) => {
d.loadDevicePlugin(plugin);
});
});
}
function supportsDevice(plugin: DevicePluginDefinition, device: BaseDevice) {
if (plugin instanceof SandyPluginDefinition) {
return (
plugin.isDevicePlugin &&
plugin.asDevicePluginModule().supportsDevice(device as any)
);
} else {
return plugin.supportsDevice(device);
}
}
function cleanupPluginStates(pluginStates: PluginStates, pluginId: string) {
Object.keys(pluginStates).forEach((pluginKey) => {
const pluginKeyParts = deconstructPluginKey(pluginKey);
if (pluginKeyParts.pluginName === pluginId) {
delete pluginStates[pluginKey];
}
});
}