Changelog

io.Connect Desktop 9.2

Release date: 20.02.2024

Components Version
Electron 28.1.4
Chromium 120.0.6099.216
Node.js 18.18.2

New Features

Search API Documentation

Added documentation for the JavaScript Search API exposed via the @interopio/search-api library. The Search API enables you to create both search providers and search clients. Search providers are apps that respond to search queries, whereas search clients are apps that initiate searches.

The following example demonstrates enabling the Search API:

import IODesktop from "@interopio/desktop";
import IOSearch from "@interopio/search-api";

const config = {
    libraries: [IOSearch]
};

const io = await IODesktop(config);

// Now you can access the Search API through `io.search`.

Download Manager

The io.Connect Download Manager is a central place for managing all downloads. Users can pause, resume or cancel downloads from it, open the location of a downloaded file, clear the list of downloads or remove individual items from it, search for downloads, set the default location for downloading files. The Download Manager can be started via a configurable keyboard shortcut (CTRL + J by default), and can also be configured to open automatically when a download is initiated.

Download Manager

To configure the Download Manager, use the "downloadManager" top-level key in the system.json system configuration file of io.Connect Desktop.

The following example demonstrates how to change the default shortcut for the Download Manager and configure it to auto start when a download is initiated:

{
    "downloadManager": {
        "autoStartOnDownload": true,
        "shortcut": "ctrl+alt+d"
    }
}

The "downloadManager" object has the following properties:

Property Type Description
"appName" string Name of an io.Connect app, as specified in its definition, to be used as a Download Manager. Defaults to "io-connect-download-manager".
"autoStartOnDownload" boolean If true, the Download Manager app will be started automatically when a download is initiated. Defaults to false.
"shortcut" string Shortcut for starting the Download Manager app. Defaults to "ctrl+j".

Using Downloads Programmatically

To manage downloads programmatically, use the downloads property of the iodesktop object attached to the global window object. You can retrieve and set the download location, get a list of all download items, clear the downloads list, manipulate individual download items (pause, resume, remove), open the location of downloaded items, and get notified when the state of a download item changes or a chunk of it has been downloaded.

The following example demonstrates how to retrieve a list of all download items, pause or resume items, and remove items from the download list:

// Retrieve a list of all download items.
const downloads = await iodesktop.downloads.list();

const itemID = downloads[0].id;

// If the download is paused, it will be resumed and vice versa.
await iodesktop.downloads.pauseResume(itemID);

// Remove the download item from the downloads list.
await iodesktop.downloads.removeItem(itemID);

Cloning Windows

⚠️ Note that this feature is available only for web groups.

Cloning allows you to duplicate io.Connect Windows with their current state. Windows can be cloned programmatically or by enabling the "Clone" button for end users. If the cloned window is a tab window, it will be added to the same tab group. All other types of windows will be cascaded:

Cloning Windows

The "Clone" button is disabled by default and can be enabled or disabled globally via the system configuration or per app via the app definition.

To enable the "Clone" button globally for all io.Connect Windows, use the "showCloneButton" property of the "windows" top-level key in the system.json file:

{
    "windows": {
        "showCloneButton": true
    }
}

To enable the "Clone" button for an app, use the "showCloneButton" property of the "details" top-level key in the app definition:

{
    "details": {
        "showCloneButton": true
    }
}

To clone a window programmatically, use the clone() method of an IOConnectWindow instance and optionally pass an ApplicationStartOptions object as an argument:

// Optional settings for the cloned window.
const options = { mode: "flat" };

await myWindow.clone(options);

Notification Settings

The "Notification Settings" section in the Notification Panel now allows users to set the position of the Notification Panel and the notification toasts on the screen:

Notification Settings

To specify default positions for the Notification Panel and the notification toasts, use the "placement" property of the "notifications" top-level key in the system.json system configuration file of io.Connect Desktop:

{
    "notifications": {
        "placement": {
            "panel": "left",
            "toasts": "top-left"
        }
    }
}

You can also set the position of the Notification Panel and the notification toasts programmatically with the configure() method. Use the placement property of the Configuration object passed as an argument:

const config = {
    placement: {
        panel: "left",
        toasts: "top-left"
    }
};

await io.notifications.configure(config);

Intents

Added a getIntents() method to the Intents API for retrieving Intents associated with an Intent handler. Added a filterHandlers() method for filtering Intent handlers based on specified criteria. The HandlerFilter object passed as a required argument allows you to specify whether the Intents Resolver UI app will open when there are more than one available Intent handlers in order to display them to the user:

