Files
flipper/src/reducers/connections.js
Daniel Büchele f4822143bd plugin reselection
Summary: When relaunching Flipper/refreshing it while developing, where was a case, where the App Client connected, before the device was registered in Flipper. In this case, we didn't select the previously selected plugin

Reviewed By: jknoxville

Differential Revision: D9359779

fbshipit-source-id: 9c6f8e6bf65a46dc84c9781242b23df0ed539810
2018-08-16 08:12:16 -07:00

252 lines
5.8 KiB
JavaScript

/**
* 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 type BaseDevice from '../devices/BaseDevice';
import type Client from '../Client';
export type State = {
devices: Array<BaseDevice>,
androidEmulators: Array<string>,
selectedDevice: ?BaseDevice,
selectedPlugin: ?string,
selectedApp: ?string,
userPreferredDevice: ?string,
userPreferredPlugin: ?string,
userPreferredApp: ?string,
error: ?string,
clients: Array<Client>,
};
export type Action =
| {
type: 'UNREGISTER_DEVICES',
payload: Set<string>,
}
| {
type: 'REGISTER_DEVICE',
payload: BaseDevice,
}
| {
type: 'REGISTER_ANDROID_EMULATORS',
payload: Array<string>,
}
| {
type: 'SELECT_DEVICE',
payload: BaseDevice,
}
| {
type: 'SELECT_PLUGIN',
payload: {
selectedPlugin: ?string,
selectedApp: ?string,
},
}
| {
type: 'SERVER_ERROR',
payload: ?string,
}
| {
type: 'NEW_CLIENT',
payload: Client,
}
| {
type: 'CLIENT_REMOVED',
payload: string,
}
| {
type: 'PREFER_DEVICE',
payload: string,
};
const DEFAULT_PLUGIN = 'DeviceLogs';
const INITAL_STATE: State = {
devices: [],
androidEmulators: [],
selectedDevice: null,
selectedApp: null,
selectedPlugin: DEFAULT_PLUGIN,
userPreferredDevice: null,
userPreferredPlugin: null,
userPreferredApp: null,
error: null,
clients: [],
};
export default function reducer(
state: State = INITAL_STATE,
action: Action,
): State {
switch (action.type) {
case 'SELECT_DEVICE': {
const {payload} = action;
return {
...state,
selectedApp: null,
selectedPlugin: DEFAULT_PLUGIN,
selectedDevice: payload,
userPreferredDevice: payload.title,
};
}
case 'REGISTER_ANDROID_EMULATORS': {
const {payload} = action;
return {
...state,
androidEmulators: payload,
};
}
case 'REGISTER_DEVICE': {
const {payload} = action;
const devices = state.devices.concat(payload);
let {selectedDevice, selectedPlugin} = state;
// select the default plugin
let selection = {
selectedApp: null,
selectedPlugin: DEFAULT_PLUGIN,
};
if (!selectedDevice) {
selectedDevice = payload;
if (selectedPlugin) {
// We already had a plugin selected, but no device. This is happening
// when the Client connected before the Device.
selection = {};
}
} else if (payload.title === state.userPreferredDevice) {
selectedDevice = payload;
} else {
// We didn't select the newly connected device, so we don't want to
// change the plugin.
selection = {};
}
return {
...state,
devices,
// select device if none was selected before
selectedDevice,
...selection,
};
}
case 'UNREGISTER_DEVICES': {
const {payload} = action;
const {selectedDevice} = state;
let selectedDeviceWasRemoved = false;
const devices = state.devices.filter((device: BaseDevice) => {
if (payload.has(device.serial)) {
if (selectedDevice === device) {
// removed device is the selected
selectedDeviceWasRemoved = true;
}
return false;
} else {
return true;
}
});
let selection = {};
if (selectedDeviceWasRemoved) {
selection = {
selectedDevice: devices[devices.length - 1],
selectedApp: null,
selectedPlugin: DEFAULT_PLUGIN,
};
}
return {
...state,
devices,
...selection,
};
}
case 'SELECT_PLUGIN': {
const {payload} = action;
const {selectedPlugin} = payload;
if (selectedPlugin) {
performance.mark(`activePlugin-${selectedPlugin}`);
}
return {
...state,
...payload,
userPreferredApp: payload.selectedApp,
userPreferredPlugin: selectedPlugin,
};
}
case 'NEW_CLIENT': {
const {payload} = action;
const {userPreferredApp, userPreferredPlugin} = state;
let {selectedApp, selectedPlugin} = state;
if (
userPreferredApp &&
userPreferredPlugin &&
payload.id === userPreferredApp &&
payload.plugins.includes(userPreferredPlugin)
) {
// user preferred client did reconnect, so let's select it
selectedApp = userPreferredApp;
selectedPlugin = userPreferredPlugin;
}
return {
...state,
clients: state.clients.concat(payload),
selectedApp,
selectedPlugin,
};
}
case 'CLIENT_REMOVED': {
const {payload} = action;
let selected = {};
if (state.selectedApp === payload) {
selected.selectedApp = null;
selected.selectedPlugin = DEFAULT_PLUGIN;
}
return {
...state,
...selected,
clients: state.clients.filter(
(client: Client) => client.id !== payload,
),
};
}
case 'PREFER_DEVICE': {
const {payload: userPreferredDevice} = action;
return {...state, userPreferredDevice};
}
case 'SERVER_ERROR': {
const {payload} = action;
return {...state, error: payload};
}
default:
return state;
}
}
export const selectDevice = (payload: BaseDevice): Action => ({
type: 'SELECT_DEVICE',
payload,
});
export const preferDevice = (payload: string): Action => ({
type: 'PREFER_DEVICE',
payload,
});
export const selectPlugin = (payload: {
selectedPlugin: ?string,
selectedApp: ?string,
}): Action => ({
type: 'SELECT_PLUGIN',
payload,
});