Changelog

io.Connect Desktop 9.5

Release date: 03.09.2024

Components Version
Electron 31.2.0
Chromium 126.0.6478.127
Node.js 20.15.0

New Features

Executing JavaScript Code in a Window

Executing JavaScript code within the context of the current or another io.Connect Window is disabled by default. To enable it, set the "allowScriptExecution" top-level key in the app definition to true:

{
    "allowScriptExecution": true
}

To execute code in the context of an io.Connect Window, use the executeCode() method of an IOConnectWindow instance. It accepts as a required argument the code to execute provided as a string. The method resolves with the result returned from the executed code, or rejects if the result of the code is a rejected Promise:

// Find the io.Connect Window in which you want to execute the code.
const ID = "2506_04";
const ioConnectWindow = io.windows.findById(ID);
// Provide the code to execute as a string.
const myCode = "(() => { return 42; })()";

const result = await ioConnectWindow.executeCode(myCode);

console.log(result);

Splash Screen

The io.Connect Desktop splash screen by default is shown always on top of any other windows. To disable this behavior, set the "alwaysOnTop" property of the "splash" top-level key in the system.json system configuration file to false:

{
    "splash": {
        "alwaysOnTop": false
    }
}

Telemetry Data

You can now instruct io.Connect Desktop what type of telemetry data to gather. To specify the desired telemetry data sets, use the "features" property of the "telemetry" top-level key in the system.json system configuration file:

The following example demonstrates how to instruct io.Connect Desktop to gather only system telemetry data:

{
    "telemetry": {
        "enabled": true,
        "features": {
            "apps": false,
            "stores": false,
            "system": true
        }
    }
}

The "features" object has the following properties:

Property Type Description
"apps" boolean If true, will enable publishing telemetry data related to web app performance.
"stores" boolean If true, will enable publishing telemetry data related to app stores.
"system" boolean If true, will enable publishing telemetry data related to system performance.

Boot Sequence Start & Completion Signals

To receive signals from io.Connect Desktop when a batch of apps with the same run priority starts and completes loading, register an Interop method and name it "T42.AppManager.AutoStart.Stage". If such method is registered, it will be invoked at the completion of the current priority batch, and then at the start and at the completion of all remaining run priority batches within the current and within all following boot sequence stages:

const methodName = "T42.AppManager.AutoStart.Stage";
const handler = ({ stage, phase, runPriority, apps }) => {
    console.log(`Run priority batch "${runPriority}" in stage "${stage}" is ${phase === "stageStarting" ? "starting" : "completed"}.`);

    console.log(`Apps: ${apps}`);
};

await io.interop.register(methodName, handler);

Each invocation of the method will return data in the shape of an object with the following properties:

Property Type Description
apps string[] List of names of the apps participating in the current run priority batch.
phase "stageStarting" | "stageCompleted" Indicates whether the current run priority batch of apps > is starting to load or has completed loading.
runPriority number The run priority value of the current app batch.
stage "core" | "pre-sso" | "post-sso" | "user" The name of the current boot sequence stage.

Log Appenders per App

By default, io.Connect Desktop uses a multiFile appender named "applications" for logging events related to io.Connect client apps. To define separate log appenders per app, execute the following steps:

  1. Define a log appender to be used for your app:
{
    "appenders": {
        "my-app-appender": {
            "type": "file",
            "filename": "%GLUE-USER-DATA%/logs/my-app.log",
            "maxLogSize": 10485760,
            "backups": 5,
            "minLevel": "info",
            "keepFileExt": true,
            "compress": true
        }
    }
}
  1. Create a category with the name of your app as defined in its app definition and assign the log appender to it. This will instruct io.Connect Desktop to use the specified log appender for your app:
{
    "categories": {
        "my-app": {
            "appenders": [
                "my-app-appender"
            ],
            "level": "trace"
        }
    }
}

Controlling Dropping Windows in Workspaces

To specify programmatically whether an io.Connect Window can be dropped in a Workspace, use the setAllowWorkspaceDrop() method of an IOConnectWindow instance. It accepts a Boolean value as an argument determining whether the user will be able to drop the current window in a Workspace:

// Preventing the user from dropping the window in a Workspace.
await myWindow.setAllowWorkspaceDrop(false);

To check whether the current window can be dropped in a Workspace, use the allowWorkspaceDrop property of the io.Connect Window object:

const canBeDropped = myWindow.allowWorkspaceDrop;

console.log(`The current window ${canBeDropped ? "can" : "can't"} be dropped in a Workspace.`);

Pinning & Unpinning Tabs for Web Groups

The tabs of io.Connect Windows in web groups can now be pinned. Pinned tabs are placed before the regular tab windows and they contain only the window title. Pinned tab windows don't have a "Close" button, effectively preventing the user from closing them:

