# io.Connect Desktop 9.8

Source: https://docs.interop.io/desktop/getting-started/changelog/9-8/index.html

## io.Connect Desktop 9.8

*Release date: 07.04.2025*

| Components | Version |
|------------|---------|
| Electron | [35.1.2](https://releases.electronjs.org/release/v35.1.2) |
| Chromium | 134.0.6998.178 |
| Node.js | 22.14.0 |

The following libraries are bundled with **io.Connect Desktop** 9.8 and will be used for [auto injection](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/javascript/index.md#auto_injection):

| Injected Library | Version |
|------------------|---------|
| [`@interopio/desktop`](https://www.npmjs.com/package/@interopio/desktop) | [6.10](https://docs.interop.io/desktop/getting-started/how-to/interop-enable-your-apps/javascript/index.md#changelog-interopiodesktop-6100) |
| [`@interopio/fdc3`](https://www.npmjs.com/package/@interopio/fdc3) | 2.5 |

## New Features

> ### Directional Multi Channel Selector
>
> The [directional multi Channel Selector](https://docs.interop.io/desktop/capabilities/data-sharing/channels/overview/index.md#channel_selector-types-directional_multi) allows the window to join multiple Channels, but also enables the user to restrict the window from publishing or from subscribing to the currently joined Channels:
>
> ![Directional Multi Channels](https://docs.interop.io/desktop/images/channels/channel-selector-directional-multi.png)
>
> To enable the directional multi Channel Selector globally for all apps, use the `"type"` property of the `"channelSelector"` object under the `"windows"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**:
>
>```json
> {
>     "windows": {
>         "channelSelector": {
>             "type": "directionalMulti"
>         }
>     }
> }
> ```
>
> To enable the directional multi Channel Selector per app when in multi Channel mode, use the `"type"` property of the `"channelSelector"` object under the `"details"` top-level key in the [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md):
>
> ```json
> {
>     "details": {
>         "channelSelector": {
>             "enabled": true,
>             "type": "directionalMulti"
>         }
>     }
> }
> ```
>
> > ⚠️ *Note that all considerations for working with the [multi Channel Selector](https://docs.interop.io/desktop/capabilities/data-sharing/channels/overview/index.md#channel_selector-types-multi) apply to the directional multi Channel Selector as well.*

> ### Clearing Channel Context Data
>
> To [clear the context data](https://docs.interop.io/desktop/capabilities/data-sharing/channels/javascript/index.md#clearing_chanel_context_data) of the current Channel, use the [`clearChannelData()`](https://docs.interop.io/desktop/reference/javascript/channels/api/index.md#API-clearChannelData) method:
>
> ```javascript
> await io.channels.clearChannelData();
> ```
>
> The `data` property of the [`ChannelContext`](https://docs.interop.io/desktop/reference/javascript/channels/channelcontext/index.md) object will be set to an empty object.
>
> To clear the context data of a specific Channel, pass the Channel name as an argument:
>
> ```javascript
> await io.channels.clearChannelData("Red");
> ```

> ### Displaying the Title of the Selected Tab in the Windows Taskbar
>
> By default, **io.Connect Desktop** displays the title of the window group when the user hovers over the group icon in the Windows taskbar. You can instruct the platform to display the title of the currently selected tab instead when the user hovers over the icon of a single tab group in the Windows taskbar:
>
> ![Selected Tab Title in Windows Taskbar](https://docs.interop.io/desktop/images/window-management/show-selected-tab-title.png)
>
> To do so, use the `"showSelectedTabTitleInTaskbar"` property of the `"tabs"` object under the `"group"` key. The `"group"` object is located under the `"windowManagement"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**:
>
> ```json
> {
>     "windowManagement": {
>         "group": {
>             "tabs": {
>                 "showSelectedTabTitleInTaskbar": true
>             }
>         }
>     }
> }
> ```

> ### Modifying Response Headers
>
> It's now possible to configure **io.Connect Desktop** and your interop-enabled web apps to remove response headers received from external server or to modify their directives.
>
> To configure the behavior for handling the response headers globally for all web web apps, use the `"responseHeaders"` property of the `"windows"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**. The `"responseHeaders"` property accepts as a value an object holding combinations of string keys and object values describing the response headers to modify or to remove. Each key in the `"responseHeaders"` object must correspond to an [HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers) name. Each object value has the following properties:
>
> | Property | Type | Description |
> |----------|------|-------------|
> | `"directives"` | `object[]` | List of response header directives to be modified. It's possible to remove a directive, to replace its value, or to append a value to its current value. |
> | `"remove"` | `boolean` | If `true`, the entire response header will be removed. |
>
> Each object in the `"directives"` array has the following properties:
>
> | Property | Type | Description |
> |----------|------|-------------|
> | `"action"` | `"append"` \| `"remove"` \| `"replace"` | Action to be performed on the directive. Set to `"remove"` to remove the directive. Set to `"replace"` to replace the current value. Set to `"append"` to append a value to the current directive value. When replacing or appending a value, it's required to specify a new value. |
> | `"name"` | `string` | Name of the directive to modify. |
> | `"value"` | `string` | New value for the directive. Required when replacing or appending a directive value. |
>
> The following example demonstrates how to configure **io.Connect Desktop** to modify the `Content-Security-Policy` response header for all web apps by appending a value to its `frame-ancestors` directive:
>
> ```json
> {
>     "windows": {
>         "responseHeaders": {
>             "Content-Security-Policy": {
>                 "directives": [
>                     {
>                         "name": "frame-ancestors",
>                         "action": "append",
>                         "value": "https://another-trusted-site.com/"
>                     }
>                 ]
>             }
>         }
>     }
> }
> ```
>
> To configure the behavior for handling the response headers per app, use the `"responseHeaders"` property of the `"details"` top-level key in the [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md).
>
> The following example demonstrates how to modify the `Content-Security-Policy` response header by removing a directive from it:
>
> ```json
> {
>     "details": {
>         "responseHeaders": {
>             "Content-Security-Policy": {
>                 "directives": [
>                     {
>                         "name": "frame-ancestors",
>                         "action": "remove"
>                     }
>                 ]
>             }
>         }
>     }
> }
> ```

> ### Preventing Multiple Workspace Instances
>
> By default, Workspace Layouts can be restored multiple times as multiple simultaneous instances. To control the behavior for allowing [multiple Workspace instances](https://docs.interop.io/desktop/capabilities/windows/workspaces/javascript/index.md#workspace-workspace_layouts-multiple_workspace_instances) dynamically, use the `allowMultiple` property of the [`WorkspaceLayoutSaveConfig`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspacelayoutsaveconfig/index.md) object when saving a Workspace Layout:
>
> ```javascript
> const config = {
>     name: "my-workspace",
>     workspaceId: "workspace-id",
>     // Prevent spawning multiple instances of this Workspace.
>     allowMultiple: false
> };
>
> await io.workspaces.layouts.save(config);
> ```
>
> > ⚠️ *Note that if the Workspace is saved in a [Global Layout](https://docs.interop.io/desktop/capabilities/windows/layouts/overview/index.md) and the `"restoreWorkspacesByReference"` property in the Workspaces App definition is set to `false`, the `allowMultiple` property won't have any effect when the Global Layout containing the Workspace is restored. This is valid irrespective of whether the property is used programmatically or in the Workspaces App definition. For more details, see the [Capabilities > Windows > Workspaces](https://docs.interop.io/desktop/capabilities/windows/workspaces/overview/index.md#extending_workspaces-configuration-restoring_workspaces) section.*

> ### Controlling the Workspace Loading Strategies Dynamically
>
> To retrieve the current [loading strategy](https://docs.interop.io/desktop/capabilities/windows/workspaces/javascript/index.md#workspace-loading_strategies) for a Workspace, use the `loadingStrategy` property of a [`Workspace`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspace/index.md) instance:
>
> ```javascript
> const myWorkspace = await io.workspaces.getWorkspace(workspace => workspace.id === "workspace-id");
>
> // Retrieving the loading strategy of a Workspace.
> const currentStrategy = myWorkspace.loadingStrategy;
> ```
>
> To set the loading strategy for a Workspace dynamically, use the [`setLoadingStrategy()`](https://docs.interop.io/desktop/reference/javascript/workspaces/workspace/index.md#Workspace-setLoadingStrategy) method of a `Workspace` instance and pass a [`LoadingStrategy`](https://docs.interop.io/desktop/reference/javascript/workspaces/loadingstrategy/index.md) value as a required argument:
>
> ```javascript
> const loadingStrategy = "lazy";
>
> await myWorkspace.setLoadingStrategy(loadingStrategy);
> ```
>
> Use the `setLoadingStrategy()` method to override the current loading strategy for the Workspace that may have been specified via configuration or programmatically when creating or restoring the Workspace.
>
> > ⚠️ *Note that the loading strategy specified via the `setLoadingStrategy()` method will be preserved in the Workspace Layout only if the Workspace is saved afterwards and the `"persistCurrentStrategy"` flag is set to `true` in the Workspaces App definition. For more details, see the [Capabilities > Windows > Workspaces](https://docs.interop.io/desktop/capabilities/windows/workspaces/overview/index.md#extending_workspaces-configuration-loading_strategies) section.*

> ### Protocol Handler Registration Control
>
> Dynamic protocol registration control may be useful if you need to register or unregister the protocol handlers conditionally depending on the environment in which the platform is running.
>
> To register or unregister all [protocol handlers](https://docs.interop.io/desktop/capabilities/more/features/index.md#global_protocol_handler) defined in the system configuration, invoke the already registered by the platform `"T42.GD.Execute"` Interop method and pass as an argument the `"register-protocol-handler"` or the `"unregister-protocol-handler"` command respectively:
>
> ```javascript
> // Registering the custom protocol handlers.
> await io.interop.invoke("T42.GD.Execute", { command: "register-protocol-handler" });
>
> // Unregistering the custom protocol handlers.
> await io.interop.invoke("T42.GD.Execute", { command: "unregister-protocol-handler" });
> ```

> ### Icon for Platform Instances Started via Protocol Handlers
>
> To specify an icon that will be used for the new platform instance started via a [protocol handler](https://docs.interop.io/desktop/capabilities/more/features/index.md#global_protocol_handler), use the `"iconPath"` property of the `"defaultExecutable"` object in the protocol handler configuration object:
>
> ```json
> {
>     "protocolHandler": [
>         {
>             "enabled": true,
>             "protocol": "custom",
>             "startNewInstance": {
>                 "enabled": true,
>                 "defaultExecutable": {
>                     "iconPath": "%GDDIR%/assets/images/my-icon.ico"
>                 }
>             }
>         }
>     ]
> }
> ```

> ### Command Line Arguments for ClickOnce Apps
>
> To specify command line arguments for a ClickOnce app, use the `"appParameters"` property of the `"details"` top-level key in the [app definition](https://docs.interop.io/desktop/developers/configuration/application/index.md). The `"appParameters"` property accepts as a value an object with key/value pairs describing the names and the values of the command line arguments to pass to the ClickOnce app:
>
> ```json
> {
>     "details": {
>         "appParameters": {
>             "parameter1": "value1",
>             "parameter2": "value2"
>         }
>     }
> }
> ```

> ### Timeouts for Publishing Telemetry Data
>
> To specify timeouts for awaiting [telemetry data](https://docs.interop.io/insights/configuration/io-connect-desktop/index.md) to be published before the io.Connect platform shuts down, use the following properties of the `"otel"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**:
>
> | Property | Type | Description |
> |----------|------|-------------|
> | `"finalExportGracePeriodMs"` | `number` | Interval in milliseconds to wait for any remaining telemetry data to be published by any apps before proceeding with the platform shutdown. Defaults to `0`. |
> | `"finalExportTimeoutMs"` | `number` | Interval in milliseconds to wait for any remaining telemetry data to be exported during shutdown of the platform. This is the maximum awaiting interval and the platform may shutdown before it expires if all telemetry data has already been published. Defaults to `0`. |
>
> The following example demonstrates configuring the timeouts for publishing telemetry data before the io.Connect platform shuts down:
>
> ```json
> {
>     "otel": {
>         "enabled": true,
>         "finalExportGracePeriodMs": 7000,
>         "finalExportTimeoutMs": 10000
>     }
> }
> ```

## Improvements & Bug Fixes

> - Upgraded to Electron 35.1.2 (Chromium 134).
>
> - It's now possible to use the Channels API in apps started outside the io.Connect platform. The only limitation is that it isn't possible to [prevent modifying the Channel restrictions](https://docs.interop.io/desktop/developers/configuration/application/index.md#channels) for such apps. This means that the `"preventModifyingRestrictionsFor"` property of the `"channelSelector"` object under the `"details"` top-level key in the app definition won't have any effect for apps started outside the io.Connect platform.
>
> - Improved behavior of resizing Workspace windows programmatically with the `setSize()` method of a `WorkspaceWindow` instance.
>
> - Improved reporting of the `"app_memory"` metric for closed app instances.
>
> - Improved the process for publishing telemetry data when the platform is shutting down.
>
> - Fixed an issue related to restoring Layout containing reusable apps when using web groups.
>
> - Fixed issues with showing and hiding the Notification Panel via API calls.

## Application Adapters

> ### Word Adapter
>
> #### Improvements & Bug Fixes
>
> - Improved the behavior for transferring large data chunks to a Word document.
>
> - Fixed an issue related to the io.Connect tab in the Word ribbon when displaying multiple registered Interop methods for handling data from Word.
