How to Limit Intent Handlers to App Instances in the Selected Workspace Using Interception

Question

When an app raises an Intent, I want running app instances to be considered as Intent handlers only if they are in the currently selected Workspace. The goal is to avoid an Intent being handled by an app instance in a Workspace that isn’t currently in use.

Solution

Use a Plugin in the Main app to intercept the "raise" operation of the "intents" domain.

In the interception handler:

  1. Use the io.Connect APIs (e.g., io.workspaces and/or io.appManager) to compile the list of instances or apps that should be considered as possible handlers.
  2. Set this list as the handlers property of the intentRequest in the intercepted control message.
  3. Forward the "raise" command to the platform with platform.system.sendControl(), setting skipInterception to true to avoid an infinite loop.
  4. Return the result of sendControl().

Interceptor Example: Filter the Handlers by the Selected Workspace

const raiseIntentInterceptionRequest: IOConnectBrowserPlatform.Plugins.InterceptorRegistrationRequest = {
  // @todo: type controlMessage as https://docs.interop.io/browser/capabilities/plugins/domains-operations/index.html#intents-raise
  async callInterceptor(controlMessage) {
    const activeWorkspace = await io.workspaces?.getWorkspace((workspace) => !!workspace.isSelected)
    const workspaceWindows = activeWorkspace?.getAllWindows()
    const workspaceWindowIds = new Set(workspaceWindows?.map((workspaceWindow) => workspaceWindow.id))
    const intentRequest: IOConnectBrowser.Intents.IntentRequest = controlMessage.data.intentRequest;

    const filterFn = (handler: IOConnectBrowser.Intents.IntentHandler) => handler.type === "app" || workspaceWindowIds.has(handler.instanceId);

    if (intentRequest.handlers?.length) {
      // use the handlers from the intent request to filter the ones from the current wsp
        controlMessage.data.intentRequest.handlers = intentRequest.handlers?.filter(filterFn);

        return await platform.system.sendControl({ ...controlMessage, settings: { skipInterception: true } });
    }

    // gather all intent handlers for the current intent request and then filter them
    const possibleHandlers = (await io.intents.find(intentRequest.intent)).map((intent) => intent.handlers).flat();

    controlMessage.data.intentRequest.handlers = possibleHandlers?.filter(filterFn);

    return await platform.system.sendControl({ ...controlMessage, settings: { skipInterception: true } });
  },
  interceptions: [
    {
      domain: 'intents',
      operation: 'raise',
    },
  ],
}

Refer to: