Add wrapper support for import / export states

Summary: Make sure custom export handlers of classic plugins wrapped in Sandy are respected

Reviewed By: passy

Differential Revision: D29233604

fbshipit-source-id: 7bab33af3422e0b59697438577906ce8580a28ad
This commit is contained in:
Michel Weststrate
2021-06-21 08:35:52 -07:00
committed by Facebook GitHub Bot
parent e40faaef3f
commit 806dd63f68
3 changed files with 48 additions and 9 deletions

View File

@@ -32,10 +32,7 @@ export type SandyPluginModule = ConstructorParameters<
>[1]; >[1];
// Wrapped features // Wrapped features
// exportPersistedState
// getActiveNotifications // getActiveNotifications
// serializePersistedState
// static deserializePersistedState: (
export function createSandyPluginWrapper<S, A extends BaseAction, P>( export function createSandyPluginWrapper<S, A extends BaseAction, P>(
Plugin: typeof FlipperPlugin | typeof FlipperDevicePlugin, Plugin: typeof FlipperPlugin | typeof FlipperDevicePlugin,
@@ -48,12 +45,12 @@ export function createSandyPluginWrapper<S, A extends BaseAction, P>(
); );
function plugin(client: PluginClient | DevicePluginClient) { function plugin(client: PluginClient | DevicePluginClient) {
const appClient = isDevicePlugin ? undefined : (client as PluginClient); const appClient = isDevicePlugin
? undefined
: (client as PluginClient<any, any>);
const instanceRef = React.createRef<FlipperPlugin<S, A, P> | null>(); const instanceRef = React.createRef<FlipperPlugin<S, A, P> | null>();
const persistedState = createState<P>(Plugin.defaultPersistedState, { const persistedState = createState<P>(Plugin.defaultPersistedState);
persist: 'persistedState',
});
const deeplink = createState<unknown>(); const deeplink = createState<unknown>();
client.onDeepLink((link) => { client.onDeepLink((link) => {
@@ -68,6 +65,47 @@ export function createSandyPluginWrapper<S, A extends BaseAction, P>(
} }
}); });
if (
Plugin.persistedStateReducer ||
Plugin.exportPersistedState ||
Plugin.defaultPersistedState ||
Plugin.serializePersistedState
) {
client.onExport(async (idler, onStatusMessage) => {
const state = Plugin.exportPersistedState
? await Plugin.exportPersistedState(
isDevicePlugin
? undefined
: (method: string, params: any) =>
appClient!.send(method, params),
persistedState.get(),
undefined, // passing an undefined Store is safe, as no plugin actually uses this param
idler,
onStatusMessage,
isDevicePlugin
? undefined
: (method: string) => appClient!.supportsMethod(method),
)
: persistedState.get();
// respect custom serialization
return Plugin.serializePersistedState
? await Plugin.serializePersistedState(
state,
onStatusMessage,
idler,
Plugin.id,
)
: state;
});
client.onImport((data) => {
if (Plugin.deserializePersistedState) {
data = Plugin.deserializePersistedState(data);
}
persistedState.set(data);
});
}
if (Plugin.keyboardActions) { if (Plugin.keyboardActions) {
function executeKeyboardAction(action: string) { function executeKeyboardAction(action: string) {
instanceRef?.current?.onKeyboardAction?.(action); instanceRef?.current?.onKeyboardAction?.(action);

View File

@@ -264,6 +264,7 @@ async function exportSandyPluginStates(
if (!res[client.id]) { if (!res[client.id]) {
res[client.id] = {}; res[client.id] = {};
} }
// makeObjectSerializable is slow but very convenient by default. If people want to speed things up
res[client.id][pluginId] = await makeObjectSerializable( res[client.id][pluginId] = await makeObjectSerializable(
await client.sandyPluginStates await client.sandyPluginStates
.get(pluginId)! .get(pluginId)!

View File

@@ -84,12 +84,12 @@ export default class LayoutPlugin extends FlipperPlugin<
| undefined | undefined
| ((method: ClientMethodCalls, params?: any) => Promise<any>), | ((method: ClientMethodCalls, params?: any) => Promise<any>),
persistedState: PersistedState | undefined, persistedState: PersistedState | undefined,
store: ReduxState | undefined, _store: ReduxState | undefined,
_idler?: Idler | undefined, _idler?: Idler | undefined,
statusUpdate?: (msg: string) => void, statusUpdate?: (msg: string) => void,
supportsMethod?: (method: ClientMethodCalls) => Promise<boolean>, supportsMethod?: (method: ClientMethodCalls) => Promise<boolean>,
): Promise<PersistedState | undefined> => { ): Promise<PersistedState | undefined> => {
if (!store || !callClient) { if (!callClient) {
return persistedState; return persistedState;
} }
statusUpdate && statusUpdate('Fetching Root Node...'); statusUpdate && statusUpdate('Fetching Root Node...');