Introduce isPluginAvailable and selectPlugin
Summary: Introduced API to replace the deprecated `selectPlugin` in Sandy. The API can be used to navigate from `device plugin -> device plugin`, or` client plugin -> device / client plugin` Introduced `isPluginAvailable` as well, so that the user interaction an be fine tuned in case the plugin is not disabled. Reviewed By: jknoxville Differential Revision: D25422370 fbshipit-source-id: c6c603f1c68e6291280b3d0883e474448754ded1
This commit is contained in:
committed by
Facebook GitHub Bot
parent
02a56da3f5
commit
52862f6083
@@ -876,3 +876,128 @@ test('PluginContainer + Sandy device plugin supports deeplink', async () => {
|
|||||||
});
|
});
|
||||||
expect(linksSeen).toEqual([theUniverse, 'london!', 'london!']);
|
expect(linksSeen).toEqual([theUniverse, 'london!', 'london!']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Sandy plugins support isPluginSupported + selectPlugin', async () => {
|
||||||
|
let renders = 0;
|
||||||
|
const linksSeen: any[] = [];
|
||||||
|
|
||||||
|
function MySandyPlugin() {
|
||||||
|
renders++;
|
||||||
|
return <h1>Plugin1</h1>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const plugin = (client: PluginClient) => {
|
||||||
|
const activatedStub = jest.fn();
|
||||||
|
const deactivatedStub = jest.fn();
|
||||||
|
client.onDeepLink((link) => {
|
||||||
|
linksSeen.push(link);
|
||||||
|
});
|
||||||
|
client.onActivate(activatedStub);
|
||||||
|
client.onDeactivate(deactivatedStub);
|
||||||
|
return {
|
||||||
|
activatedStub,
|
||||||
|
deactivatedStub,
|
||||||
|
isPluginAvailable: client.isPluginAvailable,
|
||||||
|
selectPlugin: client.selectPlugin,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const definition = new _SandyPluginDefinition(
|
||||||
|
TestUtils.createMockPluginDetails({id: 'base'}),
|
||||||
|
{
|
||||||
|
plugin,
|
||||||
|
Component: MySandyPlugin,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const definition2 = new _SandyPluginDefinition(
|
||||||
|
TestUtils.createMockPluginDetails({id: 'other'}),
|
||||||
|
{
|
||||||
|
plugin() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
Component() {
|
||||||
|
return <h1>Plugin2</h1>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const definition3 = new _SandyPluginDefinition(
|
||||||
|
TestUtils.createMockPluginDetails({id: 'device'}),
|
||||||
|
{
|
||||||
|
supportsDevice() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
devicePlugin() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
Component() {
|
||||||
|
return <h1>Plugin3</h1>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const {renderer, client, store} = await renderMockFlipperWithPlugin(
|
||||||
|
definition,
|
||||||
|
{
|
||||||
|
additionalPlugins: [definition2, definition3],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(renderer.baseElement.querySelector('h1')).toMatchInlineSnapshot(`
|
||||||
|
<h1>
|
||||||
|
Plugin1
|
||||||
|
</h1>
|
||||||
|
`);
|
||||||
|
expect(renders).toBe(1);
|
||||||
|
|
||||||
|
const pluginInstance: ReturnType<typeof plugin> = client.sandyPluginStates.get(
|
||||||
|
definition.id,
|
||||||
|
)!.instanceApi;
|
||||||
|
expect(pluginInstance.isPluginAvailable(definition.id)).toBeTruthy();
|
||||||
|
expect(pluginInstance.isPluginAvailable('nonsense')).toBeFalsy();
|
||||||
|
expect(pluginInstance.isPluginAvailable(definition2.id)).toBeFalsy(); // not enabled yet
|
||||||
|
expect(pluginInstance.isPluginAvailable(definition3.id)).toBeTruthy();
|
||||||
|
expect(pluginInstance.activatedStub).toBeCalledTimes(1);
|
||||||
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(0);
|
||||||
|
expect(linksSeen).toEqual([]);
|
||||||
|
|
||||||
|
// open a device plugin
|
||||||
|
pluginInstance.selectPlugin(definition3.id);
|
||||||
|
expect(store.getState().connections.selectedPlugin).toBe(definition3.id);
|
||||||
|
expect(renderer.baseElement.querySelector('h1')).toMatchInlineSnapshot(`
|
||||||
|
<h1>
|
||||||
|
Plugin3
|
||||||
|
</h1>
|
||||||
|
`);
|
||||||
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(1);
|
||||||
|
|
||||||
|
// go back by opening own plugin again (funny, but why not)
|
||||||
|
pluginInstance.selectPlugin(definition.id, 'data');
|
||||||
|
expect(store.getState().connections.selectedPlugin).toBe(definition.id);
|
||||||
|
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
||||||
|
expect(renderer.baseElement.querySelector('h1')).toMatchInlineSnapshot(`
|
||||||
|
<h1>
|
||||||
|
Plugin1
|
||||||
|
</h1>
|
||||||
|
`);
|
||||||
|
expect(linksSeen).toEqual(['data']);
|
||||||
|
|
||||||
|
// try to go to plugin 2, fails (not starred, so no-op)
|
||||||
|
pluginInstance.selectPlugin(definition2.id);
|
||||||
|
expect(store.getState().connections.selectedPlugin).toBe(definition.id);
|
||||||
|
|
||||||
|
// star plugin 2 and navigate to plugin 2
|
||||||
|
store.dispatch(
|
||||||
|
starPlugin({
|
||||||
|
plugin: definition2,
|
||||||
|
selectedApp: client.query.app,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
pluginInstance.selectPlugin(definition2.id);
|
||||||
|
expect(store.getState().connections.selectedPlugin).toBe(definition2.id);
|
||||||
|
expect(pluginInstance.deactivatedStub).toBeCalledTimes(2);
|
||||||
|
expect(renderer.baseElement.querySelector('h1')).toMatchInlineSnapshot(`
|
||||||
|
<h1>
|
||||||
|
Plugin2
|
||||||
|
</h1>
|
||||||
|
`);
|
||||||
|
expect(renders).toBe(2);
|
||||||
|
});
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
import {produce} from 'immer';
|
import {produce} from 'immer';
|
||||||
|
|
||||||
import BaseDevice from '../devices/BaseDevice';
|
import type BaseDevice from '../devices/BaseDevice';
|
||||||
import MacDevice from '../devices/MacDevice';
|
import MacDevice from '../devices/MacDevice';
|
||||||
import Client from '../Client';
|
import type Client from '../Client';
|
||||||
import {UninitializedClient} from '../UninitializedClient';
|
import {UninitializedClient} from '../UninitializedClient';
|
||||||
import {isEqual} from 'lodash';
|
import {isEqual} from 'lodash';
|
||||||
import {performance} from 'perf_hooks';
|
import {performance} from 'perf_hooks';
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
act as testingLibAct,
|
act as testingLibAct,
|
||||||
} from '@testing-library/react';
|
} from '@testing-library/react';
|
||||||
import {queries} from '@testing-library/dom';
|
import {queries} from '@testing-library/dom';
|
||||||
import {TestUtils} from 'flipper-plugin';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
selectPlugin,
|
selectPlugin,
|
||||||
@@ -37,7 +36,7 @@ import {registerPlugins} from '../reducers/plugins';
|
|||||||
import PluginContainer from '../PluginContainer';
|
import PluginContainer from '../PluginContainer';
|
||||||
import {getPluginKey, isDevicePluginDefinition} from '../utils/pluginUtils';
|
import {getPluginKey, isDevicePluginDefinition} from '../utils/pluginUtils';
|
||||||
import {getInstance} from '../fb-stubs/Logger';
|
import {getInstance} from '../fb-stubs/Logger';
|
||||||
import {setFlipperLibImplementation} from '../utils/flipperLibImplementation';
|
import {initializeFlipperLibImplementation} from '../utils/flipperLibImplementation';
|
||||||
|
|
||||||
export type MockFlipperResult = {
|
export type MockFlipperResult = {
|
||||||
client: Client;
|
client: Client;
|
||||||
@@ -55,7 +54,8 @@ type MockOptions = Partial<{
|
|||||||
* can be used to intercept outgoing calls. If it returns undefined
|
* can be used to intercept outgoing calls. If it returns undefined
|
||||||
* the base implementation will be used
|
* the base implementation will be used
|
||||||
*/
|
*/
|
||||||
onSend(pluginId: string, method: string, params?: object): any;
|
onSend?: (pluginId: string, method: string, params?: object) => any;
|
||||||
|
additionalPlugins?: PluginDefinition[];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export async function createMockFlipperWithPlugin(
|
export async function createMockFlipperWithPlugin(
|
||||||
@@ -64,9 +64,10 @@ export async function createMockFlipperWithPlugin(
|
|||||||
): Promise<MockFlipperResult> {
|
): Promise<MockFlipperResult> {
|
||||||
const store = createStore(rootReducer);
|
const store = createStore(rootReducer);
|
||||||
const logger = getInstance();
|
const logger = getInstance();
|
||||||
setFlipperLibImplementation(TestUtils.createMockFlipperLib());
|
initializeFlipperLibImplementation(store, logger);
|
||||||
|
store.dispatch(
|
||||||
store.dispatch(registerPlugins([pluginClazz]));
|
registerPlugins([pluginClazz, ...(options?.additionalPlugins ?? [])]),
|
||||||
|
);
|
||||||
|
|
||||||
function createDevice(serial: string): BaseDevice {
|
function createDevice(serial: string): BaseDevice {
|
||||||
const device = new BaseDevice(
|
const device = new BaseDevice(
|
||||||
|
|||||||
@@ -12,18 +12,18 @@ import type {Logger} from '../fb-interfaces/Logger';
|
|||||||
import type {Store} from '../reducers';
|
import type {Store} from '../reducers';
|
||||||
import createPaste from '../fb-stubs/createPaste';
|
import createPaste from '../fb-stubs/createPaste';
|
||||||
import GK from '../fb-stubs/GK';
|
import GK from '../fb-stubs/GK';
|
||||||
import {getInstance} from '../fb-stubs/Logger';
|
import type BaseDevice from '../devices/BaseDevice';
|
||||||
|
|
||||||
let flipperLibInstance: FlipperLib | undefined;
|
let flipperLibInstance: FlipperLib | undefined;
|
||||||
|
|
||||||
export function initializeFlipperLibImplementation(
|
export function initializeFlipperLibImplementation(
|
||||||
_store: Store,
|
store: Store,
|
||||||
_logger: Logger,
|
logger: Logger,
|
||||||
) {
|
) {
|
||||||
// late require to avoid cyclic dependency
|
// late require to avoid cyclic dependency
|
||||||
const {addSandyPluginEntries} = require('../MenuBar');
|
const {addSandyPluginEntries} = require('../MenuBar');
|
||||||
flipperLibInstance = {
|
flipperLibInstance = {
|
||||||
logger: getInstance(),
|
logger,
|
||||||
enableMenuEntries(entries) {
|
enableMenuEntries(entries) {
|
||||||
addSandyPluginEntries(entries);
|
addSandyPluginEntries(entries);
|
||||||
},
|
},
|
||||||
@@ -31,6 +31,44 @@ export function initializeFlipperLibImplementation(
|
|||||||
GK(gatekeeper: string) {
|
GK(gatekeeper: string) {
|
||||||
return GK.get(gatekeeper);
|
return GK.get(gatekeeper);
|
||||||
},
|
},
|
||||||
|
isPluginAvailable(device, client, pluginId) {
|
||||||
|
// supported device pluin
|
||||||
|
if (device.devicePlugins.includes(pluginId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (client) {
|
||||||
|
// plugin supported?
|
||||||
|
if (client.plugins.includes(pluginId)) {
|
||||||
|
// part of an archived device?
|
||||||
|
if (device.isArchived) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// plugin enabled?
|
||||||
|
if (
|
||||||
|
store
|
||||||
|
.getState()
|
||||||
|
.connections.userStarredPlugins[client.query.app]?.includes(
|
||||||
|
pluginId,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
selectPlugin(device, client, pluginId, deeplink) {
|
||||||
|
store.dispatch({
|
||||||
|
type: 'SELECT_PLUGIN',
|
||||||
|
payload: {
|
||||||
|
selectedPlugin: pluginId,
|
||||||
|
selectedDevice: device as BaseDevice,
|
||||||
|
selectedApp: client ? client.id : null,
|
||||||
|
deepLinkPayload: deeplink,
|
||||||
|
time: Date.now(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,17 @@ export type DevicePluginPredicate = (device: Device) => boolean;
|
|||||||
|
|
||||||
export type DevicePluginFactory = (client: DevicePluginClient) => object;
|
export type DevicePluginFactory = (client: DevicePluginClient) => object;
|
||||||
|
|
||||||
export interface DevicePluginClient extends BasePluginClient {}
|
export interface DevicePluginClient extends BasePluginClient {
|
||||||
|
/**
|
||||||
|
* Checks if the provided plugin is available for the current device
|
||||||
|
*/
|
||||||
|
isPluginAvailable(pluginId: string): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* opens a different plugin by id, optionally providing a deeplink to bring the plugin to a certain state
|
||||||
|
*/
|
||||||
|
selectPlugin(pluginId: string, deeplinkPayload?: unknown): void;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper interface around BaseDevice in Flipper
|
* Wrapper interface around BaseDevice in Flipper
|
||||||
@@ -59,6 +69,7 @@ export interface RealFlipperDevice {
|
|||||||
addLogListener(callback: DeviceLogListener): Symbol;
|
addLogListener(callback: DeviceLogListener): Symbol;
|
||||||
removeLogListener(id: Symbol): void;
|
removeLogListener(id: Symbol): void;
|
||||||
addLogEntry(entry: DeviceLogEntry): void;
|
addLogEntry(entry: DeviceLogEntry): void;
|
||||||
|
devicePlugins: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SandyDevicePluginInstance extends BasePluginInstance {
|
export class SandyDevicePluginInstance extends BasePluginInstance {
|
||||||
@@ -76,7 +87,17 @@ export class SandyDevicePluginInstance extends BasePluginInstance {
|
|||||||
initialStates?: Record<string, any>,
|
initialStates?: Record<string, any>,
|
||||||
) {
|
) {
|
||||||
super(flipperLib, definition, realDevice, initialStates);
|
super(flipperLib, definition, realDevice, initialStates);
|
||||||
this.client = this.createBasePluginClient();
|
this.client = {
|
||||||
|
...this.createBasePluginClient(),
|
||||||
|
isPluginAvailable(pluginId: string) {
|
||||||
|
return flipperLib.isPluginAvailable(realDevice, null, pluginId);
|
||||||
|
},
|
||||||
|
selectPlugin(pluginId: string, deeplink?: unknown) {
|
||||||
|
if (this.isPluginAvailable(pluginId)) {
|
||||||
|
flipperLib.selectPlugin(realDevice, null, pluginId, deeplink);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
this.initializePlugin(() =>
|
this.initializePlugin(() =>
|
||||||
definition.asDevicePluginModule().devicePlugin(this.client),
|
definition.asDevicePluginModule().devicePlugin(this.client),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Logger} from '../utils/Logger';
|
import {Logger} from '../utils/Logger';
|
||||||
|
import {RealFlipperDevice} from './DevicePlugin';
|
||||||
import {NormalizedMenuEntry} from './MenuEntry';
|
import {NormalizedMenuEntry} from './MenuEntry';
|
||||||
|
import {RealFlipperClient} from './Plugin';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface exposes all global methods for which an implementation will be provided by Flipper itself
|
* This interface exposes all global methods for which an implementation will be provided by Flipper itself
|
||||||
@@ -18,4 +20,15 @@ export interface FlipperLib {
|
|||||||
enableMenuEntries(menuEntries: NormalizedMenuEntry[]): void;
|
enableMenuEntries(menuEntries: NormalizedMenuEntry[]): void;
|
||||||
createPaste(input: string): Promise<string | undefined>;
|
createPaste(input: string): Promise<string | undefined>;
|
||||||
GK(gatekeeper: string): boolean;
|
GK(gatekeeper: string): boolean;
|
||||||
|
isPluginAvailable(
|
||||||
|
device: RealFlipperDevice,
|
||||||
|
client: RealFlipperClient | null,
|
||||||
|
pluginId: string,
|
||||||
|
): boolean;
|
||||||
|
selectPlugin(
|
||||||
|
device: RealFlipperDevice,
|
||||||
|
client: RealFlipperClient | null,
|
||||||
|
pluginId: string,
|
||||||
|
deeplink: unknown,
|
||||||
|
): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,16 @@ export interface PluginClient<
|
|||||||
* Checks if a method is available on the client implementation
|
* Checks if a method is available on the client implementation
|
||||||
*/
|
*/
|
||||||
supportsMethod(method: keyof Methods): Promise<boolean>;
|
supportsMethod(method: keyof Methods): Promise<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the provided plugin is available for the current device / application
|
||||||
|
*/
|
||||||
|
isPluginAvailable(pluginId: string): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* opens a different plugin by id, optionally providing a deeplink to bring the plugin to a certain state
|
||||||
|
*/
|
||||||
|
selectPlugin(pluginId: string, deeplinkPayload?: unknown): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,6 +108,7 @@ export interface RealFlipperClient {
|
|||||||
device_id: string;
|
device_id: string;
|
||||||
};
|
};
|
||||||
deviceSync: RealFlipperDevice;
|
deviceSync: RealFlipperDevice;
|
||||||
|
plugins: string[];
|
||||||
isBackgroundPlugin(pluginId: string): boolean;
|
isBackgroundPlugin(pluginId: string): boolean;
|
||||||
initPlugin(pluginId: string): void;
|
initPlugin(pluginId: string): void;
|
||||||
deinitPlugin(pluginId: string): void;
|
deinitPlugin(pluginId: string): void;
|
||||||
@@ -174,6 +185,23 @@ export class SandyPluginInstance extends BasePluginInstance {
|
|||||||
method as any,
|
method as any,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
isPluginAvailable(pluginId: string) {
|
||||||
|
return flipperLib.isPluginAvailable(
|
||||||
|
realClient.deviceSync,
|
||||||
|
realClient,
|
||||||
|
pluginId,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
selectPlugin(pluginId: string, deeplink?: unknown) {
|
||||||
|
if (this.isPluginAvailable(pluginId)) {
|
||||||
|
flipperLib.selectPlugin(
|
||||||
|
realClient.deviceSync,
|
||||||
|
realClient,
|
||||||
|
pluginId,
|
||||||
|
deeplink,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
this.initializePlugin(() =>
|
this.initializePlugin(() =>
|
||||||
definition.asPluginModule().plugin(this.client),
|
definition.asPluginModule().plugin(this.client),
|
||||||
|
|||||||
@@ -190,6 +190,7 @@ export function startPlugin<Module extends FlipperPluginModule<any>>(
|
|||||||
const deviceName = 'TestDevice';
|
const deviceName = 'TestDevice';
|
||||||
const fakeFlipperClient: RealFlipperClient = {
|
const fakeFlipperClient: RealFlipperClient = {
|
||||||
id: `${appName}#${testDevice.os}#${deviceName}#${testDevice.serial}`,
|
id: `${appName}#${testDevice.os}#${deviceName}#${testDevice.serial}`,
|
||||||
|
plugins: [definition.id],
|
||||||
query: {
|
query: {
|
||||||
app: appName,
|
app: appName,
|
||||||
device: deviceName,
|
device: deviceName,
|
||||||
@@ -297,6 +298,7 @@ export function startDevicePlugin<Module extends FlipperDevicePluginModule>(
|
|||||||
|
|
||||||
const flipperLib = createMockFlipperLib(options);
|
const flipperLib = createMockFlipperLib(options);
|
||||||
const testDevice = createMockDevice(options);
|
const testDevice = createMockDevice(options);
|
||||||
|
testDevice.devicePlugins.push(definition.id);
|
||||||
const pluginInstance = new SandyDevicePluginInstance(
|
const pluginInstance = new SandyDevicePluginInstance(
|
||||||
flipperLib,
|
flipperLib,
|
||||||
definition,
|
definition,
|
||||||
@@ -353,6 +355,8 @@ export function createMockFlipperLib(options?: StartPluginOptions): FlipperLib {
|
|||||||
GK(gk: string) {
|
GK(gk: string) {
|
||||||
return options?.GKs?.includes(gk) || false;
|
return options?.GKs?.includes(gk) || false;
|
||||||
},
|
},
|
||||||
|
selectPlugin: jest.fn(),
|
||||||
|
isPluginAvailable: jest.fn().mockImplementation(() => false),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,6 +407,7 @@ function createMockDevice(options?: StartPluginOptions): RealFlipperDevice {
|
|||||||
deviceType: 'emulator',
|
deviceType: 'emulator',
|
||||||
serial: 'serial-000',
|
serial: 'serial-000',
|
||||||
isArchived: !!options?.isArchived,
|
isArchived: !!options?.isArchived,
|
||||||
|
devicePlugins: [],
|
||||||
addLogListener(cb) {
|
addLogListener(cb) {
|
||||||
logListeners.push(cb);
|
logListeners.push(cb);
|
||||||
return (logListeners.length - 1) as any;
|
return (logListeners.length - 1) as any;
|
||||||
|
|||||||
@@ -201,9 +201,21 @@ client.addMenuEntry({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `isPluginAvailable`
|
||||||
|
|
||||||
|
Usage: `isPluginAvailable(pluginId: string): boolean`
|
||||||
|
|
||||||
|
Returns `true` if a plugin with the given id is available by for consumption, that is: supported by the current application / device, and enabled by the user.
|
||||||
|
|
||||||
|
#### `selectPlugin`
|
||||||
|
|
||||||
|
Usage: `selectPlugin(pluginId: string, deeplinkPayload?: unknown): void`
|
||||||
|
|
||||||
|
Opens a different plugin by id, optionally providing a deeplink to bring the target plugin to a certain state.
|
||||||
|
|
||||||
#### `supportsMethod`
|
#### `supportsMethod`
|
||||||
|
|
||||||
Usage; `client.supportsMethod(method: string): Promise<Boolean>`
|
Usage: `client.supportsMethod(method: string): Promise<Boolean>`
|
||||||
|
|
||||||
Resolves to true if the client supports the specified method. Useful when adding functionality to existing plugins, when connectivity to older clients is still required. Also useful when client plugins are implemented on multitple platforms and don't all have feature parity.
|
Resolves to true if the client supports the specified method. Useful when adding functionality to existing plugins, when connectivity to older clients is still required. Also useful when client plugins are implemented on multitple platforms and don't all have feature parity.
|
||||||
|
|
||||||
@@ -262,6 +274,14 @@ See the similarly named method under [`PluginClient`](#pluginclient).
|
|||||||
|
|
||||||
See the similarly named method under [`PluginClient`](#pluginclient).
|
See the similarly named method under [`PluginClient`](#pluginclient).
|
||||||
|
|
||||||
|
### `isPluginAvailable`
|
||||||
|
|
||||||
|
See the similarly named method under [`PluginClient`](#pluginclient).
|
||||||
|
|
||||||
|
### `selectPlugin`
|
||||||
|
|
||||||
|
See the similarly named method under [`PluginClient`](#pluginclient).
|
||||||
|
|
||||||
## Device
|
## Device
|
||||||
|
|
||||||
`Device` captures the metadata of the device the plugin is currently connected to.
|
`Device` captures the metadata of the device the plugin is currently connected to.
|
||||||
|
|||||||
Reference in New Issue
Block a user