# io.Connect Desktop

Source: https://docs.interop.io/browser/capabilities/desktop/index.html

## Overview

The [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) can be configured to constantly check for the presence of a locally installed **io.Connect Desktop**. If such an instance is discovered, the Main app and all of its [Browser Client](https://docs.interop.io/browser/developers/browser-client/overview/index.md) apps will attempt to switch their io.Connect connection to **io.Connect Desktop**. If this operation is successful, the **io.Connect Browser** environment will be able to fully interoperate with all **io.Connect Desktop** clients.

This enables **io.Connect Browser** projects to seamlessly integrate with **io.Connect Desktop** without disrupting any of the running [Browser Client](https://docs.interop.io/browser/developers/browser-client/overview/index.md) apps.

## Behavior

As soon as the [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) discovers a running instance of **io.Connect Desktop** and manages to connect to it, all current [Browser Client](https://docs.interop.io/browser/developers/browser-client/overview/index.md) apps follow suit. The connection switch is executed without the apps reloading or flickering and is completely invisible to the end user. However, changing the connection of an **io.Connect Browser** environment has numerous effects in all aspects of the io.Connect functionalities, explained in the following sections.

### Shared Contexts & Channels

Switching between an **io.Connect Browser** and an **io.Connect Desktop** connection is handled seamlessly for the [Shared Contexts](https://docs.interop.io/browser/capabilities/data-sharing/shared-contexts/index.md) library. If the [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) is configured to look for an **io.Connect Desktop** connection, it will monitor all shared contexts and will be aware of their latest state. Once a connection switch happens, the Main app will be the last one to reconnect, ensuring that the latest state of all shared contexts is restored. All shared context [subscriptions](https://docs.interop.io/browser/capabilities/data-sharing/shared-contexts/index.md#subscribing_for_context_updates) will be preserved and everything is executed without any visual interruption.

The [Channels](https://docs.interop.io/browser/capabilities/data-sharing/channels/index.md) are based on [Shared Contexts](https://docs.interop.io/browser/capabilities/data-sharing/shared-contexts/index.md). This provides full integration when connecting to **io.Connect Desktop**. Both an **io.Connect Browser** app and an **io.Connect Desktop** app listening for changes to the same Channel will be notified at the same time when the Channel data has been updated.

### Interop

Upon a connection change, the [Interop](https://docs.interop.io/browser/capabilities/data-sharing/interop/index.md) library will re-initiate and re-announce its current state. This means that all **io.Connect Browser** clients, including the [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md), will preserve their respective `peerId` and `instance` ID. All registered Interop [methods](https://docs.interop.io/browser/capabilities/data-sharing/interop/index.md#method_registration), [streams](https://docs.interop.io/browser/capabilities/data-sharing/interop/index.md#publishing_stream_data) and [subscriptions](https://docs.interop.io/browser/capabilities/data-sharing/interop/index.md#consuming_stream_data) will be preserved and carried over to the new connection.

### Apps, Windows & Workspaces

The functionality of the [App Management](https://docs.interop.io/browser/capabilities/app-management/index.md) and [Window Management](https://docs.interop.io/browser/capabilities/windows/window-management/index.md) libraries won't change in any way when an **io.Connect Browser** environment connects to an **io.Connect Desktop** instance. This means that the [`list()`](https://docs.interop.io/browser/reference/javascript/windows/api/index.md#API-list) method of the Window Management API will always return a collection consisting only of the currently opened **io.Connect Browser** windows, regardless of the connection state. The [`open()`](https://docs.interop.io/browser/reference/javascript/windows/api/index.md#API-open) method of the Window Management API and the [`start()`](https://docs.interop.io/browser/reference/javascript/app%20management/application/index.md#Application-start) method of an app instance will always open an **io.Connect Browser** window or start an **io.Connect Browser** app respectively when called from an **io.Connect Browser** app.

The same is applicable to the [Workspaces](https://docs.interop.io/browser/capabilities/windows/workspaces/overview/index.md) library. Calling any of the [Workspaces API](https://docs.interop.io/browser/reference/javascript/workspaces/api/index.md) methods from an **io.Connect Browser** app will always open, fetch data or manipulate an **io.Connect Browser** Workspace, regardless of whether or not the **io.Connect Browser** environment is connected to **io.Connect Desktop**.

### Notifications

There aren't any changes in the operation of the [Notifications](https://docs.interop.io/browser/capabilities/notifications/setup/index.md) library when connected to an **io.Connect Desktop** instance. All [raised notifications](https://docs.interop.io/browser/capabilities/notifications/notifications-api/index.md#raising_notifications) will be **io.Connect Browser** notifications, meaning they will be raised by the browser. However, keep in mind that if you set an [Interop method](https://docs.interop.io/browser/capabilities/data-sharing/interop/index.md#method_registration) as a handler for a [notification click](https://docs.interop.io/browser/capabilities/notifications/notifications-api/index.md#notification_click-interop_click_handler) or an [action button](https://docs.interop.io/browser/capabilities/notifications/notifications-api/index.md#notification_actions) of an **io.Connect Browser** notification, this method may also have been registered by an **io.Connect Desktop** app. Clicking on the notification or its action buttons will invoke all registered Interop methods with the same name, regardless of whether they have been registered by **io.Connect Browser** or by **io.Connect Desktop** apps. So, in a way, acting on an **io.Connect Browser** notification can have effects in **io.Connect Desktop**.

### Rejected Connections

The following describes the cases when a connection attempt to **io.Connect Desktop** may fail entirely or partially:

- When the [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) has started an **io.Connect Browser** app that uses an old version of the [`@interopio/browser`](https://www.npmjs.com/package/@interopio/browser) library. In this situation, the [Browser Client](https://docs.interop.io/browser/developers/browser-client/overview/index.md) app won't be able to handle the connection switch instructions of the Main app. As a result, the Main app will either ignore this app and proceed with the connection switch or will cancel the connection switch attempt. This is determined by the `forceIncompleteSwitch` setting when configuring the connection settings in the Main app (see the [Configuration](#configuration) section).

- When the [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) is rejected by **io.Connect Desktop** based on origin filtration or a custom authentication mechanism. In this situation, the **io.Connect Browser** environment won't attempt to transfer the [Browser Client](https://docs.interop.io/browser/developers/browser-client/overview/index.md) apps and will cancel the reconnection attempt. However, the cycle for discovering **io.Connect Desktop** instances will continue, meaning that the Main app will periodically attempt a connection.

- When the connection request of the [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) is accepted by **io.Connect Desktop**, but the connection request of a [Browser Client](https://docs.interop.io/browser/developers/browser-client/overview/index.md) app is rejected. This may happen due to origin filtration when the Main app and the Browser Client app have different origins or as a result of some other custom **io.Connect Desktop** authenticator. In this situation, the Main app will either ignore this app and proceed with the connection switch or will cancel the connection switch attempt. This is determined by the `forceIncompleteSwitch` setting when configuring the connection settings in the Main app (see the [Configuration](#configuration) section).

### Default Connection

If the **io.Connect Desktop** instance to which the **io.Connect Browser** environment is connected disappears, the **io.Connect Browser** environment will resume its default state and all [Browser Client](https://docs.interop.io/browser/developers/browser-client/overview/index.md) apps will fall back to the default **io.Connect Browser** connection to their respective Main app.

## Configuration

Enabling and configuring the discovery of **io.Connect Desktop** is executed entirely in the [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) during the [initialization](https://docs.interop.io/browser/developers/browser-platform/setup/index.md#initialization) of the [`@interopio/browser-platform`](https://www.npmjs.com/package/@interopio/browser-platform) library. Use the `connection` property of the configuration object to specify settings for the connection to **io.Connect Desktop**:

```javascript
import IOBrowserPlatform from "@interopio/browser-platform";

const config = {
    licenseKey: "my-license-key",
    connection: {
        preferred: {
            url: "ws://localhost:8385",
            auth:{
                username: "user",
                password: "password"
            },
            forceIncompleteSwitch: true,
            discoveryIntervalMS: 60000
        }
    }
};

const { io } = await IOBrowserPlatform(config);
```

The `preferred` property instructs the Main app that in addition to its own default connection, there is an additional one, whose availability is unknown, but is preferred if available. The `preferred` object has the following properties, of which only `url` is required:

| Property | Type | Description |
|----------|------|-------------|
| `auth` | `object` | Defines the authentication data that will be used when trying to connect to the **io.Connect Desktop** instance. If this property isn't provided, **io.Connect Browser** will attempt a connection with a dedicated **io.Connect Browser** authenticator. |
| `discoveryIntervalMS` | `number` | Interval in milliseconds at which the Main app will try to find a local **io.Connect Desktop** instance. Defaults to `15000`. |
| `forceIncompleteSwitch` | `boolean` | If `true`, the [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) will proceed and connect to **io.Connect Desktop** when some or all of its clients have been rejected, due to using outdated [`@interopio/browser`](https://www.npmjs.com/package/@interopio/browser) libraries or origin filtration. Defaults to `false`. |
| `url` | `string` | **Required.** A valid URL string pointing to the io.Connect Gateway to which to connect. |

> ⚠️ *Note that for an **io.Connect Browser** environment to be able to discover and connect to an **io.Connect Desktop** instance, the **io.Connect Desktop** Gateway must use a known port whose URL you must supply to the `url` property of the `preferred` object. Currently, an **io.Connect Browser** environment isn't able to discover an **io.Connect Desktop** instance configured to use a [dynamic port for the io.Connect Gateway](https://docs.interop.io/desktop/developers/configuration/system/index.md#dynamic_gateway_port).*

## Migrating to io.Connect Desktop

The [Main app](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) and all [Browser Client](https://docs.interop.io/browser/developers/browser-client/overview/index.md) apps can run in **io.Connect Desktop** without any code modification. The Main app will automatically detect that it's running in **io.Connect Desktop** and won't initialize any of its [Browser Platform](https://docs.interop.io/browser/developers/browser-platform/overview/index.md) logic - it will default to being a normal **io.Connect Desktop** client app. The Browser Client apps will also auto detect the environment and will initialize the [`@interopio/desktop`](https://www.npmjs.com/package/@interopio/desktop) library instead of [`@interopio/browser`](https://www.npmjs.com/package/@interopio/browser), with all necessary features enabled and set to the highest possible level (e.g., the Aplication Management API will be initialized in `"full"` mode) to ensure correct app functionality. This gives you the option to easily experiment with your apps running in a functionally richer environment with more integration options.

> ℹ️ *For more information, see the **io.Connect Desktop** [product page](https://interop.io/products/io-connect/) and the *io.Connect Desktop** [official documentation](https://docs.interop.io/desktop/getting-started/what-is-io-connect-desktop/general-overview/index.md).*

### Guide

1. Get a licensed copy of **io.Connect Desktop** and install it.

2. Make sure that **io.Connect Desktop** runs with auto injection on:

- Open the `system.json` configuration file located in the `<installation_location>\config` folder.

- Edit the `"autoInjectAPI"` property of the `"windows"` top-level key using the following configuration:

```json
{
    "windows": {
        "autoInjectAPI": {
            "enabled": true,
            "version": "6.*",
            "autoInit": false
        }
    }
}
```

> ℹ️ *For more details on configuring **io.Connect Desktop**, see the [Developers > Configuration > System](https://docs.interop.io/desktop/developers/configuration/system/index.md) section in the **io.Connect Desktop** documentation.*

3. Create a definition file for your app. Use the following template and change the `"name"`, `"title"` and `"url"` properties with the details of your app:

```json
[
    {
        "title": "io.Connect Browser App",
        "type": "window",
        "name": "browser-app",
        "details": {
            "url": "http://localhost:4242/",
            "top": 100,
            "left": 200,
            "width": 600,
            "height": 300,
            "mode": "tab"
        }
    }
]
```

Save the configuration file in JSON format and place it in the app definitions folder. Usually, this is the `%LocalAppData%\interop.io\io.Connect Desktop\UserData\<ENV-REG>\apps` folder where `<ENV-REG>` should be replaced with the region and environment folder name used for the deployment of your **io.Connect Desktop** - e.g., `DEMO-INTEROP.IO`.

> ℹ️ *For more details on configuring an interop-enabled app in **io.Connect Desktop**, see the [Developers > Configuration > Application](https://docs.interop.io/desktop/developers/configuration/application/index.md) section in the **io.Connect Desktop** documentation.*

4. Start **io.Connect Desktop** and open your app from the io.Connect launcher.

### Using io.Connect Desktop Features

If you want to keep your app running in both environments and also use features that are specific to **io.Connect Desktop**, you must check in your code in which environment your app is running.

For example, you may want to register a global hotkey shortcut using the [Hotkeys API](https://docs.interop.io/desktop/reference/javascript/hotkeys/api/index.md) that is only available in **io.Connect Desktop**. Use the `iodesktop` or the `iobrowser` objects that are automatically injected in the global `window` object on startup of **io.Connect Desktop** or **io.Connect Browser** respectively to determine in which environment your app is running:

```javascript
// Check whether the app is running in io.Connect Desktop in order to use the Hotkeys API.
if (typeof iodesktop !== "undefined") {

    // Define a hotkey object.
    const hotkeyClientDetails = {
        hotkey: "shift+alt+c",
        description: "Open Client Details"
    };

    // Define a hotkey handler.
    const handler = (details) => {
        // This function will be invoked when the hotkey is used.
        console.log("Shortcut has been used.");
    };

    // Register the hotkey.
    await io.hotkeys.register(hotkeyClientDetails, handler);
} else if (typeof iobrowser !== "undefined") {
    // Running in io.Connect Browser, will fall back to in-page shortcuts.
};
```

If you are using TypeScript, cast your [`@interopio/browser`](https://www.npmjs.com/package/@interopio/browser) API to the [`@interopio/desktop`](https://www.npmjs.com/package/@interopio/desktop) API to get better types:

```typescript
// Import the types.
import { IOConnectDesktop } from "@interopio/desktop";

if (typeof iodesktop !== "undefined") {
    // Running in io.Connect Desktop, you can now use io.Connect Desktop specific APIs.
    const ioConnect = io as IOConnectDesktop.API;
};
```
