Import from exported file
Summary: This diff adds the feature to import the exported flipper data. It has the following features - Dialog to select the file - Merges the data with an existing store. Reviewed By: danielbuechele Differential Revision: D13901944 fbshipit-source-id: 1b9755735419732a34254bdc39d911bcb51ad8fe
This commit is contained in:
committed by
Facebook Github Bot
parent
259ae35284
commit
9bc54597cf
@@ -80,20 +80,20 @@ export default class Client extends EventEmitter {
|
||||
constructor(
|
||||
id: string,
|
||||
query: ClientQuery,
|
||||
conn: ReactiveSocket,
|
||||
conn: ?ReactiveSocket,
|
||||
logger: Logger,
|
||||
store: Store,
|
||||
plugins: ?Plugins,
|
||||
) {
|
||||
super();
|
||||
this.connected = true;
|
||||
this.plugins = [];
|
||||
this.plugins = plugins ? plugins : [];
|
||||
this.connection = conn;
|
||||
this.id = id;
|
||||
this.query = query;
|
||||
this.messageIdCounter = 0;
|
||||
this.logger = logger;
|
||||
this.store = store;
|
||||
|
||||
this.broadcastCallbacks = new Map();
|
||||
this.requestCallbacks = new Map();
|
||||
|
||||
@@ -104,6 +104,7 @@ export default class Client extends EventEmitter {
|
||||
},
|
||||
};
|
||||
|
||||
if (conn) {
|
||||
conn.connectionStatus().subscribe({
|
||||
onNext(payload) {
|
||||
if (payload.kind == 'ERROR' || payload.kind == 'CLOSED') {
|
||||
@@ -115,6 +116,7 @@ export default class Client extends EventEmitter {
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getDevice = (): ?BaseDevice =>
|
||||
this.store
|
||||
@@ -132,7 +134,7 @@ export default class Client extends EventEmitter {
|
||||
query: ClientQuery;
|
||||
messageIdCounter: number;
|
||||
plugins: Plugins;
|
||||
connection: ReactiveSocket;
|
||||
connection: ?ReactiveSocket;
|
||||
responder: PartialResponder;
|
||||
store: Store;
|
||||
|
||||
@@ -337,7 +339,9 @@ export default class Client extends EventEmitter {
|
||||
|
||||
console.debug(data, 'message:call');
|
||||
this.startTimingRequestResponse({method, id, params});
|
||||
if (this.connection) {
|
||||
this.connection.fireAndForget({data: JSON.stringify(data)});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -369,8 +373,10 @@ export default class Client extends EventEmitter {
|
||||
params,
|
||||
};
|
||||
console.debug(data, 'message:send');
|
||||
if (this.connection) {
|
||||
this.connection.fireAndForget({data: JSON.stringify(data)});
|
||||
}
|
||||
}
|
||||
|
||||
call(api: string, method: string, params?: Object): Promise<Object> {
|
||||
return reportPluginFailures(
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
*/
|
||||
|
||||
import type {FlipperPlugin, FlipperDevicePlugin} from './plugin.js';
|
||||
import {exportStoreToFile} from './utils/exportData.js';
|
||||
import {exportStoreToFile, importFileToStore} from './utils/exportData.js';
|
||||
import type {Store} from './reducers/';
|
||||
import electron from 'electron';
|
||||
import {GK} from 'flipper';
|
||||
import {remote} from 'electron';
|
||||
const {dialog} = remote;
|
||||
|
||||
export type DefaultKeyboardAction = 'clear' | 'goToBottom' | 'createPaste';
|
||||
export type TopLevelMenu = 'Edit' | 'View' | 'Window' | 'Help';
|
||||
@@ -315,12 +317,28 @@ function getTemplate(
|
||||
label: 'File',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Export Data',
|
||||
label: 'Export Data...',
|
||||
role: 'export',
|
||||
click: function(item: Object, focusedWindow: Object) {
|
||||
exportStoreToFile(store);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Import Data...',
|
||||
role: 'import',
|
||||
click: function(item: Object, focusedWindow: Object) {
|
||||
dialog.showOpenDialog(
|
||||
{
|
||||
properties: ['openFile'],
|
||||
},
|
||||
(files: Array<string>) => {
|
||||
if (files !== undefined && files.length > 0) {
|
||||
importFileToStore(files[0], store);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -219,7 +219,6 @@ class MainSidebar extends PureComponent<MainSidebarProps> {
|
||||
numNotifications,
|
||||
} = this.props;
|
||||
let {clients, uninitializedClients} = this.props;
|
||||
|
||||
clients = clients
|
||||
.filter(
|
||||
(client: Client) =>
|
||||
|
||||
@@ -78,7 +78,7 @@ export default class AndroidDevice extends BaseDevice {
|
||||
});
|
||||
}
|
||||
|
||||
spawnShell(): DeviceShell {
|
||||
spawnShell(): ?DeviceShell {
|
||||
return child_process.spawn('adb', ['-s', this.serial, 'shell', '-t', '-t']);
|
||||
}
|
||||
}
|
||||
|
||||
23
src/devices/ArchivedDevice.js
Normal file
23
src/devices/ArchivedDevice.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright 2018-present Facebook.
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
* @format
|
||||
*/
|
||||
import BaseDevice from './BaseDevice.js';
|
||||
import type {DeviceType, OS, DeviceShell} from './BaseDevice.js';
|
||||
|
||||
export default class ArchivedDevice extends BaseDevice {
|
||||
constructor(serial: string, deviceType: DeviceType, title: string, os: OS) {
|
||||
super(serial, deviceType, title);
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
getLogs() {
|
||||
return [];
|
||||
}
|
||||
|
||||
spawnShell(): ?DeviceShell {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ export default class BaseDevice {
|
||||
teardown() {}
|
||||
|
||||
supportedColumns(): Array<string> {
|
||||
throw new Error('unimplemented');
|
||||
return ['date', 'pid', 'tid', 'tag', 'message', 'type', 'time'];
|
||||
}
|
||||
|
||||
addLogListener(callback: DeviceLogListener): Symbol {
|
||||
@@ -117,7 +117,7 @@ export default class BaseDevice {
|
||||
this.logListeners.delete(id);
|
||||
}
|
||||
|
||||
spawnShell(): DeviceShell {
|
||||
spawnShell(): ?DeviceShell {
|
||||
throw new Error('unimplemented');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ import type {State as PluginStatesState} from '../reducers/pluginStates';
|
||||
import type {State} from '../reducers/index';
|
||||
import {FlipperDevicePlugin} from '../plugin.js';
|
||||
import {default as BaseDevice} from '../devices/BaseDevice';
|
||||
import {default as ArchivedDevice} from '../devices/ArchivedDevice';
|
||||
import {default as Client} from '../Client';
|
||||
import {getInstance} from '../fb-stubs/Logger.js';
|
||||
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
@@ -150,3 +153,61 @@ export const exportStoreToFile = (store: Store): Promise<void> => {
|
||||
console.error('Make sure a device is connected');
|
||||
return new Promise.reject(new Error('No device is selected'));
|
||||
};
|
||||
|
||||
export const importFileToStore = (file: string, store: Store) => {
|
||||
fs.readFile(file, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
const json = JSON.parse(data);
|
||||
const {device, clients} = json;
|
||||
const archivedDevice = new ArchivedDevice(
|
||||
device.serial,
|
||||
device.deviceType,
|
||||
device.title,
|
||||
device.os,
|
||||
);
|
||||
store.dispatch({
|
||||
type: 'REGISTER_DEVICE',
|
||||
payload: archivedDevice,
|
||||
});
|
||||
store.dispatch({
|
||||
type: 'SELECT_DEVICE',
|
||||
payload: archivedDevice,
|
||||
});
|
||||
|
||||
const {pluginStates} = json.store;
|
||||
const keys = Object.keys(pluginStates);
|
||||
clients.forEach(client => {
|
||||
const clientPlugins = keys
|
||||
.filter(key => {
|
||||
const arr = key.split('#');
|
||||
arr.pop();
|
||||
const clientPlugin = arr.join('#');
|
||||
return client.id === clientPlugin;
|
||||
})
|
||||
.map(client => client.split('#').pop());
|
||||
store.dispatch({
|
||||
type: 'NEW_CLIENT',
|
||||
payload: new Client(
|
||||
client.id,
|
||||
client.query,
|
||||
null,
|
||||
getInstance(),
|
||||
store,
|
||||
clientPlugins,
|
||||
),
|
||||
});
|
||||
});
|
||||
keys.forEach(key => {
|
||||
store.dispatch({
|
||||
type: 'SET_PLUGIN_STATE',
|
||||
payload: {
|
||||
pluginKey: key,
|
||||
state: pluginStates[key],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user