Auto-install favorite plugins
Summary: After unbudling plugins users will need to manually install them. To simlify this transition we can auto-install favorite plugins on every app connection, so users won't need to install plugins which they marked as favorite before. Reviewed By: passy Differential Revision: D25538638 fbshipit-source-id: 4ac3ad0c8c026d149f7ce0c4af07da3e8b909772
This commit is contained in:
committed by
Facebook GitHub Bot
parent
bd01b58566
commit
965559ee65
@@ -56,6 +56,7 @@ Object {
|
|||||||
"disabledPlugins": Array [],
|
"disabledPlugins": Array [],
|
||||||
"failedPlugins": Array [],
|
"failedPlugins": Array [],
|
||||||
"gatekeepedPlugins": Array [],
|
"gatekeepedPlugins": Array [],
|
||||||
|
"loadedPlugins": Map {},
|
||||||
"marketplacePlugins": Array [],
|
"marketplacePlugins": Array [],
|
||||||
"selectedPlugins": Array [],
|
"selectedPlugins": Array [],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
addGatekeepedPlugins,
|
addGatekeepedPlugins,
|
||||||
addDisabledPlugins,
|
addDisabledPlugins,
|
||||||
addFailedPlugins,
|
addFailedPlugins,
|
||||||
|
registerLoadedPlugins,
|
||||||
} from '../reducers/plugins';
|
} from '../reducers/plugins';
|
||||||
import GK from '../fb-stubs/GK';
|
import GK from '../fb-stubs/GK';
|
||||||
import {FlipperBasePlugin} from '../plugin';
|
import {FlipperBasePlugin} from '../plugin';
|
||||||
@@ -63,10 +64,12 @@ export default async (store: Store, logger: Logger) => {
|
|||||||
|
|
||||||
const uninstalledPlugins = store.getState().pluginManager.uninstalledPlugins;
|
const uninstalledPlugins = store.getState().pluginManager.uninstalledPlugins;
|
||||||
|
|
||||||
const initialPlugins: PluginDefinition[] = filterNewestVersionOfEachPlugin(
|
const loadedPlugins = filterNewestVersionOfEachPlugin(
|
||||||
getBundledPlugins(),
|
getBundledPlugins(),
|
||||||
await getDynamicPlugins(),
|
await getDynamicPlugins(),
|
||||||
)
|
);
|
||||||
|
|
||||||
|
const initialPlugins: PluginDefinition[] = loadedPlugins
|
||||||
.filter((p) => !uninstalledPlugins.has(p.name))
|
.filter((p) => !uninstalledPlugins.has(p.name))
|
||||||
.map(reportVersion)
|
.map(reportVersion)
|
||||||
.filter(checkDisabled(disabledPlugins))
|
.filter(checkDisabled(disabledPlugins))
|
||||||
@@ -74,6 +77,7 @@ export default async (store: Store, logger: Logger) => {
|
|||||||
.map(createRequirePluginFunction(failedPlugins))
|
.map(createRequirePluginFunction(failedPlugins))
|
||||||
.filter(notNull);
|
.filter(notNull);
|
||||||
|
|
||||||
|
store.dispatch(registerLoadedPlugins(loadedPlugins));
|
||||||
store.dispatch(addGatekeepedPlugins(gatekeepedPlugins));
|
store.dispatch(addGatekeepedPlugins(gatekeepedPlugins));
|
||||||
store.dispatch(addDisabledPlugins(disabledPlugins));
|
store.dispatch(addDisabledPlugins(disabledPlugins));
|
||||||
store.dispatch(addFailedPlugins(failedPlugins));
|
store.dispatch(addFailedPlugins(failedPlugins));
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
addGatekeepedPlugins,
|
addGatekeepedPlugins,
|
||||||
} from '../plugins';
|
} from '../plugins';
|
||||||
import {FlipperPlugin, FlipperDevicePlugin, BaseAction} from '../../plugin';
|
import {FlipperPlugin, FlipperDevicePlugin, BaseAction} from '../../plugin';
|
||||||
|
import {InstalledPluginDetails} from 'flipper-plugin-lib';
|
||||||
|
|
||||||
const testPlugin = class extends FlipperPlugin<any, BaseAction, any> {
|
const testPlugin = class extends FlipperPlugin<any, BaseAction, any> {
|
||||||
static id = 'TestPlugin';
|
static id = 'TestPlugin';
|
||||||
@@ -31,6 +32,7 @@ test('add clientPlugin', () => {
|
|||||||
{
|
{
|
||||||
devicePlugins: new Map(),
|
devicePlugins: new Map(),
|
||||||
clientPlugins: new Map(),
|
clientPlugins: new Map(),
|
||||||
|
loadedPlugins: new Map(),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
@@ -47,6 +49,7 @@ test('add devicePlugin', () => {
|
|||||||
{
|
{
|
||||||
devicePlugins: new Map(),
|
devicePlugins: new Map(),
|
||||||
clientPlugins: new Map(),
|
clientPlugins: new Map(),
|
||||||
|
loadedPlugins: new Map(),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
@@ -63,6 +66,7 @@ test('do not add plugin twice', () => {
|
|||||||
{
|
{
|
||||||
devicePlugins: new Map(),
|
devicePlugins: new Map(),
|
||||||
clientPlugins: new Map(),
|
clientPlugins: new Map(),
|
||||||
|
loadedPlugins: new Map(),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
@@ -75,15 +79,15 @@ test('do not add plugin twice', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('add gatekeeped plugin', () => {
|
test('add gatekeeped plugin', () => {
|
||||||
const gatekeepedPlugins = [
|
const gatekeepedPlugins: InstalledPluginDetails[] = [
|
||||||
{
|
{
|
||||||
name: 'plugin',
|
name: 'plugin',
|
||||||
out: 'out.js',
|
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
dir: '/plugins/test',
|
dir: '/plugins/test',
|
||||||
specVersion: 2,
|
specVersion: 2,
|
||||||
source: 'src/index.ts',
|
source: 'src/index.ts',
|
||||||
isBundled: false,
|
isBundled: false,
|
||||||
|
isActivatable: true,
|
||||||
main: 'lib/index.js',
|
main: 'lib/index.js',
|
||||||
title: 'test',
|
title: 'test',
|
||||||
id: 'test',
|
id: 'test',
|
||||||
@@ -94,6 +98,7 @@ test('add gatekeeped plugin', () => {
|
|||||||
{
|
{
|
||||||
devicePlugins: new Map(),
|
devicePlugins: new Map(),
|
||||||
clientPlugins: new Map(),
|
clientPlugins: new Map(),
|
||||||
|
loadedPlugins: new Map(),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {DevicePluginMap, ClientPluginMap, PluginDefinition} from '../plugin';
|
import {DevicePluginMap, ClientPluginMap, PluginDefinition} from '../plugin';
|
||||||
import {PluginDetails, DownloadablePluginDetails} from 'flipper-plugin-lib';
|
import {
|
||||||
|
DownloadablePluginDetails,
|
||||||
|
ActivatablePluginDetails,
|
||||||
|
} from 'flipper-plugin-lib';
|
||||||
import {Actions} from '.';
|
import {Actions} from '.';
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import {isDevicePluginDefinition} from '../utils/pluginUtils';
|
import {isDevicePluginDefinition} from '../utils/pluginUtils';
|
||||||
@@ -16,9 +19,10 @@ import {isDevicePluginDefinition} from '../utils/pluginUtils';
|
|||||||
export type State = {
|
export type State = {
|
||||||
devicePlugins: DevicePluginMap;
|
devicePlugins: DevicePluginMap;
|
||||||
clientPlugins: ClientPluginMap;
|
clientPlugins: ClientPluginMap;
|
||||||
gatekeepedPlugins: Array<PluginDetails>;
|
loadedPlugins: Map<string, ActivatablePluginDetails>;
|
||||||
disabledPlugins: Array<PluginDetails>;
|
gatekeepedPlugins: Array<ActivatablePluginDetails>;
|
||||||
failedPlugins: Array<[PluginDetails, string]>;
|
disabledPlugins: Array<ActivatablePluginDetails>;
|
||||||
|
failedPlugins: Array<[ActivatablePluginDetails, string]>;
|
||||||
selectedPlugins: Array<string>;
|
selectedPlugins: Array<string>;
|
||||||
marketplacePlugins: Array<DownloadablePluginDetails>;
|
marketplacePlugins: Array<DownloadablePluginDetails>;
|
||||||
};
|
};
|
||||||
@@ -32,15 +36,15 @@ export type Action =
|
|||||||
| RegisterPluginAction
|
| RegisterPluginAction
|
||||||
| {
|
| {
|
||||||
type: 'GATEKEEPED_PLUGINS';
|
type: 'GATEKEEPED_PLUGINS';
|
||||||
payload: Array<PluginDetails>;
|
payload: Array<ActivatablePluginDetails>;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'DISABLED_PLUGINS';
|
type: 'DISABLED_PLUGINS';
|
||||||
payload: Array<PluginDetails>;
|
payload: Array<ActivatablePluginDetails>;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'FAILED_PLUGINS';
|
type: 'FAILED_PLUGINS';
|
||||||
payload: Array<[PluginDetails, string]>;
|
payload: Array<[ActivatablePluginDetails, string]>;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'SELECTED_PLUGINS';
|
type: 'SELECTED_PLUGINS';
|
||||||
@@ -49,11 +53,16 @@ export type Action =
|
|||||||
| {
|
| {
|
||||||
type: 'MARKETPLACE_PLUGINS';
|
type: 'MARKETPLACE_PLUGINS';
|
||||||
payload: Array<DownloadablePluginDetails>;
|
payload: Array<DownloadablePluginDetails>;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'REGISTER_LOADED_PLUGINS';
|
||||||
|
payload: Array<ActivatablePluginDetails>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const INITIAL_STATE: State = {
|
const INITIAL_STATE: State = {
|
||||||
devicePlugins: new Map(),
|
devicePlugins: new Map(),
|
||||||
clientPlugins: new Map(),
|
clientPlugins: new Map(),
|
||||||
|
loadedPlugins: new Map(),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
@@ -105,6 +114,11 @@ export default function reducer(
|
|||||||
...state,
|
...state,
|
||||||
marketplacePlugins: action.payload,
|
marketplacePlugins: action.payload,
|
||||||
};
|
};
|
||||||
|
} else if (action.type === 'REGISTER_LOADED_PLUGINS') {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
loadedPlugins: new Map(action.payload.map((p) => [p.id, p])),
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@@ -121,19 +135,21 @@ export const registerPlugins = (payload: PluginDefinition[]): Action => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const addGatekeepedPlugins = (
|
export const addGatekeepedPlugins = (
|
||||||
payload: Array<PluginDetails>,
|
payload: Array<ActivatablePluginDetails>,
|
||||||
): Action => ({
|
): Action => ({
|
||||||
type: 'GATEKEEPED_PLUGINS',
|
type: 'GATEKEEPED_PLUGINS',
|
||||||
payload,
|
payload,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const addDisabledPlugins = (payload: Array<PluginDetails>): Action => ({
|
export const addDisabledPlugins = (
|
||||||
|
payload: Array<ActivatablePluginDetails>,
|
||||||
|
): Action => ({
|
||||||
type: 'DISABLED_PLUGINS',
|
type: 'DISABLED_PLUGINS',
|
||||||
payload,
|
payload,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const addFailedPlugins = (
|
export const addFailedPlugins = (
|
||||||
payload: Array<[PluginDetails, string]>,
|
payload: Array<[ActivatablePluginDetails, string]>,
|
||||||
): Action => ({
|
): Action => ({
|
||||||
type: 'FAILED_PLUGINS',
|
type: 'FAILED_PLUGINS',
|
||||||
payload,
|
payload,
|
||||||
@@ -145,3 +161,10 @@ export const registerMarketplacePlugins = (
|
|||||||
type: 'MARKETPLACE_PLUGINS',
|
type: 'MARKETPLACE_PLUGINS',
|
||||||
payload,
|
payload,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const registerLoadedPlugins = (
|
||||||
|
payload: Array<ActivatablePluginDetails>,
|
||||||
|
): Action => ({
|
||||||
|
type: 'REGISTER_LOADED_PLUGINS',
|
||||||
|
payload,
|
||||||
|
});
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {deconstructPluginKey} from './utils/clientUtils';
|
|||||||
import {_SandyPluginDefinition} from 'flipper-plugin';
|
import {_SandyPluginDefinition} from 'flipper-plugin';
|
||||||
import BaseDevice from './devices/BaseDevice';
|
import BaseDevice from './devices/BaseDevice';
|
||||||
import {State as PluginStates} from './reducers/pluginStates';
|
import {State as PluginStates} from './reducers/pluginStates';
|
||||||
|
import {ActivatablePluginDetails} from 'flipper-plugin-lib';
|
||||||
|
|
||||||
export const store: Store = createStore<StoreState, Actions, any, any>(
|
export const store: Store = createStore<StoreState, Actions, any, any>(
|
||||||
rootReducer,
|
rootReducer,
|
||||||
@@ -173,7 +174,7 @@ function updateClientPlugin(
|
|||||||
clientsWithEnabledPlugin.forEach((client) => {
|
clientsWithEnabledPlugin.forEach((client) => {
|
||||||
startPlugin(client, plugin, true);
|
startPlugin(client, plugin, true);
|
||||||
});
|
});
|
||||||
draft.pluginManager.uninstalledPlugins.delete(plugin.details.name);
|
registerLoadedPlugin(draft, plugin.details);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,6 +192,7 @@ function uninstallPlugin(state: StoreState, plugin: PluginDefinition) {
|
|||||||
});
|
});
|
||||||
cleanupPluginStates(draft.pluginStates, plugin.id);
|
cleanupPluginStates(draft.pluginStates, plugin.id);
|
||||||
draft.plugins.clientPlugins.delete(plugin.id);
|
draft.plugins.clientPlugins.delete(plugin.id);
|
||||||
|
draft.plugins.devicePlugins.delete(plugin.id);
|
||||||
draft.pluginManager.uninstalledPlugins.add(plugin.details.name);
|
draft.pluginManager.uninstalledPlugins.add(plugin.details.name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -209,9 +211,21 @@ function updateDevicePlugin(state: StoreState, plugin: DevicePluginDefinition) {
|
|||||||
devicesWithEnabledPlugin.forEach((d) => {
|
devicesWithEnabledPlugin.forEach((d) => {
|
||||||
d.loadDevicePlugin(plugin);
|
d.loadDevicePlugin(plugin);
|
||||||
});
|
});
|
||||||
|
registerLoadedPlugin(draft, plugin.details);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function registerLoadedPlugin(
|
||||||
|
draft: {
|
||||||
|
pluginManager: StoreState['pluginManager'];
|
||||||
|
plugins: StoreState['plugins'];
|
||||||
|
},
|
||||||
|
plugin: ActivatablePluginDetails,
|
||||||
|
) {
|
||||||
|
draft.pluginManager.uninstalledPlugins.delete(plugin.name);
|
||||||
|
draft.plugins.loadedPlugins.set(plugin.id, plugin);
|
||||||
|
}
|
||||||
|
|
||||||
function supportsDevice(plugin: DevicePluginDefinition, device: BaseDevice) {
|
function supportsDevice(plugin: DevicePluginDefinition, device: BaseDevice) {
|
||||||
if (plugin instanceof _SandyPluginDefinition) {
|
if (plugin instanceof _SandyPluginDefinition) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -762,6 +762,11 @@ test('test determinePluginsToProcess for mutilple clients having plugins present
|
|||||||
['RandomPlugin', TestPlugin],
|
['RandomPlugin', TestPlugin],
|
||||||
]),
|
]),
|
||||||
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
||||||
|
loadedPlugins: new Map([
|
||||||
|
['TestPlugin', TestPlugin.details],
|
||||||
|
['RandomPlugin', TestPlugin.details],
|
||||||
|
['TestDevicePlugin', TestDevicePlugin.details],
|
||||||
|
]),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
@@ -828,6 +833,11 @@ test('test determinePluginsToProcess for no selected plugin present in any clien
|
|||||||
['RandomPlugin', TestPlugin],
|
['RandomPlugin', TestPlugin],
|
||||||
]),
|
]),
|
||||||
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
||||||
|
loadedPlugins: new Map([
|
||||||
|
['TestPlugin', TestPlugin.details],
|
||||||
|
['RandomPlugin', TestPlugin.details],
|
||||||
|
['TestDevicePlugin', TestDevicePlugin.details],
|
||||||
|
]),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
@@ -872,6 +882,10 @@ test('test determinePluginsToProcess for multiple clients on same device', async
|
|||||||
const plugins: PluginsState = {
|
const plugins: PluginsState = {
|
||||||
clientPlugins: new Map([['TestPlugin', TestPlugin]]),
|
clientPlugins: new Map([['TestPlugin', TestPlugin]]),
|
||||||
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
||||||
|
loadedPlugins: new Map([
|
||||||
|
['TestPlugin', TestPlugin.details],
|
||||||
|
['TestDevicePlugin', TestDevicePlugin.details],
|
||||||
|
]),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
@@ -954,6 +968,10 @@ test('test determinePluginsToProcess for multiple clients on different device',
|
|||||||
const plugins: PluginsState = {
|
const plugins: PluginsState = {
|
||||||
clientPlugins: new Map([['TestPlugin', TestPlugin]]),
|
clientPlugins: new Map([['TestPlugin', TestPlugin]]),
|
||||||
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
||||||
|
loadedPlugins: new Map([
|
||||||
|
['TestPlugin', TestPlugin.details],
|
||||||
|
['TestDevicePlugin', TestDevicePlugin.details],
|
||||||
|
]),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
@@ -1033,6 +1051,10 @@ test('test determinePluginsToProcess to ignore archived clients', async () => {
|
|||||||
const plugins: PluginsState = {
|
const plugins: PluginsState = {
|
||||||
clientPlugins: new Map([['TestPlugin', TestPlugin]]),
|
clientPlugins: new Map([['TestPlugin', TestPlugin]]),
|
||||||
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
||||||
|
loadedPlugins: new Map([
|
||||||
|
['TestPlugin', TestPlugin.details],
|
||||||
|
['TestDevicePlugin', TestDevicePlugin.details],
|
||||||
|
]),
|
||||||
gatekeepedPlugins: [],
|
gatekeepedPlugins: [],
|
||||||
disabledPlugins: [],
|
disabledPlugins: [],
|
||||||
failedPlugins: [],
|
failedPlugins: [],
|
||||||
|
|||||||
Reference in New Issue
Block a user