Use AbstractClient from flipper-frontend-core in fliper-ui-core
Summary: This stack attempts to start using flipper-frontend-core from flipper-ui-core. Currently, flipper-frontend-core contains lots of copy-pasted code from flipper-ui-core. Reviewed By: lblasa Differential Revision: D37139198 fbshipit-source-id: 042db7492c550e10ea72c32fd15001c141bf53f9
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c2e3c4eb50
commit
ef5fa275a3
@@ -15,7 +15,7 @@
|
|||||||
"flipper-plugin": "0.0.0",
|
"flipper-plugin": "0.0.0",
|
||||||
"immer": "^9.0.12",
|
"immer": "^9.0.12",
|
||||||
"js-base64": "^3.7.2",
|
"js-base64": "^3.7.2",
|
||||||
"p-map": "^5.3.0",
|
"p-map": "^4.0.0",
|
||||||
"reconnecting-websocket": "^4.4.0",
|
"reconnecting-websocket": "^4.4.0",
|
||||||
"semver": "^7.3.7"
|
"semver": "^7.3.7"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -37,11 +37,6 @@ import isProduction from './utils/isProduction';
|
|||||||
type Plugins = Set<string>;
|
type Plugins = Set<string>;
|
||||||
type PluginsArr = Array<string>;
|
type PluginsArr = Array<string>;
|
||||||
|
|
||||||
export type ClientExport = {
|
|
||||||
id: string;
|
|
||||||
query: ClientQuery;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Params = {
|
export type Params = {
|
||||||
api: string;
|
api: string;
|
||||||
method: string;
|
method: string;
|
||||||
@@ -108,7 +103,7 @@ export default abstract class AbstractClient extends EventEmitter {
|
|||||||
protected abstract shouldConnectAsBackgroundPlugin(pluginId: string): boolean;
|
protected abstract shouldConnectAsBackgroundPlugin(pluginId: string): boolean;
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
await this.loadPlugins();
|
await this.loadPlugins('init');
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
[...this.plugins].map(async (pluginId) =>
|
[...this.plugins].map(async (pluginId) =>
|
||||||
this.startPluginIfNeeded(await this.getPlugin(pluginId)),
|
this.startPluginIfNeeded(await this.getPlugin(pluginId)),
|
||||||
@@ -124,7 +119,7 @@ export default abstract class AbstractClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the supported plugins
|
// get the supported plugins
|
||||||
protected async loadPlugins(): Promise<Plugins> {
|
protected async loadPlugins(_phase: 'init' | 'refresh'): Promise<Plugins> {
|
||||||
const {plugins} = await timeout(
|
const {plugins} = await timeout(
|
||||||
30 * 1000,
|
30 * 1000,
|
||||||
this.rawCall<{plugins: Plugins}>('getPlugins', false),
|
this.rawCall<{plugins: Plugins}>('getPlugins', false),
|
||||||
@@ -204,9 +199,9 @@ export default abstract class AbstractClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the plugins, and update the UI
|
// get the plugins, and update the UI
|
||||||
protected async refreshPlugins() {
|
async refreshPlugins() {
|
||||||
const oldBackgroundPlugins = this.backgroundPlugins;
|
const oldBackgroundPlugins = this.backgroundPlugins;
|
||||||
await this.loadPlugins();
|
await this.loadPlugins('refresh');
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
[...this.plugins].map(async (pluginId) =>
|
[...this.plugins].map(async (pluginId) =>
|
||||||
this.startPluginIfNeeded(await this.getPlugin(pluginId)),
|
this.startPluginIfNeeded(await this.getPlugin(pluginId)),
|
||||||
@@ -291,13 +286,7 @@ export default abstract class AbstractClient extends EventEmitter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const pluginInstance = this.getPluginInstanceForExecuteMessage(params);
|
const handled = this.handleExecuteMessage(params);
|
||||||
|
|
||||||
let handled = false; // This is just for analysis
|
|
||||||
if (pluginInstance) {
|
|
||||||
handled = true;
|
|
||||||
pluginInstance.receiveMessages([params]);
|
|
||||||
}
|
|
||||||
if (!handled && !isProduction()) {
|
if (!handled && !isProduction()) {
|
||||||
console.warn(`Unhandled message ${params.api}.${params.method}`);
|
console.warn(`Unhandled message ${params.api}.${params.method}`);
|
||||||
}
|
}
|
||||||
@@ -307,10 +296,13 @@ export default abstract class AbstractClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getPluginInstanceForExecuteMessage(
|
protected handleExecuteMessage(params: Params): boolean {
|
||||||
params: Params,
|
const pluginInstance = this.sandyPluginStates.get(params.api);
|
||||||
): _SandyPluginInstance | undefined {
|
if (!pluginInstance) {
|
||||||
return this.sandyPluginStates.get(params.api);
|
return false;
|
||||||
|
}
|
||||||
|
pluginInstance.receiveMessages([params]);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onResponse(
|
protected onResponse(
|
||||||
@@ -502,6 +494,17 @@ export default abstract class AbstractClient extends EventEmitter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
send(api: string, method: string, params?: Object): void {
|
||||||
|
if (!isProduction()) {
|
||||||
|
console.warn(
|
||||||
|
`${api}:${
|
||||||
|
method || ''
|
||||||
|
} client.send() is deprecated. Please use call() instead so you can handle errors.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.rawSend('execute', {api, method, params});
|
||||||
|
}
|
||||||
|
|
||||||
async supportsMethod(api: string, method: string): Promise<boolean> {
|
async supportsMethod(api: string, method: string): Promise<boolean> {
|
||||||
if (!this.connected.get()) {
|
if (!this.connected.get()) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -8,10 +8,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export {RenderHost, getRenderHostInstance} from './RenderHost';
|
export {RenderHost, getRenderHostInstance} from './RenderHost';
|
||||||
export {default as AbstractClient, ClientConnection} from './AbstractClient';
|
export {
|
||||||
|
default as AbstractClient,
|
||||||
|
ClientConnection,
|
||||||
|
Params,
|
||||||
|
RequestMetadata,
|
||||||
|
} from './AbstractClient';
|
||||||
export {default as ArchivedDevice} from './devices/ArchivedDevice';
|
export {default as ArchivedDevice} from './devices/ArchivedDevice';
|
||||||
export {default as BaseDevice} from './devices/BaseDevice';
|
export {default as BaseDevice} from './devices/BaseDevice';
|
||||||
export * from './globalObject';
|
export * from './globalObject';
|
||||||
export * from './plugins';
|
export * from './plugins';
|
||||||
|
export {getPluginKey} from './utils/pluginKey';
|
||||||
export * from './flipperLibImplementation';
|
export * from './flipperLibImplementation';
|
||||||
export * from './client/FlipperServerClient';
|
export * from './client/FlipperServerClient';
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"eventemitter3": "^4.0.7",
|
"eventemitter3": "^4.0.7",
|
||||||
"flipper-client-sdk": "^0.0.3",
|
"flipper-client-sdk": "^0.0.3",
|
||||||
"flipper-common": "0.0.0",
|
"flipper-common": "0.0.0",
|
||||||
|
"flipper-frontend-core": "0.0.0",
|
||||||
"flipper-plugin": "0.0.0",
|
"flipper-plugin": "0.0.0",
|
||||||
"flipper-ui-core": "0.0.0",
|
"flipper-ui-core": "0.0.0",
|
||||||
"hotkeys-js": "^3.9.3",
|
"hotkeys-js": "^3.9.3",
|
||||||
|
|||||||
@@ -10,63 +10,40 @@
|
|||||||
// We're using `deviceSync` here on purpose which is triggering a lot of warnings.
|
// We're using `deviceSync` here on purpose which is triggering a lot of warnings.
|
||||||
/* eslint-disable node/no-sync */
|
/* eslint-disable node/no-sync */
|
||||||
|
|
||||||
import {PluginDefinition} from './plugin';
|
|
||||||
import BaseDevice from './devices/BaseDevice';
|
|
||||||
import {Logger, FlipperServer, ServerAddOnControls} from 'flipper-common';
|
|
||||||
import {Store} from './reducers/index';
|
|
||||||
import {
|
import {
|
||||||
reportPluginFailures,
|
Logger,
|
||||||
NoLongerConnectedToClientError,
|
FlipperServer,
|
||||||
|
ClientQuery,
|
||||||
|
ClientErrorType,
|
||||||
} from 'flipper-common';
|
} from 'flipper-common';
|
||||||
import {default as isProduction} from './utils/isProduction';
|
import {Store} from './reducers/index';
|
||||||
import EventEmitter from 'eventemitter3';
|
import {NoLongerConnectedToClientError} from 'flipper-common';
|
||||||
import {getPluginKey} from './utils/pluginKey';
|
|
||||||
|
|
||||||
import {defaultEnabledBackgroundPlugins} from './utils/pluginUtils';
|
import {defaultEnabledBackgroundPlugins} from './utils/pluginUtils';
|
||||||
import {processMessagesLater} from './utils/messageQueue';
|
import {processMessagesLater} from './utils/messageQueue';
|
||||||
import {emitBytesReceived} from './dispatcher/tracking';
|
import {emitBytesReceived} from './dispatcher/tracking';
|
||||||
import {debounce} from 'lodash';
|
import {debounce} from 'lodash';
|
||||||
import {batch} from 'react-redux';
|
import {batch} from 'react-redux';
|
||||||
import {
|
import {_SandyPluginInstance, _SandyPluginDefinition} from 'flipper-plugin';
|
||||||
timeout,
|
|
||||||
ClientQuery,
|
|
||||||
ClientResponseType,
|
|
||||||
ClientErrorType,
|
|
||||||
} from 'flipper-common';
|
|
||||||
import {
|
|
||||||
createState,
|
|
||||||
_SandyPluginInstance,
|
|
||||||
getFlipperLib,
|
|
||||||
_SandyPluginDefinition,
|
|
||||||
} from 'flipper-plugin';
|
|
||||||
import {freeze} from 'immer';
|
|
||||||
import {message} from 'antd';
|
import {message} from 'antd';
|
||||||
import {
|
import {
|
||||||
isFlipperMessageDebuggingEnabled,
|
isFlipperMessageDebuggingEnabled,
|
||||||
registerFlipperDebugMessage,
|
registerFlipperDebugMessage,
|
||||||
} from './chrome/FlipperMessages';
|
} from './chrome/FlipperMessages';
|
||||||
import {waitFor} from './utils/waitFor';
|
import {waitFor} from './utils/waitFor';
|
||||||
import {createServerAddOnControls} from './utils/createServerAddOnControls';
|
import {
|
||||||
|
AbstractClient,
|
||||||
type Plugins = Set<string>;
|
Params,
|
||||||
type PluginsArr = Array<string>;
|
ClientConnection,
|
||||||
|
BaseDevice,
|
||||||
|
RequestMetadata,
|
||||||
|
getPluginKey,
|
||||||
|
} from 'flipper-frontend-core';
|
||||||
|
|
||||||
export type ClientExport = {
|
export type ClientExport = {
|
||||||
id: string;
|
id: string;
|
||||||
query: ClientQuery;
|
query: ClientQuery;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Params = {
|
|
||||||
api: string;
|
|
||||||
method: string;
|
|
||||||
params?: Object;
|
|
||||||
};
|
|
||||||
export type RequestMetadata = {
|
|
||||||
method: string;
|
|
||||||
id: number;
|
|
||||||
params: Params | undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleError = (
|
const handleError = (
|
||||||
store: Store,
|
store: Store,
|
||||||
device: BaseDevice,
|
device: BaseDevice,
|
||||||
@@ -97,25 +74,8 @@ const handleError = (
|
|||||||
crashReporterPlugin.instanceApi.reportCrash(payload);
|
crashReporterPlugin.instanceApi.reportCrash(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ClientConnection {
|
export default class Client extends AbstractClient {
|
||||||
send(data: any): void;
|
|
||||||
sendExpectResponse(data: any): Promise<ClientResponseType>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Client extends EventEmitter {
|
|
||||||
connected = createState(false);
|
|
||||||
id: string;
|
|
||||||
query: ClientQuery;
|
|
||||||
sdkVersion: number;
|
|
||||||
messageIdCounter: number;
|
|
||||||
plugins: Plugins; // TODO: turn into atom, and remove eventEmitter
|
|
||||||
backgroundPlugins: Plugins;
|
|
||||||
connection: ClientConnection | null | undefined;
|
|
||||||
store: Store;
|
store: Store;
|
||||||
activePlugins: Set<string>;
|
|
||||||
|
|
||||||
device: BaseDevice;
|
|
||||||
logger: Logger;
|
|
||||||
broadcastCallbacks: Map<string, Map<string, Set<Function>>>;
|
broadcastCallbacks: Map<string, Map<string, Set<Function>>>;
|
||||||
messageBuffer: Record<
|
messageBuffer: Record<
|
||||||
string /*pluginKey*/,
|
string /*pluginKey*/,
|
||||||
@@ -124,9 +84,6 @@ export default class Client extends EventEmitter {
|
|||||||
messages: Params[];
|
messages: Params[];
|
||||||
}
|
}
|
||||||
> = {};
|
> = {};
|
||||||
sandyPluginStates = new Map<string /*pluginID*/, _SandyPluginInstance>();
|
|
||||||
private readonly serverAddOnControls: ServerAddOnControls;
|
|
||||||
private readonly flipperServer: FlipperServer;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
id: string,
|
id: string,
|
||||||
@@ -134,36 +91,29 @@ export default class Client extends EventEmitter {
|
|||||||
conn: ClientConnection | null | undefined,
|
conn: ClientConnection | null | undefined,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
store: Store,
|
store: Store,
|
||||||
plugins: Plugins | null | undefined,
|
plugins: Set<string> | null | undefined,
|
||||||
device: BaseDevice,
|
device: BaseDevice,
|
||||||
flipperServer: FlipperServer,
|
flipperServer: FlipperServer,
|
||||||
) {
|
) {
|
||||||
super();
|
super(id, query, conn, logger, plugins, device, flipperServer);
|
||||||
this.connected.set(!!conn);
|
|
||||||
this.plugins = plugins ? plugins : new Set();
|
|
||||||
this.backgroundPlugins = new Set();
|
|
||||||
this.connection = conn;
|
|
||||||
this.id = id;
|
|
||||||
this.query = query;
|
|
||||||
this.sdkVersion = query.sdk_version || 0;
|
|
||||||
this.messageIdCounter = 0;
|
|
||||||
this.logger = logger;
|
|
||||||
this.store = store;
|
this.store = store;
|
||||||
this.broadcastCallbacks = new Map();
|
this.broadcastCallbacks = new Map();
|
||||||
this.activePlugins = new Set();
|
|
||||||
this.device = device;
|
this.on('flipper-debug-message', (message) => {
|
||||||
this.flipperServer = flipperServer;
|
if (isFlipperMessageDebuggingEnabled()) {
|
||||||
this.serverAddOnControls = createServerAddOnControls(this.flipperServer);
|
registerFlipperDebugMessage(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on('bytes-received', (api, bytes) => emitBytesReceived(api, bytes));
|
||||||
|
|
||||||
|
this.on('error', (error) => handleError(this.store, this.device, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
supportsPlugin(pluginId: string): boolean {
|
supportsPlugin(pluginId: string): boolean {
|
||||||
return this.plugins.has(pluginId);
|
return this.plugins.has(pluginId);
|
||||||
}
|
}
|
||||||
|
|
||||||
isBackgroundPlugin(pluginId: string) {
|
|
||||||
return this.backgroundPlugins.has(pluginId);
|
|
||||||
}
|
|
||||||
|
|
||||||
isEnabledPlugin(pluginId: string) {
|
isEnabledPlugin(pluginId: string) {
|
||||||
return this.store
|
return this.store
|
||||||
.getState()
|
.getState()
|
||||||
@@ -177,77 +127,41 @@ export default class Client extends EventEmitter {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async initFromImport(
|
||||||
await this.loadPlugins();
|
initialStates: Record<string, Record<string, any>>,
|
||||||
// if a client arrives before all plugins are loaded, we'll have to wait
|
): Promise<this> {
|
||||||
await waitFor(this.store, (state) => state.plugins.initialized);
|
await Promise.all(
|
||||||
// this starts all sandy enabled plugins
|
[...this.plugins].map(async (pluginId) => {
|
||||||
this.plugins.forEach((pluginId) =>
|
const plugin = await this.getPlugin(pluginId);
|
||||||
this.startPluginIfNeeded(this.getPlugin(pluginId)),
|
|
||||||
);
|
|
||||||
this.backgroundPlugins = new Set(await this.getBackgroundPlugins());
|
|
||||||
this.backgroundPlugins.forEach((plugin) => {
|
|
||||||
if (this.shouldConnectAsBackgroundPlugin(plugin)) {
|
|
||||||
this.initPlugin(plugin);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.emit('plugins-change');
|
|
||||||
}
|
|
||||||
|
|
||||||
initFromImport(initialStates: Record<string, Record<string, any>>): this {
|
|
||||||
this.plugins.forEach((pluginId) => {
|
|
||||||
const plugin = this.getPlugin(pluginId);
|
|
||||||
if (plugin) {
|
if (plugin) {
|
||||||
this.loadPlugin(plugin, initialStates[pluginId]);
|
this.loadPlugin(plugin, initialStates[pluginId]);
|
||||||
}
|
}
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
this.emit('plugins-change');
|
this.emit('plugins-change');
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the supported plugins
|
// get the supported plugins
|
||||||
async loadPlugins(): Promise<Plugins> {
|
async loadPlugins(phase: 'init' | 'refresh'): Promise<Set<string>> {
|
||||||
const {plugins} = await timeout(
|
const plugins = await super.loadPlugins(phase);
|
||||||
30 * 1000,
|
if (phase === 'init') {
|
||||||
this.rawCall<{plugins: Plugins}>('getPlugins', false),
|
// if a client arrives before all plugins are loaded, we'll have to wait
|
||||||
'Fetch plugin timeout for ' + this.id,
|
await waitFor(this.store, (state) => state.plugins.initialized);
|
||||||
);
|
}
|
||||||
this.plugins = new Set(plugins);
|
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPlugin(
|
|
||||||
plugin: _SandyPluginDefinition,
|
|
||||||
initialState?: Record<string, any>,
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
this.sandyPluginStates.set(
|
|
||||||
plugin.id,
|
|
||||||
new _SandyPluginInstance(
|
|
||||||
this.serverAddOnControls,
|
|
||||||
getFlipperLib(),
|
|
||||||
plugin,
|
|
||||||
this,
|
|
||||||
getPluginKey(this.id, {serial: this.query.device_id}, plugin.id),
|
|
||||||
initialState,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to start plugin '${plugin.id}': `, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startPluginIfNeeded(
|
startPluginIfNeeded(
|
||||||
plugin: PluginDefinition | undefined,
|
plugin: _SandyPluginDefinition | undefined,
|
||||||
isEnabled = plugin ? this.isEnabledPlugin(plugin.id) : false,
|
isEnabled = plugin ? this.isEnabledPlugin(plugin.id) : false,
|
||||||
) {
|
) {
|
||||||
// start a plugin on start if it is a SandyPlugin, which is enabled, and doesn't have persisted state yet
|
// start a plugin on start if it is a SandyPlugin, which is enabled, and doesn't have persisted state yet
|
||||||
if (
|
if (
|
||||||
plugin &&
|
plugin &&
|
||||||
(isEnabled || defaultEnabledBackgroundPlugins.includes(plugin.id)) &&
|
(isEnabled || defaultEnabledBackgroundPlugins.includes(plugin.id))
|
||||||
!this.sandyPluginStates.has(plugin.id)
|
|
||||||
) {
|
) {
|
||||||
this.loadPlugin(plugin);
|
super.startPluginIfNeeded(plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,145 +175,27 @@ export default class Client extends EventEmitter {
|
|||||||
pluginId,
|
pluginId,
|
||||||
);
|
);
|
||||||
delete this.messageBuffer[pluginKey];
|
delete this.messageBuffer[pluginKey];
|
||||||
const instance = this.sandyPluginStates.get(pluginId);
|
return super.stopPluginIfNeeded(pluginId, force);
|
||||||
if (instance) {
|
|
||||||
instance.destroy();
|
|
||||||
this.sandyPluginStates.delete(pluginId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// connection lost, but Client might live on
|
|
||||||
disconnect() {
|
|
||||||
this.sandyPluginStates.forEach((instance) => {
|
|
||||||
instance.disconnect();
|
|
||||||
});
|
|
||||||
this.emit('close');
|
|
||||||
this.connected.set(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clean up this client
|
|
||||||
destroy() {
|
|
||||||
this.disconnect();
|
|
||||||
this.plugins.forEach((pluginId) => this.stopPluginIfNeeded(pluginId, true));
|
|
||||||
this.serverAddOnControls.unsubscribe();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets a plugin by pluginId
|
// gets a plugin by pluginId
|
||||||
getPlugin(pluginId: string): PluginDefinition | undefined {
|
protected async getPlugin(
|
||||||
|
pluginId: string,
|
||||||
|
): Promise<_SandyPluginDefinition | undefined> {
|
||||||
const plugins = this.store.getState().plugins;
|
const plugins = this.store.getState().plugins;
|
||||||
return (
|
return (
|
||||||
plugins.clientPlugins.get(pluginId) || plugins.devicePlugins.get(pluginId)
|
plugins.clientPlugins.get(pluginId) || plugins.devicePlugins.get(pluginId)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the supported background plugins
|
|
||||||
async getBackgroundPlugins(): Promise<PluginsArr> {
|
|
||||||
if (this.sdkVersion < 4) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
const data = await timeout(
|
|
||||||
30 * 1000,
|
|
||||||
this.rawCall<{plugins: PluginsArr}>('getBackgroundPlugins', false),
|
|
||||||
'Fetch background plugins timeout for ' + this.id,
|
|
||||||
);
|
|
||||||
return data.plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the plugins, and update the UI
|
|
||||||
async refreshPlugins() {
|
|
||||||
const oldBackgroundPlugins = this.backgroundPlugins;
|
|
||||||
await this.loadPlugins();
|
|
||||||
this.plugins.forEach((pluginId) =>
|
|
||||||
this.startPluginIfNeeded(this.getPlugin(pluginId)),
|
|
||||||
);
|
|
||||||
const newBackgroundPlugins = await this.getBackgroundPlugins();
|
|
||||||
this.backgroundPlugins = new Set(newBackgroundPlugins);
|
|
||||||
// diff the background plugin list, disconnect old, connect new ones
|
|
||||||
oldBackgroundPlugins.forEach((plugin) => {
|
|
||||||
if (
|
|
||||||
!this.backgroundPlugins.has(plugin) &&
|
|
||||||
this.store
|
|
||||||
.getState()
|
|
||||||
.connections.enabledPlugins[this.query.app]?.includes(plugin)
|
|
||||||
) {
|
|
||||||
this.deinitPlugin(plugin);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
newBackgroundPlugins.forEach((plugin) => {
|
|
||||||
if (
|
|
||||||
!oldBackgroundPlugins.has(plugin) &&
|
|
||||||
this.shouldConnectAsBackgroundPlugin(plugin)
|
|
||||||
) {
|
|
||||||
this.initPlugin(plugin);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.emit('plugins-change');
|
|
||||||
}
|
|
||||||
|
|
||||||
onMessage(msg: string) {
|
onMessage(msg: string) {
|
||||||
if (typeof msg !== 'string') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
batch(() => {
|
batch(() => {
|
||||||
let rawData;
|
super.onMessage(msg);
|
||||||
try {
|
|
||||||
rawData = freeze(JSON.parse(msg), true);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`Invalid JSON: ${msg}`, 'clientMessage');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data: {
|
|
||||||
id?: number;
|
|
||||||
method?: string;
|
|
||||||
params?: Params;
|
|
||||||
success?: Object;
|
|
||||||
error?: ClientErrorType;
|
|
||||||
} = rawData;
|
|
||||||
|
|
||||||
const {id, method} = data;
|
|
||||||
|
|
||||||
if (isFlipperMessageDebuggingEnabled()) {
|
|
||||||
registerFlipperDebugMessage({
|
|
||||||
device: this.device?.displayTitle(),
|
|
||||||
app: this.query.app,
|
|
||||||
flipperInternalMethod: method,
|
|
||||||
plugin: data.params?.api,
|
|
||||||
pluginMethod: data.params?.method,
|
|
||||||
payload: data.params?.params,
|
|
||||||
direction: 'toFlipper:message',
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id == null) {
|
protected handleExecuteMessage(params: Params): boolean {
|
||||||
const {error} = data;
|
const persistingPlugin: _SandyPluginDefinition | undefined =
|
||||||
if (error != null) {
|
|
||||||
console.error(
|
|
||||||
`Error received from device ${
|
|
||||||
method ? `when calling ${method}` : ''
|
|
||||||
}: ${error.message} + \nDevice Stack Trace: ${error.stacktrace}`,
|
|
||||||
'deviceError',
|
|
||||||
);
|
|
||||||
handleError(this.store, this.device, error);
|
|
||||||
} else if (method === 'refreshPlugins') {
|
|
||||||
this.refreshPlugins();
|
|
||||||
} else if (method === 'execute') {
|
|
||||||
if (!data.params) {
|
|
||||||
throw new Error('expected params');
|
|
||||||
}
|
|
||||||
const params: Params = data.params;
|
|
||||||
const bytes = msg.length * 2; // string lengths are measured in UTF-16 units (not characters), so 2 bytes per char
|
|
||||||
emitBytesReceived(params.api, bytes);
|
|
||||||
if (bytes > 5 * 1024 * 1024) {
|
|
||||||
console.warn(
|
|
||||||
`Plugin '${params.api}' received excessively large message for '${
|
|
||||||
params.method
|
|
||||||
}': ${Math.round(bytes / 1024)}kB`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const persistingPlugin: PluginDefinition | undefined =
|
|
||||||
this.store.getState().plugins.clientPlugins.get(params.api) ||
|
this.store.getState().plugins.clientPlugins.get(params.api) ||
|
||||||
this.store.getState().plugins.devicePlugins.get(params.api);
|
this.store.getState().plugins.devicePlugins.get(params.api);
|
||||||
|
|
||||||
@@ -437,31 +233,7 @@ export default class Client extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!handled && !isProduction()) {
|
return handled;
|
||||||
console.warn(`Unhandled message ${params.api}.${params.method}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return; // method === 'execute'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onResponse(
|
|
||||||
data: ClientResponseType,
|
|
||||||
resolve: ((a: any) => any) | undefined,
|
|
||||||
reject: (error: ClientErrorType) => any,
|
|
||||||
) {
|
|
||||||
if (data.success) {
|
|
||||||
resolve && resolve(data.success);
|
|
||||||
} else if (data.error) {
|
|
||||||
reject(data.error);
|
|
||||||
const {error} = data;
|
|
||||||
if (error) {
|
|
||||||
handleError(this.store, this.device, error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// ???
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): ClientExport {
|
toJSON(): ClientExport {
|
||||||
@@ -497,82 +269,15 @@ export default class Client extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rawCall<T>(method: string, fromPlugin: boolean, params?: Params): Promise<T> {
|
rawCall<T>(method: string, fromPlugin: boolean, params?: Params): Promise<T> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return super.rawCall<T>(method, fromPlugin, params).catch((error) => {
|
||||||
const id = this.messageIdCounter++;
|
if (error instanceof NoLongerConnectedToClientError) {
|
||||||
const metadata: RequestMetadata = {
|
|
||||||
method,
|
|
||||||
id,
|
|
||||||
params,
|
|
||||||
};
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
id,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
};
|
|
||||||
|
|
||||||
const plugin = params ? params.api : undefined;
|
|
||||||
|
|
||||||
console.debug(data, 'message:call');
|
|
||||||
|
|
||||||
const mark = this.getPerformanceMark(metadata);
|
|
||||||
performance.mark(mark);
|
|
||||||
if (!this.connected.get()) {
|
|
||||||
message.warn({
|
message.warn({
|
||||||
content: 'Not connected',
|
content: 'Not connected',
|
||||||
key: 'appnotconnectedwarning',
|
key: 'appnotconnectedwarning',
|
||||||
duration: 0.5,
|
duration: 0.5,
|
||||||
});
|
});
|
||||||
reject(new NoLongerConnectedToClientError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!fromPlugin || this.isAcceptingMessagesFromPlugin(plugin)) {
|
|
||||||
try {
|
|
||||||
const response = await this.connection!.sendExpectResponse(data);
|
|
||||||
if (!fromPlugin || this.isAcceptingMessagesFromPlugin(plugin)) {
|
|
||||||
const logEventName = this.getLogEventName(data);
|
|
||||||
this.logger.trackTimeSince(mark, logEventName);
|
|
||||||
emitBytesReceived(plugin || 'unknown', response.length * 2);
|
|
||||||
|
|
||||||
this.onResponse(response, resolve, reject);
|
|
||||||
|
|
||||||
if (isFlipperMessageDebuggingEnabled()) {
|
|
||||||
registerFlipperDebugMessage({
|
|
||||||
device: this.device?.displayTitle(),
|
|
||||||
app: this.query.app,
|
|
||||||
flipperInternalMethod: method,
|
|
||||||
payload: response,
|
|
||||||
plugin,
|
|
||||||
pluginMethod: params?.method,
|
|
||||||
direction: 'toFlipper:response',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// This is only called if the connection is dead. Not in expected
|
|
||||||
// and recoverable cases like a missing receiver/method.
|
|
||||||
this.disconnect();
|
|
||||||
reject(new Error('Unable to send, connection error: ' + error));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reject(
|
|
||||||
new Error(
|
|
||||||
`Cannot send ${method}, client is not accepting messages for plugin ${plugin}`,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isFlipperMessageDebuggingEnabled()) {
|
|
||||||
registerFlipperDebugMessage({
|
|
||||||
device: this.device?.displayTitle(),
|
|
||||||
app: this.query.app,
|
|
||||||
flipperInternalMethod: method,
|
|
||||||
plugin: params?.api,
|
|
||||||
pluginMethod: params?.method,
|
|
||||||
payload: params?.params,
|
|
||||||
direction: 'toClient:call',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
throw error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,118 +310,4 @@ export default class Client extends EventEmitter {
|
|||||||
const logEventName = this.getLogEventName(data);
|
const logEventName = this.getLogEventName(data);
|
||||||
this.logger.trackTimeSince(mark, logEventName);
|
this.logger.trackTimeSince(mark, logEventName);
|
||||||
}
|
}
|
||||||
|
|
||||||
isAcceptingMessagesFromPlugin(plugin: string | null | undefined) {
|
|
||||||
return this.connection && (!plugin || this.activePlugins.has(plugin));
|
|
||||||
}
|
|
||||||
|
|
||||||
getPerformanceMark(data: RequestMetadata): string {
|
|
||||||
const {method, id} = data;
|
|
||||||
return `request_response_${method}_${id}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLogEventName(data: RequestMetadata): string {
|
|
||||||
const {method, params} = data;
|
|
||||||
return params && params.api && params.method
|
|
||||||
? `request_response_${method}_${params.api}_${params.method}`
|
|
||||||
: `request_response_${method}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
initPlugin(pluginId: string) {
|
|
||||||
this.activePlugins.add(pluginId);
|
|
||||||
const instance = this.sandyPluginStates.get(pluginId);
|
|
||||||
if (this.connected.get() && instance) {
|
|
||||||
this.rawSend('init', {plugin: pluginId});
|
|
||||||
instance.connect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deinitPlugin(pluginId: string) {
|
|
||||||
this.activePlugins.delete(pluginId);
|
|
||||||
const instance = this.sandyPluginStates.get(pluginId);
|
|
||||||
instance?.disconnect();
|
|
||||||
if (this.connected.get() && instance) {
|
|
||||||
this.rawSend('deinit', {plugin: pluginId});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rawSend(method: string, params?: Object): void {
|
|
||||||
const data = {
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
};
|
|
||||||
console.debug(data, 'message:send');
|
|
||||||
if (this.connection) {
|
|
||||||
this.connection.send(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isFlipperMessageDebuggingEnabled()) {
|
|
||||||
registerFlipperDebugMessage({
|
|
||||||
device: this.device?.displayTitle(),
|
|
||||||
app: this.query.app,
|
|
||||||
flipperInternalMethod: method,
|
|
||||||
payload: params,
|
|
||||||
direction: 'toClient:send',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
call(
|
|
||||||
api: string,
|
|
||||||
method: string,
|
|
||||||
fromPlugin: boolean,
|
|
||||||
params?: Object,
|
|
||||||
): Promise<Object> {
|
|
||||||
return reportPluginFailures(
|
|
||||||
this.rawCall<Object>('execute', fromPlugin, {
|
|
||||||
api,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
}).catch((err: Error) => {
|
|
||||||
// We only throw errors if the connection is still alive
|
|
||||||
// as connection-related ones aren't recoverable from
|
|
||||||
// user code.
|
|
||||||
if (this.connected.get()) {
|
|
||||||
// This is a special case where we a send failed because of
|
|
||||||
// a disconnect "mid-air". This can happen, for instance,
|
|
||||||
// when you pull the plug from a connected phone. We can
|
|
||||||
// still handle this gracefully.
|
|
||||||
if (err.toString().includes('Socket closed unexpectedly')) {
|
|
||||||
console.warn(
|
|
||||||
`Failed to call device due to unexpected disconnect: ${err}`,
|
|
||||||
);
|
|
||||||
this.disconnect();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
// This effectively preserves the previous behavior
|
|
||||||
// of ignoring disconnection-related call failures.
|
|
||||||
return {};
|
|
||||||
}),
|
|
||||||
`Call-${method}`,
|
|
||||||
api,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
send(api: string, method: string, params?: Object): void {
|
|
||||||
if (!isProduction()) {
|
|
||||||
console.warn(
|
|
||||||
`${api}:${
|
|
||||||
method || ''
|
|
||||||
} client.send() is deprecated. Please use call() instead so you can handle errors.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return this.rawSend('execute', {api, method, params});
|
|
||||||
}
|
|
||||||
|
|
||||||
async supportsMethod(api: string, method: string): Promise<boolean> {
|
|
||||||
const response = await this.rawCall<{
|
|
||||||
isSupported: boolean;
|
|
||||||
}>('isMethodSupported', true, {
|
|
||||||
api,
|
|
||||||
method,
|
|
||||||
});
|
|
||||||
return response.isSupported;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,9 @@ test.skip('PluginContainer can render Sandy plugins', async () => {
|
|||||||
const {renderer, act, sendMessage, client, store} =
|
const {renderer, act, sendMessage, client, store} =
|
||||||
await renderMockFlipperWithPlugin(definition);
|
await renderMockFlipperWithPlugin(definition);
|
||||||
|
|
||||||
expect(client.rawSend).toBeCalledWith('init', {plugin: 'TestPlugin'});
|
expect((client as any).rawSend).toBeCalledWith('init', {
|
||||||
|
plugin: 'TestPlugin',
|
||||||
|
});
|
||||||
|
|
||||||
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
||||||
<body>
|
<body>
|
||||||
@@ -260,7 +262,9 @@ test.skip('PluginContainer can render Sandy plugins', async () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(client.rawSend).toBeCalledWith('deinit', {plugin: 'TestPlugin'});
|
expect((client as any).rawSend).toBeCalledWith('deinit', {
|
||||||
|
plugin: 'TestPlugin',
|
||||||
|
});
|
||||||
|
|
||||||
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
||||||
<body>
|
<body>
|
||||||
@@ -326,7 +330,9 @@ test.skip('PluginContainer can render Sandy plugins', async () => {
|
|||||||
expect(pluginInstance.disconnectedStub).toBeCalledTimes(1);
|
expect(pluginInstance.disconnectedStub).toBeCalledTimes(1);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
||||||
expect(pluginInstance.deactivatedStub).toBeCalledTimes(1);
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(1);
|
||||||
expect(client.rawSend).toBeCalledWith('init', {plugin: 'TestPlugin'});
|
expect((client as any).rawSend).toBeCalledWith('init', {
|
||||||
|
plugin: 'TestPlugin',
|
||||||
|
});
|
||||||
|
|
||||||
// disable
|
// disable
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -341,7 +347,9 @@ test.skip('PluginContainer can render Sandy plugins', async () => {
|
|||||||
expect(pluginInstance.disconnectedStub).toBeCalledTimes(2);
|
expect(pluginInstance.disconnectedStub).toBeCalledTimes(2);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
||||||
expect(pluginInstance.deactivatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(2);
|
||||||
expect(client.rawSend).toBeCalledWith('deinit', {plugin: 'TestPlugin'});
|
expect((client as any).rawSend).toBeCalledWith('deinit', {
|
||||||
|
plugin: 'TestPlugin',
|
||||||
|
});
|
||||||
|
|
||||||
// re-enable
|
// re-enable
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -365,7 +373,9 @@ test.skip('PluginContainer can render Sandy plugins', async () => {
|
|||||||
client.sandyPluginStates.get('TestPlugin')!.instanceApi;
|
client.sandyPluginStates.get('TestPlugin')!.instanceApi;
|
||||||
expect(newPluginInstance).not.toBe(pluginInstance);
|
expect(newPluginInstance).not.toBe(pluginInstance);
|
||||||
expect(newPluginInstance.connectedStub).toBeCalledTimes(1);
|
expect(newPluginInstance.connectedStub).toBeCalledTimes(1);
|
||||||
expect(client.rawSend).toBeCalledWith('init', {plugin: 'TestPlugin'});
|
expect((client as any).rawSend).toBeCalledWith('init', {
|
||||||
|
plugin: 'TestPlugin',
|
||||||
|
});
|
||||||
expect(newPluginInstance.count.get()).toBe(0);
|
expect(newPluginInstance.count.get()).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -401,8 +411,10 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(client.rawSend).toBeCalledWith('init', {plugin: 'TestPlugin'});
|
expect((client as any).rawSend).toBeCalledWith('init', {
|
||||||
(client.rawSend as jest.Mock).mockClear();
|
plugin: 'TestPlugin',
|
||||||
|
});
|
||||||
|
((client as any).rawSend as jest.Mock).mockClear();
|
||||||
// make sure the plugin gets connected
|
// make sure the plugin gets connected
|
||||||
const pluginInstance: ReturnType<typeof plugin> =
|
const pluginInstance: ReturnType<typeof plugin> =
|
||||||
client.sandyPluginStates.get(definition.id)!.instanceApi;
|
client.sandyPluginStates.get(definition.id)!.instanceApi;
|
||||||
@@ -423,8 +435,8 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
// bg plugin!
|
// bg plugin!
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
(client.rawSend as jest.Mock).mockClear();
|
((client as any).rawSend as jest.Mock).mockClear();
|
||||||
expect(pluginInstance.connectedStub).toBeCalledTimes(1);
|
expect(pluginInstance.connectedStub).toBeCalledTimes(1);
|
||||||
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(1);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(1);
|
||||||
@@ -445,8 +457,8 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
||||||
expect(pluginInstance.deactivatedStub).toBeCalledTimes(1);
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(1);
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
(client.rawSend as jest.Mock).mockClear();
|
((client as any).rawSend as jest.Mock).mockClear();
|
||||||
|
|
||||||
// disable
|
// disable
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -461,8 +473,10 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
expect(pluginInstance.disconnectedStub).toBeCalledTimes(1);
|
expect(pluginInstance.disconnectedStub).toBeCalledTimes(1);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
||||||
expect(pluginInstance.deactivatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(2);
|
||||||
expect(client.rawSend).toBeCalledWith('deinit', {plugin: 'TestPlugin'});
|
expect((client as any).rawSend).toBeCalledWith('deinit', {
|
||||||
(client.rawSend as jest.Mock).mockClear();
|
plugin: 'TestPlugin',
|
||||||
|
});
|
||||||
|
((client as any).rawSend as jest.Mock).mockClear();
|
||||||
|
|
||||||
// select something else
|
// select something else
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -499,8 +513,10 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
expect(newPluginInstance.disconnectedStub).toBeCalledTimes(0);
|
expect(newPluginInstance.disconnectedStub).toBeCalledTimes(0);
|
||||||
expect(newPluginInstance.activatedStub).toBeCalledTimes(0);
|
expect(newPluginInstance.activatedStub).toBeCalledTimes(0);
|
||||||
expect(newPluginInstance.deactivatedStub).toBeCalledTimes(0);
|
expect(newPluginInstance.deactivatedStub).toBeCalledTimes(0);
|
||||||
expect(client.rawSend).toBeCalledWith('init', {plugin: 'TestPlugin'});
|
expect((client as any).rawSend).toBeCalledWith('init', {
|
||||||
(client.rawSend as jest.Mock).mockClear();
|
plugin: 'TestPlugin',
|
||||||
|
});
|
||||||
|
((client as any).rawSend as jest.Mock).mockClear();
|
||||||
|
|
||||||
// select new plugin
|
// select new plugin
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -517,8 +533,8 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
expect(newPluginInstance.disconnectedStub).toBeCalledTimes(0);
|
expect(newPluginInstance.disconnectedStub).toBeCalledTimes(0);
|
||||||
expect(newPluginInstance.activatedStub).toBeCalledTimes(1);
|
expect(newPluginInstance.activatedStub).toBeCalledTimes(1);
|
||||||
expect(newPluginInstance.deactivatedStub).toBeCalledTimes(0);
|
expect(newPluginInstance.deactivatedStub).toBeCalledTimes(0);
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
(client.rawSend as jest.Mock).mockClear();
|
((client as any).rawSend as jest.Mock).mockClear();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
||||||
@@ -555,7 +571,9 @@ test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
|||||||
definition,
|
definition,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(client.rawSend).toBeCalledWith('init', {plugin: 'TestPlugin'});
|
expect((client as any).rawSend).toBeCalledWith('init', {
|
||||||
|
plugin: 'TestPlugin',
|
||||||
|
});
|
||||||
|
|
||||||
expect(linksSeen).toEqual([]);
|
expect(linksSeen).toEqual([]);
|
||||||
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
||||||
@@ -1242,7 +1260,7 @@ test('PluginContainer can render Sandy plugins for archived devices', async () =
|
|||||||
{archivedDevice: true},
|
{archivedDevice: true},
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
|
|
||||||
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
||||||
<body>
|
<body>
|
||||||
@@ -1296,7 +1314,7 @@ test('PluginContainer can render Sandy plugins for archived devices', async () =
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
|
|
||||||
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
||||||
<body>
|
<body>
|
||||||
@@ -1359,7 +1377,7 @@ test('PluginContainer can render Sandy plugins for archived devices', async () =
|
|||||||
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
||||||
expect(pluginInstance.deactivatedStub).toBeCalledTimes(1);
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(1);
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('PluginContainer triggers correct lifecycles for background plugin', async () => {
|
test('PluginContainer triggers correct lifecycles for background plugin', async () => {
|
||||||
@@ -1397,7 +1415,7 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
// make sure the plugin gets connected
|
// make sure the plugin gets connected
|
||||||
const pluginInstance: ReturnType<typeof plugin> =
|
const pluginInstance: ReturnType<typeof plugin> =
|
||||||
client.sandyPluginStates.get(definition.id)!.instanceApi;
|
client.sandyPluginStates.get(definition.id)!.instanceApi;
|
||||||
@@ -1418,7 +1436,7 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
// bg plugin!
|
// bg plugin!
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
expect(pluginInstance.connectedStub).toBeCalledTimes(0);
|
expect(pluginInstance.connectedStub).toBeCalledTimes(0);
|
||||||
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(1);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(1);
|
||||||
@@ -1439,7 +1457,7 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
||||||
expect(pluginInstance.deactivatedStub).toBeCalledTimes(1);
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(1);
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
|
|
||||||
// select something else
|
// select something else
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -1466,5 +1484,5 @@ test('PluginContainer triggers correct lifecycles for background plugin', async
|
|||||||
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
expect(pluginInstance.disconnectedStub).toBeCalledTimes(0);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(3);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(3);
|
||||||
expect(pluginInstance.deactivatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(2);
|
||||||
expect(client.rawSend).not.toBeCalled();
|
expect((client as any).rawSend).not.toBeCalled();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {createStore} from 'redux';
|
|||||||
import BaseDevice from '../../devices/BaseDevice';
|
import BaseDevice from '../../devices/BaseDevice';
|
||||||
import {createRootReducer} from '../../reducers';
|
import {createRootReducer} from '../../reducers';
|
||||||
import {Store} from '../../reducers/index';
|
import {Store} from '../../reducers/index';
|
||||||
import Client, {ClientConnection} from '../../Client';
|
import Client from '../../Client';
|
||||||
import {
|
import {
|
||||||
Logger,
|
Logger,
|
||||||
buildClientId,
|
buildClientId,
|
||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
import {PluginDefinition} from '../../plugin';
|
import {PluginDefinition} from '../../plugin';
|
||||||
import {pluginsInitialized, registerPlugins} from '../../reducers/plugins';
|
import {pluginsInitialized, registerPlugins} from '../../reducers/plugins';
|
||||||
import {getLogger} from 'flipper-common';
|
import {getLogger} from 'flipper-common';
|
||||||
|
import {ClientConnection} from 'flipper-frontend-core';
|
||||||
import {initializeFlipperLibImplementation} from '../../utils/flipperLibImplementation';
|
import {initializeFlipperLibImplementation} from '../../utils/flipperLibImplementation';
|
||||||
import pluginManager from '../../dispatcher/pluginManager';
|
import pluginManager from '../../dispatcher/pluginManager';
|
||||||
import {PluginDetails} from 'flipper-common';
|
import {PluginDetails} from 'flipper-common';
|
||||||
@@ -197,6 +198,8 @@ export default class MockFlipper {
|
|||||||
this._logger,
|
this._logger,
|
||||||
this._store,
|
this._store,
|
||||||
new Set(supportedPlugins),
|
new Set(supportedPlugins),
|
||||||
|
// TODO: Remove after migration
|
||||||
|
// @ts-expect-error
|
||||||
device,
|
device,
|
||||||
this.flipperServer,
|
this.flipperServer,
|
||||||
);
|
);
|
||||||
@@ -225,7 +228,7 @@ export default class MockFlipper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
client.rawSend = jest.fn();
|
(client as any).rawSend = jest.fn();
|
||||||
if (!device.isArchived) {
|
if (!device.isArchived) {
|
||||||
await client.init();
|
await client.init();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -101,12 +101,16 @@ export async function handleDeeplink(
|
|||||||
const selectedClient = getAllClients(store.getState().connections).find(
|
const selectedClient = getAllClients(store.getState().connections).find(
|
||||||
(c) =>
|
(c) =>
|
||||||
c.query.app === match[0] &&
|
c.query.app === match[0] &&
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
(selectedDevice == null || c.device === selectedDevice),
|
(selectedDevice == null || c.device === selectedDevice),
|
||||||
);
|
);
|
||||||
|
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
selectPlugin({
|
selectPlugin({
|
||||||
selectedAppId: selectedClient?.id,
|
selectedAppId: selectedClient?.id,
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
selectedDevice: selectedClient ? selectedClient.device : selectedDevice,
|
selectedDevice: selectedClient ? selectedClient.device : selectedDevice,
|
||||||
selectedPlugin: match[1],
|
selectedPlugin: match[1],
|
||||||
deepLinkPayload,
|
deepLinkPayload,
|
||||||
|
|||||||
@@ -300,6 +300,8 @@ export async function handleClientConnected(
|
|||||||
logger,
|
logger,
|
||||||
store,
|
store,
|
||||||
undefined,
|
undefined,
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device,
|
device,
|
||||||
server,
|
server,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ export async function handleOpenPluginDeeplink(
|
|||||||
const client: Client | undefined = isDevicePlugin
|
const client: Client | undefined = isDevicePlugin
|
||||||
? undefined
|
? undefined
|
||||||
: (deviceOrClient as Client);
|
: (deviceOrClient as Client);
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
const device: BaseDevice = isDevicePlugin
|
const device: BaseDevice = isDevicePlugin
|
||||||
? (deviceOrClient as BaseDevice)
|
? (deviceOrClient as BaseDevice)
|
||||||
: (deviceOrClient as Client).device;
|
: (deviceOrClient as Client).device;
|
||||||
@@ -507,6 +509,8 @@ async function selectDevicesAndClient(
|
|||||||
: c.plugins.has(params.pluginId),
|
: c.plugins.has(params.pluginId),
|
||||||
)
|
)
|
||||||
.filter((c) => c.connected.get())
|
.filter((c) => c.connected.get())
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
.filter((c) => availableDevices.includes(c.device));
|
.filter((c) => availableDevices.includes(c.device));
|
||||||
|
|
||||||
if (validClients.length === 1) {
|
if (validClients.length === 1) {
|
||||||
|
|||||||
@@ -243,11 +243,15 @@ export default (state: State = INITAL_STATE, action: Actions): State => {
|
|||||||
selectedAppId =
|
selectedAppId =
|
||||||
getAllClients(state).find(
|
getAllClients(state).find(
|
||||||
(c) =>
|
(c) =>
|
||||||
|
// TODO: Remove after migration
|
||||||
|
// @ts-expect-error
|
||||||
c.device === payload && c.query.app === state.userPreferredApp,
|
c.device === payload && c.query.app === state.userPreferredApp,
|
||||||
)?.id ?? null;
|
)?.id ?? null;
|
||||||
// nothing found, try first app if any
|
// nothing found, try first app if any
|
||||||
if (!selectedAppId) {
|
if (!selectedAppId) {
|
||||||
selectedAppId =
|
selectedAppId =
|
||||||
|
// TODO: Remove after migration
|
||||||
|
// @ts-expect-error
|
||||||
getAllClients(state).find((c) => c.device === payload)?.id ?? null;
|
getAllClients(state).find((c) => c.device === payload)?.id ?? null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,7 +284,11 @@ export default (state: State = INITAL_STATE, action: Actions): State => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
staticView: null,
|
staticView: null,
|
||||||
|
// TODO: Remove after migration
|
||||||
|
// @ts-expect-error
|
||||||
selectedDevice: device,
|
selectedDevice: device,
|
||||||
|
// TODO: Remove after migration
|
||||||
|
// @ts-expect-error
|
||||||
userPreferredDevice: canBeDefaultDevice(device)
|
userPreferredDevice: canBeDefaultDevice(device)
|
||||||
? device.title
|
? device.title
|
||||||
: state.userPreferredDevice,
|
: state.userPreferredDevice,
|
||||||
@@ -337,6 +345,8 @@ export default (state: State = INITAL_STATE, action: Actions): State => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
selectedAppId: payload,
|
selectedAppId: payload,
|
||||||
|
// TODO: Remove after migration
|
||||||
|
// @ts-expect-error
|
||||||
selectedDevice: client.device,
|
selectedDevice: client.device,
|
||||||
userPreferredDevice: client.device.title,
|
userPreferredDevice: client.device.title,
|
||||||
userPreferredApp: client.query.app,
|
userPreferredApp: client.query.app,
|
||||||
|
|||||||
@@ -311,6 +311,8 @@ export function openNotification(store: Store, noti: PluginNotificationOrig) {
|
|||||||
selectPlugin({
|
selectPlugin({
|
||||||
selectedPlugin: noti.pluginId,
|
selectedPlugin: noti.pluginId,
|
||||||
selectedAppId: client.id,
|
selectedAppId: client.id,
|
||||||
|
// TODO: Will be fixed later in the stack
|
||||||
|
// @ts-expect-error
|
||||||
selectedDevice: client.device,
|
selectedDevice: client.device,
|
||||||
deepLinkPayload: noti.notification.action,
|
deepLinkPayload: noti.notification.action,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ export const getActiveDevice = createSelector(
|
|||||||
}
|
}
|
||||||
// if there is an active app, use device owning the app
|
// if there is an active app, use device owning the app
|
||||||
if (client) {
|
if (client) {
|
||||||
return client.device;
|
// TODO: Will be fixed later in the stack
|
||||||
|
return client.device as any;
|
||||||
}
|
}
|
||||||
return selectedDevice;
|
return selectedDevice;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -733,6 +733,8 @@ test('test determinePluginsToProcess for mutilple clients having plugins present
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestPlugin', 'TestDevicePlugin']),
|
new Set(['TestPlugin', 'TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -748,6 +750,8 @@ test('test determinePluginsToProcess for mutilple clients having plugins present
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestDevicePlugin']),
|
new Set(['TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -763,6 +767,8 @@ test('test determinePluginsToProcess for mutilple clients having plugins present
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestPlugin', 'TestDevicePlugin']),
|
new Set(['TestPlugin', 'TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -823,6 +829,8 @@ test('test determinePluginsToProcess for no selected plugin present in any clien
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestPlugin', 'TestDevicePlugin']),
|
new Set(['TestPlugin', 'TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -838,6 +846,8 @@ test('test determinePluginsToProcess for no selected plugin present in any clien
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestDevicePlugin']),
|
new Set(['TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -881,6 +891,8 @@ test('test determinePluginsToProcess for multiple clients on same device', async
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestPlugin', 'TestDevicePlugin']),
|
new Set(['TestPlugin', 'TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -896,6 +908,8 @@ test('test determinePluginsToProcess for multiple clients on same device', async
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestDevicePlugin']),
|
new Set(['TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -944,6 +958,8 @@ test('test determinePluginsToProcess for multiple clients on different device',
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestPlugin', 'TestDevicePlugin']),
|
new Set(['TestPlugin', 'TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -959,6 +975,8 @@ test('test determinePluginsToProcess for multiple clients on different device',
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestDevicePlugin']),
|
new Set(['TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -974,6 +992,8 @@ test('test determinePluginsToProcess for multiple clients on different device',
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestPlugin', 'TestDevicePlugin']),
|
new Set(['TestPlugin', 'TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -989,6 +1009,8 @@ test('test determinePluginsToProcess for multiple clients on different device',
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestDevicePlugin']),
|
new Set(['TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
device1,
|
device1,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -1061,6 +1083,8 @@ test('test determinePluginsToProcess to ignore archived clients', async () => {
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestPlugin', 'TestDevicePlugin']),
|
new Set(['TestPlugin', 'TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
archivedDevice,
|
archivedDevice,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
@@ -1076,6 +1100,8 @@ test('test determinePluginsToProcess to ignore archived clients', async () => {
|
|||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
new Set(['TestPlugin', 'TestDevicePlugin']),
|
new Set(['TestPlugin', 'TestDevicePlugin']),
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
archivedDevice,
|
archivedDevice,
|
||||||
flipperServer,
|
flipperServer,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {getAppVersion} from './info';
|
|||||||
import {pluginKey} from '../utils/pluginKey';
|
import {pluginKey} from '../utils/pluginKey';
|
||||||
import {DevicePluginMap, ClientPluginMap} from '../plugin';
|
import {DevicePluginMap, ClientPluginMap} from '../plugin';
|
||||||
import {default as BaseDevice} from '../devices/BaseDevice';
|
import {default as BaseDevice} from '../devices/BaseDevice';
|
||||||
import {default as ArchivedDevice} from '../devices/ArchivedDevice';
|
import {ArchivedDevice} from 'flipper-frontend-core';
|
||||||
import {v4 as uuidv4} from 'uuid';
|
import {v4 as uuidv4} from 'uuid';
|
||||||
import {tryCatchReportPlatformFailures} from 'flipper-common';
|
import {tryCatchReportPlatformFailures} from 'flipper-common';
|
||||||
import {TestIdler} from './Idler';
|
import {TestIdler} from './Idler';
|
||||||
@@ -512,7 +512,11 @@ export const exportStoreToFile = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function importDataToStore(source: string, data: string, store: Store) {
|
export async function importDataToStore(
|
||||||
|
source: string,
|
||||||
|
data: string,
|
||||||
|
store: Store,
|
||||||
|
) {
|
||||||
getLogger().track('usage', IMPORT_FLIPPER_TRACE_EVENT);
|
getLogger().track('usage', IMPORT_FLIPPER_TRACE_EVENT);
|
||||||
const json: ExportType = JSON.parse(data);
|
const json: ExportType = JSON.parse(data);
|
||||||
const {device, clients, deviceScreenshot} = json;
|
const {device, clients, deviceScreenshot} = json;
|
||||||
@@ -536,19 +540,22 @@ export function importDataToStore(source: string, data: string, store: Store) {
|
|||||||
);
|
);
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
type: 'REGISTER_DEVICE',
|
type: 'REGISTER_DEVICE',
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
payload: archivedDevice,
|
payload: archivedDevice,
|
||||||
});
|
});
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
type: 'SELECT_DEVICE',
|
type: 'SELECT_DEVICE',
|
||||||
|
// TODO: Remove at the end of migration
|
||||||
|
// @ts-expect-error
|
||||||
payload: archivedDevice,
|
payload: archivedDevice,
|
||||||
});
|
});
|
||||||
|
|
||||||
clients.forEach((client: {id: string; query: ClientQuery}) => {
|
await Promise.all(
|
||||||
|
clients.map(async (client: {id: string; query: ClientQuery}) => {
|
||||||
const sandyPluginStates = json.pluginStates2[client.id] || {};
|
const sandyPluginStates = json.pluginStates2[client.id] || {};
|
||||||
const clientPlugins = new Set(Object.keys(sandyPluginStates));
|
const clientPlugins = new Set(Object.keys(sandyPluginStates));
|
||||||
store.dispatch({
|
const clientInstance = await new Client(
|
||||||
type: 'NEW_CLIENT',
|
|
||||||
payload: new Client(
|
|
||||||
client.id,
|
client.id,
|
||||||
client.query,
|
client.query,
|
||||||
null,
|
null,
|
||||||
@@ -557,9 +564,13 @@ export function importDataToStore(source: string, data: string, store: Store) {
|
|||||||
clientPlugins,
|
clientPlugins,
|
||||||
archivedDevice,
|
archivedDevice,
|
||||||
getRenderHostInstance().flipperServer,
|
getRenderHostInstance().flipperServer,
|
||||||
).initFromImport(sandyPluginStates),
|
).initFromImport(sandyPluginStates);
|
||||||
});
|
store.dispatch({
|
||||||
|
type: 'NEW_CLIENT',
|
||||||
|
payload: clientInstance,
|
||||||
});
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const importFileToStore = async (file: string, store: Store) => {
|
export const importFileToStore = async (file: string, store: Store) => {
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
{
|
{
|
||||||
"path": "../flipper-common"
|
"path": "../flipper-common"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "../flipper-frontend-core"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "../flipper-plugin"
|
"path": "../flipper-plugin"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ module.exports = {
|
|||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'^flipper$': '<rootDir>/app/src',
|
'^flipper$': '<rootDir>/app/src',
|
||||||
'^flipper-plugin$': '<rootDir>/flipper-plugin/src',
|
'^flipper-plugin$': '<rootDir>/flipper-plugin/src',
|
||||||
'^flipper-(server-core|ui-core|common)$': '<rootDir>/flipper-$1/src',
|
'^flipper-(server-core|ui-core|frontend-core|common)$':
|
||||||
|
'<rootDir>/flipper-$1/src',
|
||||||
'^flipper-(pkg|pkg-lib|doctor|test-utils)$': '<rootDir>/$1/src',
|
'^flipper-(pkg|pkg-lib|doctor|test-utils)$': '<rootDir>/$1/src',
|
||||||
},
|
},
|
||||||
clearMocks: true,
|
clearMocks: true,
|
||||||
|
|||||||
@@ -258,6 +258,7 @@ export default class LayoutPlugin extends FlipperPlugin<
|
|||||||
if (this.props.isArchivedDevice) {
|
if (this.props.isArchivedDevice) {
|
||||||
Promise.resolve(this.device)
|
Promise.resolve(this.device)
|
||||||
.then((d) => {
|
.then((d) => {
|
||||||
|
// @ts-expect-error
|
||||||
const handle = (d as ArchivedDevice).getArchivedScreenshotHandle();
|
const handle = (d as ArchivedDevice).getArchivedScreenshotHandle();
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
throw new Error('No screenshot attached.');
|
throw new Error('No screenshot attached.');
|
||||||
|
|||||||
@@ -4035,14 +4035,6 @@ aggregate-error@^3.0.0:
|
|||||||
clean-stack "^2.0.0"
|
clean-stack "^2.0.0"
|
||||||
indent-string "^4.0.0"
|
indent-string "^4.0.0"
|
||||||
|
|
||||||
aggregate-error@^4.0.0:
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-4.0.0.tgz#83dbdb53a0d500721281d22e19eee9bc352a89cd"
|
|
||||||
integrity sha512-8DGp7zUt1E9k0NE2q4jlXHk+V3ORErmwolEdRz9iV+LKJ40WhMHh92cxAvhqV2I+zEn/gotIoqoMs0NjF3xofg==
|
|
||||||
dependencies:
|
|
||||||
clean-stack "^4.0.0"
|
|
||||||
indent-string "^5.0.0"
|
|
||||||
|
|
||||||
ajv-errors@^1.0.1:
|
ajv-errors@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
|
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
|
||||||
@@ -5340,13 +5332,6 @@ clean-stack@^3.0.0, clean-stack@^3.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
escape-string-regexp "4.0.0"
|
escape-string-regexp "4.0.0"
|
||||||
|
|
||||||
clean-stack@^4.0.0:
|
|
||||||
version "4.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-4.1.0.tgz#5ce5a2fd19a12aecdce8570daefddb7ac94b6b4e"
|
|
||||||
integrity sha512-dxXQYI7mfQVcaF12s6sjNFoZ6ZPDQuBBLp3QJ5156k9EvUFClUoZ11fo8HnLQO241DDVntHEug8MOuFO5PSfRg==
|
|
||||||
dependencies:
|
|
||||||
escape-string-regexp "5.0.0"
|
|
||||||
|
|
||||||
cli-boxes@^2.2.1:
|
cli-boxes@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
|
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
|
||||||
@@ -6662,11 +6647,6 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||||
|
|
||||||
escape-string-regexp@5.0.0:
|
|
||||||
version "5.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8"
|
|
||||||
integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==
|
|
||||||
|
|
||||||
escape-string-regexp@^1.0.5:
|
escape-string-regexp@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
@@ -8211,11 +8191,6 @@ indent-string@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||||
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
|
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
|
||||||
|
|
||||||
indent-string@^5.0.0:
|
|
||||||
version "5.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5"
|
|
||||||
integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==
|
|
||||||
|
|
||||||
inflight@^1.0.4:
|
inflight@^1.0.4:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||||
@@ -11256,13 +11231,6 @@ p-map@^4.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
aggregate-error "^3.0.0"
|
aggregate-error "^3.0.0"
|
||||||
|
|
||||||
p-map@^5.3.0:
|
|
||||||
version "5.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/p-map/-/p-map-5.3.0.tgz#2204823bc9f37f17ddc9e7f446293c4530b8a4cf"
|
|
||||||
integrity sha512-SRbIQFoLYNezHkqZslqeg963HYUtqOrfMCxjNrFOpJ19WTYuq26rQoOXeX8QQiMLUlLqdYV/7PuDsdYJ7hLE1w==
|
|
||||||
dependencies:
|
|
||||||
aggregate-error "^4.0.0"
|
|
||||||
|
|
||||||
p-try@^1.0.0:
|
p-try@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
||||||
|
|||||||
Reference in New Issue
Block a user