export default()

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;
  }
};