// Retrieving Intents for an Intent handler.
const intents = await io.intents.find("ShowChart");
const handler = intents[0].handlers[0];

const intentsResult = await io.intents.getIntents(handler);
// The `getIntents()` method resolves with an object with an `intents` property holding a list of `IntentInfo` objects.
intentsResult.intents.forEach(console.log);

// Filtering Intent handlers.
const filter = {
    intent: "ShowChart",
    openResolver: false
};

const handlersResult = await io.intents.filterHandlers(filter);
// The `filterHandlers()` method resolves with an object with a `handlers` property holding a list of `IntentHandler` objects.
handlersResult.handlers.forEach(console.log);

Customizable Buttons for HTML Windows in Web Groups

Web Groups now offer full support for customizing the buttons of HTML windows. The HTML Buttons element that by default appears on hover and holds the default system buttons for windows with mode set to "html", can now be customized by using the html property of the components object in the <Group /> component:

import React from "react";
import Group, { HtmlButtons } from "@interopio/groups-ui-react";
import CustomButton from "./CustomButton";

const App = () => {
    return (
        <Group
            components={{
                html: {
                    Buttons: props => <> <CustomButton /> <HtmlButtons {...props} /> </>
                }
            }}
        />
    );
};

export default App;

Closing Event for Window Groups

⚠️ Note that this feature is available only for web groups.

The Group object now has an onClosing() method that notifies you when a window group is about to be closed. It accepts a callback as an argument which allows you to execute your custom logic before closing the window group. You can also prevent closing the group altogether via the prevent() function received as an argument by the callback. The callback will be awaited for 30 seconds before closing the group.

const handler = async (prevent) => {
    const options = { showDialog: false };

    prevent(options);
};

myGroup.onClosing(handler);

Using the Browser window.open() in Workspace Frames

The browser window.open() method can now be used from Workspace Frames as well.

For details on how to configure globally the behavior for handling the browser window.open() method, see the Developers > Configuration > System > Window Settings > Handling the Browser window.open() section.

Boot Sequence

A new "user" stage was added to the boot sequence configuration for apps under the "runPriority" top-level key in the app definition. At this stage, apps defined in the regular user-specific app stores and apps from the in memory store can be started.

The "waitForInitialization" property now accepts the following values, in addition to a boolean value:

Value Description
"interopReady" The platform will be automatically signaled when the Interop library has been fully initialized. Default for apps defined in regular user-specific app stores.
"appSignal" The app must explicitly send a signal to the platform that the necessary initialization has been completed.
"no" The platform won't wait for the app to initialize before continuing the boot sequence. Default for apps defined in system app stores.

The following example demonstrates how to configure an app to be started at the "user" stage and to instruct the platform to wait for an explicit signal from the app that it's initialization has been completed:

{
    "runPriority": {
        "stage": "user",
        "priority": 101,
        "waitForInitialization": "appSignal"
    }
}

Web Apps Cache

io.Connect Desktop can now copy the Electron cache from its closest previously installed version when upgrading to a newer version. This enables you to preserve and transfer any browser data that may be important for your users to the upgraded version.

The "cache" property of the "folders" top-level key in the system.json system configuration file of io.Connect Desktop now accepts also an object with the following properties:

Property Type Description
"copy" boolean If true, the Electron cache from the closest previously installed io.Connect Desktop version will be copied and added to the cache files for the upgraded version of io.Connect Desktop. Defaults to false.
"location" string Location for the Electron cache. Accepts an absolute path, or a path relative to the location of the io.Connect Desktop executable file. You can use environment variables. Defaults to "%LocalAppData%/interop.io/io.Connect Desktop/Cache/%GLUE-ENV%-%GLUE-REGION%/".

The following example demonstrates how to define a custom location for the Electron cache and instruct io.Connect Desktop to copy the cache from the closest previously installed version:

{
    "folders": {
        "cache": {
            "copy": true,
            "location": "../MyCache/%GLUE-ENV%-%GLUE-REGION%/"
        }
    }
}

Reload Options for Web Apps

io.Connect Desktop can try to reload web apps in case of load failure. To specify options for reloading an app, use the "reloadOptions" property of the "details" top-level key in the app definition:

{
    "details": {
        "reloadOptions": {
            "maxAttempts": 5,
            "timeout": 2000
        }
    }
}

The "reloadOptions" object has the following properties:

Property Type Description
"maxAttempts" number Maximum number of times to attempt reloading the window.
"timeout" number Interval in milliseconds at which to attempt to reload the window.

URL Filtering for Web Apps

It's now possible to provide filters for allowed navigation URLs for the current window and allowed URLs when opening new windows from the current one.