Pinned Tab

⚠️ Note that pinning and unpinning window tabs is available only for tab windows in web groups.

To make your tab window pinned via configuration, use the "isPinned" property of the "details" top-level key in the app definition:

{
    "details": {
        "isPinned": true
    }
}

To pin and unpin tab windows programmatically, use the pin() and unpin() methods of an IOConnectWindow instance:

// Pins the tab of the current window.
await myWindow.pin();

// Unpins the tab of the current window, reverting it to a normal tab with a "Close" button.
await myWindow.unpin();

To check whether a tab window is pinned, use the isPinned property of the io.Connect Window object:

const isPinned = myWindow.isPinned;

console.log(`The tab window is ${isPinned ? "pinned": "not pinned."}.`);

Drag Mode for Windows in Workspaces

By default, when the user starts to drag a window participating in a Workspace, the window is ejected from the Workspace. The user can drop it outside the Workspace or back inside the Workspace. To change this behavior, use the "windowDragMode" property of the "details" top-level key in the Workspaces App configuration. It accepts "autoEject" (default) or "keepInside" as values.

The following example demonstrates how to prevent the Workspaces App from ejecting the windows in a Workspace when the user drags them:

{
    "details": {
        "windowDragMode": "keepInside"
    }
}

To set the window drag mode for an existing Workspace programmatically, use the setWindowDragMode() method of a Workspace instance:

// Windows won't be ejected from the Workspace when the user drags them.
await myWorkspace.setWindowDragMode("keepInside");

To check the current window drag mode setting of an existing Workspace, use the windowDragMode property of the Workspace object:

const dragMode = myWorkspace.windowDragMode;

To specify the window drag mode when creating a Workspace, use the windowDragMode property of the config object in the WorkspaceDefinition:

const definition = {
    config: {
        title: "My Workspace",
        windowDragMode: "keepInside"
    }
};

const myWorkspace = await io.workspaces.createWorkspace(definition);

Channel Restrictions

Subscribing for Channel Restriction Changes

To get notified when the Channel restrictions for any window have changed, use the onChannelRestrictionsChanged() method and provide a handler for the event. The handler will receive as arguments the current set of Channel restrictions and the ID of the window for which the Channel restrictions have changed:

const handler = (restrictions, windowID) => {
    console.log(`Channel restrictions changed for window with ID: "${windowID}"`);
    console.log(restrictions.channels);
};

const unsubscribe = io.channels.onChannelRestrictionsChanged(handler);

Preventing Apps from Modifying Channel Restrictions

To prevent an app from modifying Channel restrictions, use the "preventModifyingRestrictionsFor" property of the "channelSelector" object under the "details" top-level key in the app definition. Provide the names of the Channels whose restrictions the app won't be able to modify:

{
    "details": {
        "channelSelector": {
            "preventModifyingRestrictionsFor": ["Red", "Green"]
        }
    }
}

⚠️ Note that the "preventModifyingRestrictionsFor" property is valid only for apps of type "window", "exe", "clickonce", "childWindow" and "citrix".

Electron Cache

The "copy" property of the "cache" object under the "folders" top-level key in the system.json system configuration file of io.Connect Desktop can now accept either an object or a Boolean value.

To specify a location from where to copy the Electron cache from the closest previously installed io.Connect Desktop version and add it to the cache files for the upgraded version of io.Connect Desktop, use the "path" property of the "copy" object. Provide an absolute path pointing to the location of the Electron cache you want to migrate:

{
    "folders": {
        "cache": {
            "copy": {
                "path": "%LocalAppData%/MyElectronCache/"
            }
        }
    }
}

Notifications API

Added methods for snoozing, clearing, and updating the state of multiple notifications at a time - snoozeMany(), clearMany(), and setStates():

// List of IDs of the notifications to snooze, to clear, or whose states to set.
const notificationIDs = notifications.map(notification => notification.id);

// Snoozing multiple notifications.
const snoozeDurationMS = 600000;

await io.notifications.snoozeMany(notificationIDs, snoozeDurationMS);

// Setting the state of multiple notifications.
const notificationState = "Seen";

await io.notifications.setStates(notificationIDs, notificationState);

// Clearing multiple notifications.
await io.notifications.clearMany(notificationIDs);

Improvements & Bug Fixes

  • Improved support for adding additional apps during a boot sequence stage.

  • Improved handling theme changes for the web page search triggered with CTRL + F.

  • Added an error message displayed in the io.Connect launcher UI when a Layout fails to save.

  • Improved handling of opening windows with invalid values for width and height when using the browser native window.open() method.

  • Improved handling invocations of Interop methods when an Interop server has been removed.

  • Improved tab drag and move behavior in web groups.