in desktop/flipper-ui-core/src/reducers/connections.tsx [190:442]
export default (state: State = INITAL_STATE, action: Actions): State => {
switch (action.type) {
case 'SET_STATIC_VIEW': {
const {payload, deepLinkPayload} = action;
return {
...state,
staticView: payload,
deepLinkPayload: deepLinkPayload ?? null,
};
}
case 'RESET_SUPPORT_FORM_V2_STATE': {
return {
...state,
staticView: null,
};
}
case 'SELECT_DEVICE': {
const {payload} = action;
return {
...state,
staticView: null,
selectedDevice: payload,
selectedAppId: null,
userPreferredDevice: payload
? payload.title
: state.userPreferredDevice,
};
}
case 'SET_MENU_ENTRIES': {
return {...state, pluginMenuEntries: action.payload};
}
case 'REGISTER_DEVICE': {
const {payload} = action;
const newDevices = state.devices.slice();
const existing = state.devices.findIndex(
(device) => device.serial === payload.serial,
);
if (existing !== -1) {
const d = newDevices[existing];
if (d.connected.get()) {
throw new Error(`Cannot register, '${d.serial}' is still connected`);
}
newDevices[existing] = payload;
} else {
newDevices.push(payload);
}
const selectNewDevice =
!state.selectedDevice ||
!state.selectedDevice.isConnected ||
state.userPreferredDevice === payload.title;
let selectedAppId = state.selectedAppId;
if (selectNewDevice) {
// need to select a different app
selectedAppId =
getAllClients(state).find(
(c) =>
c.device === payload && c.query.app === state.userPreferredApp,
)?.id ?? null;
// nothing found, try first app if any
if (!selectedAppId) {
selectedAppId =
getAllClients(state).find((c) => c.device === payload)?.id ?? null;
}
}
return {
...state,
devices: newDevices,
selectedDevice: selectNewDevice ? payload : state.selectedDevice,
selectedAppId,
};
}
case 'SELECT_PLUGIN': {
const {selectedPlugin, selectedAppId, deepLinkPayload} = action.payload;
if (selectedPlugin) {
performance.mark(`activePlugin-${selectedPlugin}`);
}
const client = state.clients.get(selectedAppId!);
const device = action.payload.selectedDevice ?? client?.device;
if (!device) {
console.warn(
'No valid device / client provided when calling SELECT_PLUGIN',
);
return state;
}
return {
...state,
staticView: null,
selectedDevice: device,
userPreferredDevice: canBeDefaultDevice(device)
? device.title
: state.userPreferredDevice,
selectedAppId: selectedAppId ?? null,
userPreferredApp:
state.clients.get(selectedAppId!)?.query.app ??
state.userPreferredApp,
selectedPlugin,
userPreferredPlugin: selectedPlugin,
deepLinkPayload: deepLinkPayload,
};
}
case 'NEW_CLIENT': {
const {payload} = action;
return produce(state, (draft) => {
if (draft.clients.has(payload.id)) {
console.warn(
`Received a new connection for client ${payload.id}, but the old connection was not cleaned up`,
);
}
draft.clients.set(payload.id, payload);
// select new client if nothing select, this one is preferred, or the old one is offline
const selectNewClient =
!draft.selectedAppId ||
draft.userPreferredApp === payload.query.app ||
draft.clients.get(draft.selectedAppId!)?.connected.get() === false;
if (selectNewClient) {
draft.selectedAppId = payload.id;
draft.selectedDevice = payload.device;
}
const unitialisedIndex = draft.uninitializedClients.findIndex(
(c) =>
c.deviceName === payload.query.device ||
c.appName === payload.query.app,
);
if (unitialisedIndex !== -1)
draft.uninitializedClients.splice(unitialisedIndex, 1);
});
}
case 'SELECT_CLIENT': {
const {payload} = action;
const client = state.clients.get(payload);
if (!client) {
return state;
}
return {
...state,
selectedAppId: payload,
selectedDevice: client.device,
userPreferredDevice: client.device.title,
userPreferredApp: client.query.app,
selectedPlugin:
state.selectedPlugin && client.supportsPlugin(state.selectedPlugin)
? state.selectedPlugin
: state.userPreferredPlugin &&
client.supportsPlugin(state.userPreferredPlugin)
? state.userPreferredPlugin
: null,
};
}
case 'CLIENT_REMOVED': {
const {payload} = action;
return produce(state, (draft) => {
draft.clients.delete(payload);
if (draft.selectedAppId === payload) {
draft.selectedAppId = null;
}
});
}
case 'START_CLIENT_SETUP': {
const {payload} = action;
return {
...state,
uninitializedClients: [
...state.uninitializedClients.filter(
(existing) => !shallowEqual(existing, payload),
),
payload,
],
};
}
case 'REGISTER_PLUGINS': {
// plugins are registered after creating the base devices, so update them
const plugins = action.payload;
plugins.forEach((plugin) => {
if (isDevicePluginDefinition(plugin)) {
// smell: devices are mutable
state.devices.forEach((device) => {
device.loadDevicePlugin(plugin);
});
}
});
return state;
}
case 'SET_PLUGIN_ENABLED': {
const {pluginId, selectedApp} = action.payload;
return produce(state, (draft) => {
if (!draft.enabledPlugins[selectedApp]) {
draft.enabledPlugins[selectedApp] = [];
}
const plugins = draft.enabledPlugins[selectedApp];
const idx = plugins.indexOf(pluginId);
if (idx === -1) {
plugins.push(pluginId);
}
});
}
case 'SET_DEVICE_PLUGIN_ENABLED': {
const {pluginId} = action.payload;
return produce(state, (draft) => {
draft.enabledDevicePlugins.add(pluginId);
});
}
case 'SET_PLUGIN_DISABLED': {
const {pluginId, selectedApp} = action.payload;
return produce(state, (draft) => {
if (!draft.enabledPlugins[selectedApp]) {
draft.enabledPlugins[selectedApp] = [];
}
const plugins = draft.enabledPlugins[selectedApp];
const idx = plugins.indexOf(pluginId);
if (idx !== -1) {
plugins.splice(idx, 1);
}
});
}
case 'SET_DEVICE_PLUGIN_DISABLED': {
const {pluginId} = action.payload;
return produce(state, (draft) => {
draft.enabledDevicePlugins.delete(pluginId);
});
}
case 'APP_PLUGIN_LIST_CHANGED': {
return produce(state, (draft) => {
draft.selectedAppPluginListRevision++;
});
}
default:
return state;
}
};