To specify allowed navigation URLs for the current window, use the "allowed" property of the "navigation" object under the "details" top-level key in the app definition:

{
    "details": {
        "navigation": {
            "allowed": "^https:\/\/(www\\.)?my-org\\.com\\/"
        }
    }
}

To specify allowed URLs for opening new windows from the current window, use the "allowed" property of the "windowOpen" object under the "details" top-level key in the app definition:

{
    "details": {
        "windowOpen": {
            "allowed": "^https:\/\/(www\\.)?my-org\\.com\\/"
        }
    }
}

Background Throttling for Web Apps

Animations and timers for web apps running in the background can be throttled. Background throttling is enabled by default. To disable it, use the "backgroundThrottling" property of the "details" top-level key in the app definition:

{
    "details": {
        "backgroundThrottling": false
    }
}

Dialog for Saving Layout Changes

When the current Global Layout is modified and the user tries to restore another Global Layout, io.Connect Desktop will show a prompt that allows the user to either save or discard the changes for the current Layout before restoring the new one:

Unsaved Layout Changes Dialog

To enable or disable showing this dialog, use the "unsavedLayoutChanges" property of the "enableDefaultDialogs" object under the "dialogs" top-level key in the system.json system configuration file of io.Connect Desktop:

{
    "dialogs": {
        "enableDefaultDialogs": {
            "unsavedLayoutChanges": false
        }
    }
}

Persisting Data in Layouts for Web Apps

To persist data for web apps in Layouts, it's now recommended to use the "saveInLayout" property found under the "windows" top-level key in the system.json system configuration file of io.Connect Desktop, as well as under the "details" top-level key in the app definition.

The following example demonstrates how to configure io.Connect Desktop globally to persist the current URLs of web apps only when they participate in Global Layouts and Workspaces, and to persist the current window titles of web apps in all types of Layouts:

{
    "windows": {
        "saveInLayout": {
            "url": ["Global", "Workspace"],
            "title": true
        }
    }
}

The "saveInLayout" object has the following properties relevant to web apps:

Property Type Description
"title" boolean | string[] If true, the current window title will be saved for all Layout types. Alternatively, you can provide a list of Layout types for which the window title is to be saved. The possible string values are "Global", "Workspace" and "ApplicationDefault".
"url" boolean | string[] If true, the current window URL will be saved for all Layout types. Alternatively, you can provide a list of Layout types for which the window URL is to be saved. The possible string values are "Global", "Workspace" and "ApplicationDefault".

Persisting Data in Layouts for Native Apps

To persist data for native apps in Layouts, use the "saveInLayout" property found under the "windows" top-level key in the system.json system configuration file of io.Connect Desktop, as well as under the "details" top-level key in the app definition.

The following example demonstrates how to configure io.Connect Desktop globally to persist the command and the parameters with which native apps are started when they are saved in a Layout:

{
    "windows": {
        "saveInLayout": {
            "command": true,
            "parameters": true
        }
    }
}

The "saveInLayout" object has the following properties relevant to native apps:

Property Type Description
"command" boolean If true, when the app is saved in a Layout, the command with which it was started will be persisted. If the value of the "command" property in the app definition is changed, when the Layout is restored, the app will be started with the previously persisted command, and not the one in the current app definition.
"parameters" boolean If true, when the app is saved in a Layout, the parameters with which it was started will be persisted. If the value of the "parameters" property in the app definition is changed, when the Layout is restored, the app will be started with the previously persisted parameters, and not the ones in the current app definition.

FDC3 App Definitions

FDC3 2.0 app definitions stored in local app stores, or in memory, are now automatically converted to io.Connect app definitions.

Java API System Buttons

To enable or disable the default io.Connect system buttons, use the windowButtons() method when supplying options for registering your window in the io.Connect framework:

Window myWindow =
    io.windows()
        .register(handle, options -> {
            options.windowButtons(
                WindowButtons.builder()
                                .allowClose(true)
                                .allowCollapse(false)
                                .allowLockUnlock(true)
                                .allowMaximize(false)
                                .allowMinimize(false)
                                .build()
            )});

Improvements & Bug Fixes

  • Upgraded to Electron 28.1.4 (Chromium 120).

  • Fixed misalignment of loader text for Web Groups. The fix is available in the latest version of the @interopio/groups-ui-react library.

  • Improved initialization of .NET library related to a corner-case timeout exception.

  • Improved the functionality for preventing window close.

  • Improved the functionality for saving app context in the current Layout.

  • Fixed a scaling issue related to collapsing and expanding windows on 4K monitors.