Summary:
Some styling fixes and minor improvements in DataTable, used by network plugin:
- be able to customise the context menu
- be able to customise how entire rows are copied and presented on the clipboard to be able to deviate from the standard JSON
- deeplink handling was made async, this gives the plugin the opportunity to first handle initial setup and rendering before trying to jump somewhere which is a typical use case for deeplinking
Reviewed By: passy
Differential Revision: D27947186
fbshipit-source-id: a56f081d60520c4bc2ad3c547a8ca5b9357e71a1
Summary:
This diff converts the CrashReporter plugin to Sandy. The main driver is that it allows us to fix the connection management of logs in a next diff.
There are few changes to highlight:
* A bunch of the old unit tests are removed, as they primarily verified that persistedState abstraction works, a concept that doesn't exist anymore with Sandy (as a result all the logic in error handling and crash reporter plugin has become a lot more trivial as well)
* Added additional unit tests to verify that the integration with notifications from Sandy, and the integration of crashes in combination with CrashReporter plugin works (this wasn't the case before)
* Plugin errors were always suppressed in production builds of Flipper. However, that makes error reporting pretty pointless in the first place, so enabled it by default, but made it a setting in case this results in too many errors suddenly.
* The integration with clicking OS crash notification -> bringing the user to a sensible place _doesn't_ work, but it didn't work before this diff either, so will address that later
* This doesn't upgrade the Crash reporter UI to sandy yet, will do that later in a separate diff
Changelog: Crash reporter will now report errors triggered from the device / client plugins by default. This can be disabled in settings.
Reviewed By: priteshrnandgaonkar
Differential Revision: D27044507
fbshipit-source-id: 8233798f5cce668d61460c948c24bdf92ed7c834
Summary: Exposed the `pluginKey` to sandy plugins (which we will use later for storing table preferences per plugin). And a little moving code around because circular deps problem roared its ugly head again.
Reviewed By: nikoant
Differential Revision: D27009721
fbshipit-source-id: 7ad29e72ff8028c9daae270c4749b657bd8ff049
Summary:
Introduced a context menu for DataTable with some default options. Opted to put it under a visible hovered dropdown instead of on right-click, since this better alings with Ant's design guides (we don't have context clicks anywhere else I think), but if it isn't convincing we can still change it.
Included some default actions, to set up quick filters, and to copy values. For copying rows, implemented it to by default take the JSON from a row, rather than space separated values like in ManagedTable, as many existing plugins customize the onCopy handler to just do that, so it seemed like a better default since it is a richer format. If there are good use cases for the previous behavior, we'll probably find out after the old release :)
Introduced utility to copy text to clipboard in FlipperLib, but decoupled it from Electron.
Didn't include multi select yet, that will be done in a next diff.
Reviewed By: nikoant
Differential Revision: D26513161
fbshipit-source-id: b2b1b20b0a6f4ada9de2566bf6b02171f722c4aa
Summary:
*Stack summary*: this stack adds ability to manage device plugins in the same way as client plugins: install, update, uninstall, enable (star) and disable (unstar) them.
*Diff summary*: changed the way how plugin compatibility with devices is checked from dynamic call to "supportsDevice" to static checks of "supportedDevices" metadata property which make it possible to check compatibility without even downloading plugin from Marketplace.
Changelog: plugin compatibility with devices is now checked according to metadata in property "supportedDevices" in package.json
Reviewed By: mweststrate
Differential Revision: D26315848
fbshipit-source-id: 6e4b052c4ea0507ee185fc17999b6211cdb11093
Summary:
*Stack summary*: this stack refactors plugin management actions to perform them in a dispatcher rather than in the root reducer (store.tsx) as all of these actions has side effects. To do that, we store requested plugin management actions (install/update/uninstall, star/unstar) in a queue which is then handled by pluginManager dispatcher. This dispatcher then dispatches all required state updates.
*Diff summary*: refactored "uninstall plugin" operation to perform it in pluginManager dispatcher
Reviewed By: mweststrate
Differential Revision: D26166198
fbshipit-source-id: d74a1d690102d9036c6d3d8612d2428f5ecef4e6
Summary:
Minor code cleanup to avoid future confusion:
- archived: a device that was imported from a Flipper trace, and only has persisted state
- (dis)connected: a real stateful device that might or might not have an active connection
Reviewed By: nikoant
Differential Revision: D26275459
fbshipit-source-id: eba554b37c39711e367c3795ff4456329a303c22
Summary:
It should be possible to exported disconnected devices, so that flipper traces / support form reports can be created from them. This diff introduces this functionality. Support for plugins with custom export logic is introduced in a later diff.
Issues fixed in this diff:
- don't try to take a screenshot for a disconnected device (this would hang forever)
- device plugins were always exported, regardless whether the user did select them or not
- sandy plugins were never part of exported disconnected clients
- increased the amount of data exported for device logs to ~10 MB. This makes more sense now as the logs will no longer be included in all cases
- fixed issue where are plugins would appear to be enabled after the client disconnected (this bug is the result of some unfortunate naming of `isArchived` vs `isConnected` semantics. Will clean up those names in a later diff.
Changelog: It is now possible to create a Flipper trace for disconnected devices and apps
Reviewed By: nikoant
Differential Revision: D26250894
fbshipit-source-id: 4dd0ec0cb152b1a8f649c31913e80efc25bcc5dd
Summary:
Introduced `isConnected` flag on device and plugin client to reflect whether a connection is still available for the plugins, or that they have been disconnected.
Potentially we could expose the (readonly) `connected` state atom for this as well, or an `onDisconnect` event for device pugins, to create a responsive UI, but there might be no need for that, in which case this suffices.
Reviewed By: nikoant
Differential Revision: D26249346
fbshipit-source-id: b8486713fdf2fcd520488ce54f771bd038fd13f8
Summary:
Sandy plugins can now set up an `onExport` handler to enable customizing the export format of a plugin: `client.onExport(callback: (idler, onStatusMessage) => Promise<state>)`
Import will be done in next diff
Reviewed By: nikoant
Differential Revision: D26124440
fbshipit-source-id: c787c79d929aa8fb484f15a9340d7c87545793cb
Summary: Plugin metadata format extended to include type of each plugin (client / device) and list of supported devices (android/ios/..., emulator/physical, etc). This will allow to detect plugins supported by device even if they are not installed and only available on Marketplace.
Reviewed By: mweststrate
Differential Revision: D26073531
fbshipit-source-id: e331f1be1af1046cd4220a286a1d52378c26cc53
Summary:
I've re-designed interfaces describing plugins as I found that mental overhead working with them became too expensive because of slightly flawed design. However this cascaded changes in many files so you can see how extensively these interfaces used in our codebase.
Before this change we had one interface PluginDetails which described three different entities: 1) plugins installed on the disk 2) plugins bundled into Flipper 3) plugins available on Marketplace. It's hard to use this "general" PluginDetails interface because of this as you always need to think about all three use cases everywhere.
After this change we have 3 separate interfaces: InstalledPluginDetails, BundledPluginDetails and DownloadablePluginDetails and things became much type-safer now.
Reviewed By: mweststrate
Differential Revision: D25530383
fbshipit-source-id: b93593916a980c04e36dc6ffa168797645a0ff9c
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
Summary:
`activatePlugin` events where not recorded correctly for Sandy plugins. Although the starting measuerments is fired the `connections` reducer, the completing event fires from `PluginContainer`. Since this is done as part of a ref-update (!!), see [here](https://www.internalfb.com/intern/diffusion/FBS/browse/master/xplat/sonar/desktop/app/src/PluginContainer.tsx?commit=65a625ea9941&lines=155), and the ref to the corresponding element is not set for Sandy plugins, the event was never marked as completed.
Fixed this by making it part of the `activate` life-cycle event of Sandy plugins.
Reviewed By: passy
Differential Revision: D25421537
fbshipit-source-id: 5cbfeb91cc12e4520fa271bab24034094d7ddb39
Summary: Make sure that GKs can be used in pure sandy plugins.
Reviewed By: jknoxville
Differential Revision: D25368358
fbshipit-source-id: c7c6aa4ecf0443cb3b5d90e22e8aca9a73a69389
Summary: expose `appName`, `appId` and `device` to Sandy plugins. Will be used in next diff to migrate navigation plugin
Reviewed By: cekkaewnumchai
Differential Revision: D24857253
fbshipit-source-id: 03ac3d376d5d1950bcf3d78386a65ce167b517e3
Summary:
per title
In addition, this diff adds `startUnactivated` option to allow setting up `onSend` mock implementation.
Reviewed By: mweststrate
Differential Revision: D24477989
fbshipit-source-id: f913574ebacdd436e8511baa43744249a014e90b
Summary: `supportsMethod` wasn't implemented in the new sandy APIs so far, but is needed for D24108772
Reviewed By: cekkaewnumchai
Differential Revision: D24109496
fbshipit-source-id: 694344b423c1805baa193e4f2e1ad5f28483378b
Summary:
I noticed that after the typescript upgrade, I got several weird positives from ESLint (like unused parameters in a type definition, which are obviously always unused, e.g. `type onClick = (e: Event) => void`). After some investigation, it turned out these warnings are generated by eslint, but that those rules should be performaned by typescript/eslint instead. For future reference to which rules this applies:
https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/README.md#extension-rules
Updated the config, and while at it, fixed all warnings in our codebase, except for `react-hooks/exhaustive-deps` warnings, since those require semantic changes.
This reduces the amount of eslint warnings from 86 to 39.
Reviewed By: passy
Differential Revision: D23905630
fbshipit-source-id: 0557708fd9ec6b17840a3c191e7d3baf225bdf23
Summary:
Added support for `createPaste` in Sandy plugins
Nice minimalistic example of how to expose a Flipper api to Sandy.
Note that some indirection could be removed by having an interface that is shared directly between `BasePluginClient` and `FlipperLib` (e.g. `PublicFlipperLib`). In contrast to `addMenuEntries` from the previous diff, `createPaste` is basically exposed verbatim to Sandy without additional wrapping, so those cases could be made simpler. Maybe will do that later.
Reviewed By: passy
Differential Revision: D22815873
fbshipit-source-id: e6d0773a35341edfe5de0898317eaadf88de79d0
Summary:
[interesting] since it shows how Flipper APIs are exposed through sandy. However, the next diff is a much simpler example of that
This diff adds support for adding menu entries for sandy plugin (renamed keyboard actions to menus, as it always creates a menu entry, but not necessarily a keyboard shortcut)
```
client.addMenuEntry(
// custom entry
{
label: 'Reset Selection',
topLevelMenu: 'Edit',
handler: () => {
selectedID.set(null);
},
},
// based on built-in action (sets standard label, shortcut)
{
action: 'createPaste',
handler: () => {
console.log('creating paste');
},
},
);
```
Most of this diff is introducing the concept of FlipperUtils, a set of static Flipper methods (not related to a device or client) that can be used from Sandy. This will for example be used to implement things as `createPaste` as well
Reviewed By: nikoant
Differential Revision: D22766990
fbshipit-source-id: ce90af3b700e6c3d9a779a3bab4673ba356f3933
Summary:
The device type enum was mixing two different concepts (emulator vs physical) and (archived vs not), and we already have a separate `isArchived` field. So cleaned this up to not leak it into sandy.
If anybody can think of any unforeseen consequences of this, lemme know :)
Reviewed By: jknoxville
Differential Revision: D22763506
fbshipit-source-id: bd2f7dbd1d2d2e6942ba7c6ddd8dc91ee34d591d
Summary: Introducing a base abstract class (blegh) to share some life cycle management between Device- and normal plugins. Cleaned up the test utils a bit as well + some old TODO's that now have been taken care of
Reviewed By: nikoant
Differential Revision: D22727089
fbshipit-source-id: 507816f1bfdbc6e7e71d4bd365b881b6710ca917
Summary:
Device plugins have an activate and deactivate hook, that reflects the plugin being selected in the UI. Added these same hooks to client plugins as well. In practice they are called at the same times as `onConnect` and `onDisconnect`, except for background plugins, which connect only once, so it is pretty useful to be still able to make the distinction.
Since there is now quite some common functionality between plugins and device plugins, will clean things a bit up in a next diff
[Interesting] as it explains the difference between the different lifecycle methods of plugins, and the impact of being a background plugin
LIfecycle summary:
1. app connects
2. for background plugins: connect them (`onConnect`)
3. user selects a plugin, triggers `onActivate`. will also trigger `onConnect` the plugin if it _isnt_ a bg plugin
4. user selects a different plugin, triggers `onDeactivate`. will also trigger `onDisconnect` if it isn't a bg plugin.
5. app is unloaded. Triggers `onDisconnect` for bg plugins. Triggers `onDestroy` for all plugins,
Reviewed By: jknoxville
Differential Revision: D22724791
fbshipit-source-id: 9fe2e666eb37fa2e0bd00fa61d78d2d4b1080137
Summary:
Make sure device plugins can be deeplinked as well.
(note that the duplication between `Plugin` and `DevicePlugin` is cleaned up again in D22727089, first wanted to make it work and tested, then clean)
DeepLink no longer have to be strings, per popular requests, as that makes direct linking between plugins easier (online links from the outside world have to arrive as strings)
Reviewed By: jknoxville, nikoant
Differential Revision: D22727091
fbshipit-source-id: 523c90b1e1fbf3700fdb4f62699dd57070cbc980
Summary: Add unit tests to verify that the unit test utilities for for Sandy device plugins work as expected. Fixed a bug revealed by that and cleaned up some TODO's
Reviewed By: jknoxville, passy, nikoant
Differential Revision: D22693928
fbshipit-source-id: 93162db19d826d0cd7f642cef1447fd756261ac8
Summary:
This stack introduces Sandy device plugins, they are quite similar to normal plugins, but, a devicePlugin module is organized as
```
export function supportsDevice(device): boolean
export function devicePlugin(devicePluginClient)
export function Component
```
Device plugins get access to the device meta data and can subscribe to the `onLogEntry` callback and `onDestroy` lifecycle.
They will be able to store state just as normal plugins, but can't send or receive methods, so devicePluginClient is a bit limited.
This diff only sets up most of the new data structures, and makes sure everything still compiles and no existing tests fail.
To prevent this diff from becoming to big, actually loading, rendering and testing device plugins will be done in next diffs
Please take a critical look at the api proposed and the (especially) the public names used :)
Reviewed By: passy, nikoant
Differential Revision: D22691351
fbshipit-source-id: bdbbd7f86d14b646fc9a693ad19f33583a76f26d
Summary:
This adds support for handling incoming deeplinks in a Sandy plugin, which can be done by using a `client.onDeepLink(deepLink => { } )` listener
Also generalized deeplinks to not just support strings, but also richer objects, which is beneficial to plugin to plugin linking.
Reviewed By: jknoxville
Differential Revision: D22524749
fbshipit-source-id: 2cbe8d52f6eac91a1c1c8c8494706952920b9181
Summary:
This plugin adds serialization capabilities to Sandy plugins buy setting the a `persist: <key>` flag. This shouldn't be used for state that is unserializable, too big, too sensitive, or irrelevant during export / import.
Using an explicit `persist` flag is done to make plugins robust to changes over time; as long as the key is kept the same, state variables can be renamed and reordered without breaking the import / export format. Also it allows us to detect some changes in the import / export format and warn about it.
Alternative designs considered but not implemented would be:
1. requiring the user to explicitly return the state from the factory (e.g. `const todos = createState([]); return { todos }`,
2. or construct the state from client (e.g. `const todos = client.createState([])`)
3. enable persistence by default, and store states in the order the states were created (much like useState in React). This was implemented in the first versions of this diff, but as pointed out in the discussions, this is too sensitive too (accidental) format changes, as the storage format would be quite implicit
A nice benefit of the current approach, especially compared with alternative approach 1, is that state being restored is immediately visible in the plugin factory. In other words, directly after initialization `const todos = createState([])`, the `todos.get()` is actually set to the state that is being restored, rather than having still the initial state which is only overridden rather. So this behaves very much like the `useState` hook in React.
Furthermore, in the future we could use the same `persist` key in combination with other options, such as `saveToLocalStorage`, in case some state acts as a 'preference' (T69989583).
`TestUtils.startPlugin` supports starting plugins with an initial state by using the optional `initialState` field
Actually wiring up the serialization and deserialization into the export / import functionality of Flipper is done in the next diff.
Reviewed By: jknoxville
Differential Revision: D22432770
fbshipit-source-id: 9a4849582c2f6f54d1e40f65a6cba73092c28fe8
Summary:
Created a few breakages. Would appreciate some closer eyes on this.
Pull Request resolved: https://github.com/facebook/flipper/pull/1366
Reviewed By: mweststrate
Differential Revision: D22501454
fbshipit-source-id: 9b882a12aecc65da85f29101bf87bf27519a7d2a
Summary: While testing manually discovered the sandy plugin infra din't cover the case that a plugin can be selected but not enabled at the same time. Added test and fixed that.
Reviewed By: nikoant
Differential Revision: D22308597
fbshipit-source-id: 6cef2b543013ee81cee449396d523dd9a657ad1c
Summary:
Introduced a minimal state abstraction so that state can be maintained in the plugin instance, but subscribe to by the UI.
At a later point we could pick an off the shelve solution like Recoil or MobX, or introduce cursors to read something deep etc etc, but for now that doesn't seem to be needed at all, and I think this will be pretty comprehensible for plugin authors (see also the 25th diff in this stack).
The api
```
createState(initialValue): Atom
Atom {
get() // returns current value
set(newValue) // sets a new value
update(draft => { }) // updates a complex value using Immer behind the scenes
}
// hook, subscribes to the updates of the Atom and always returns the current value
useValue(atom)
```
Reviewed By: nikoant
Differential Revision: D22306673
fbshipit-source-id: c49f5af85ae9929187e4d8a051311a07c1b88eb5
Summary: This diffs adds the capability to listen to messages in Sandy plugins. Although API wise it looks more like the old `this.subscribe`, semantically it behaves like the `persistedStateReducer`; messages are queued if the plugin is enabled but not active.
Reviewed By: nikoant
Differential Revision: D22282711
fbshipit-source-id: 885faa702fe779ac8d593c1d224b2be13e688d47
Summary: Sandy plugins can now send messages to plugins. The methods and params are strongly typed in implementation and unit tests, based on the <Methods> generic of FlipperClient.
Reviewed By: nikoant
Differential Revision: D22256972
fbshipit-source-id: 549523a402949b3eb6bb4b4ca160dedb5c5e722d
Summary:
This sets up the initial infra that is to be used by plugin devs to test plugins.
There is not much yet to see, as there is no state or message sending yet. But at least the life cycle of plugins can be test, things are strongly typed and everything is in the place where it should be :)
N.b. the import difference with these utils and the createFlipperMock utilities in Flipper are
1. this testing infra is entirely inside flipper-plugin package, so that plugin devs don't need flipper as a dependency
2. this testing infra doesn't provide abstractions for plugin / device / client switching; it tests plugins purely in isolation of the rest of the world (except for firing `onConnect` / `onDisconnect` which is normally the effect of switching plugins)
Reviewed By: nikoant
Differential Revision: D22255262
fbshipit-source-id: b94ccbab720d2b49428a646aed3c55af71a5bc80