Files
flipper/desktop/app/src/reducers/pluginStates.tsx
Anton Nikolaev 01f02b2cab Command processing (3/n): Uninstall plugin
Summary:
*Stack summary*: this stack refactors plugin management actions to perform them in a dispatcher rather than in the root reducer (store.tsx) as all of these actions has side effects. To do that, we store requested plugin management actions (install/update/uninstall, star/unstar) in a queue which is then handled by pluginManager dispatcher. This dispatcher then dispatches all required state updates.

*Diff summary*: refactored "uninstall plugin" operation to perform it in pluginManager dispatcher

Reviewed By: mweststrate

Differential Revision: D26166198

fbshipit-source-id: d74a1d690102d9036c6d3d8612d2428f5ecef4e6
2021-02-16 10:50:17 -08:00

98 lines
2.6 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 {produce} from 'immer';
import {Actions} from '.';
import {deconstructPluginKey} from '../utils/clientUtils';
export type State = {
[pluginKey: string]: any;
};
export const pluginKey = (serial: string, pluginName: string): string => {
return `${serial}#${pluginName}`;
};
export type Action =
| {
type: 'SET_PLUGIN_STATE';
payload: {
pluginKey: string;
state: Object;
};
}
| {
type: 'CLEAR_CLIENT_PLUGINS_STATE';
payload: {clientId: string; devicePlugins: Set<string>};
}
| {
type: 'CLEAR_PLUGIN_STATE';
payload: {pluginId: string};
};
export default function reducer(
state: State | undefined = {},
action: Actions,
): State {
if (action.type === 'SET_PLUGIN_STATE') {
const newPluginState = action.payload.state;
if (newPluginState && newPluginState !== state[action.payload.pluginKey]) {
return {
...state,
[action.payload.pluginKey]: {
...state[action.payload.pluginKey],
...newPluginState,
},
};
}
return {...state};
} else if (action.type === 'CLEAR_CLIENT_PLUGINS_STATE') {
const {payload} = action;
return Object.keys(state).reduce((newState: State, pluginKey) => {
// Only add the pluginState, if its from a plugin other than the one that
// was removed. pluginKeys are in the form of ${clientID}#${pluginID}.
const plugin = deconstructPluginKey(pluginKey);
const clientId = plugin.client;
const pluginId = plugin.pluginName;
if (
clientId !== payload.clientId ||
(pluginId && payload.devicePlugins.has(pluginId))
) {
newState[pluginKey] = state[pluginKey];
}
return newState;
}, {});
} else if (action.type === 'CLEAR_PLUGIN_STATE') {
const {pluginId} = action.payload;
return produce(state, (draft) => {
Object.keys(draft).forEach((pluginKey) => {
const pluginKeyParts = deconstructPluginKey(pluginKey);
if (pluginKeyParts.pluginName === pluginId) {
delete draft[pluginKey];
}
});
});
} else {
return state;
}
}
export const setPluginState = (payload: {
pluginKey: string;
state: Object;
}): Action => ({
type: 'SET_PLUGIN_STATE',
payload,
});
export const clearPluginState = (payload: {pluginId: string}): Action => ({
type: 'CLEAR_PLUGIN_STATE',
payload,
});