Glue42 Enterprise is now io.Connect Desktop! The new documentation site for all interop.io products is located at docs.interop.io.

Changelog

Glue42 Desktop

Release date: 07.03.2023

Components Version
Electron 22.0.0
Chromium 108.0.5359.62
Node.js 16.17.1

Breaking Changes

Workspaces Layouts API

The import() method of the Workspaces API accessible through the glue.workspaces.layouts object accepts as a second optional argument a string specifying the import mode - either "merge" or "replace".

Note that since Glue42 Enterprise 3.18, the default value for the mode argument is "replace" instead of "merge". If you don't specify the import mode, the imported Workspace Layouts will replace the existing one.

Until now, using the import() method without specifying a value for the mode argument resulted in merging the imported Workspace Layouts with the existing ones, replacing the ones with the same name, as the default value was "merge". From now on, if you want to merge the imported Workspace Layouts with the existing ones, you must explicitly specify the import mode, otherwise the imported Workspace Layouts will replace the existing ones:

const myWorkspaceLayouts = [];
const importMode = "merge";

// Specify explicitly that you want to merge the imported Workspace Layouts with the existing ones.
await glue.workspaces.layouts.import(myWorkspaceLayouts, importMode);

Glue42 Launchpad

Clients using the Glue42 Launchpad and upgrading to Glue42 Enterprise 3.18 must also update their @glue42/launchpad-ui library to the latest version in order to avoid problems with shutting down Glue42 Enterprise from the Launchpad app.

New Features

Feedback Form

The Feedback Form can now be completely customized using the @glue42/feedback-ui-react library. The library provides React hooks and default components that can be used, customized or entirely replaced when building your own custom Feedback App:

import React from "react";
import { Feedback, IssueReportingProvider } from "@glue42/feedback-ui-react";
import CustomHeader from "./CustomFooter";
import CustomBody from "./CustomFooter";
import CustomFooter from "./CustomFooter";

const App = () => {
    return (
        <IssueReportingProvider>
            <Feedback
                components={{
                    Header: CustomHeader,
                    Body: CustomBody,
                    Footer: CustomFooter
                }}
            />
        </IssueReportingProvider>
    );
};

export default App;

A Feedback App containing custom header, body and footer:

Custom Footer

Glue42 Dialogs

Glue42 Enterprise now offers default confirmation dialogs that will be shown on system shutdown or restart and when a window that prevents closing is about to be closed:

Default Dialogs

The default dialogs are configurable via the "dialogs" top-level key of the system.json system configuration file of Glue42 Enterprise. You can specify size for them, disable them, or provide a URL pointing to you own custom dialog app to be used by Glue42 Enterprise:

{
    "dialogs": {
        "url": "https://my-custom-dialog.com",
        "width": 380,
        "height": 150,
        "enableDefaultDialogs": {
            "preventShutdown": false,
            "preventWindowClose": false
        }
    }
}

To show dialogs programmatically, use the showDialog() method of the GDWindow object. It accepts a DialogOptions object as an argument in which you can specify dialog options - select a predefined Glue42 dialog type and fine-tune it, or create a completely customized one:

// Creating a custom dialog.
const myDialog = {
    type: "MyCustomDialog",
    title: "Custom Title",
    message: "Custom Message",
    size:{
        width: 300,
        height: 120
    },
    showAffirmativeButton: true,
    affirmativeButtonName: "Confirm",
};

await myWindow.showDialog(myDialog);

Prevent Closing Windows

Glue42 Windows can now prevent closing. The handler passed to the onClosing() method of the GDWindow object now accepts as an argument a prevent() function that can be used to prevent closing the window. This function accepts as an argument a PreventClosingOptions object in which you can specify whether to show a confirmation dialog to the user:

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

    prevent(options);
};

myWindow.onClosing(handler);

The close() method of the GDWindow object used for closing a window has been extended and now accepts a CloseOptions object as an argument in which you can specify whether to allow the window to prevent closing and whether to show a dialog to the user:

const options = {
    // Both options are set to `false` by default.
    allowPrevent: true,
    showDialog: true
};

await myWindow.close(options);

The close() method will override all window prevent close settings - e.g., if the close() method is invoked without any options in order to close a window that itself prevents closing with the onClosing() event handler, that window will be closed immediately and a confirmation dialog won't be shown to the user.

Notifications

Max Toasts

It's now possible to pass a negative value to the maxToasts property of the <Toasts /> component to allow the toasts wrapper to adjust dynamically to the number of active notifications to be displayed:

import React from "react";
import {
    NotificationsProvider,
    useNotificationsContext
} from "@glue42/notifications-ui-react";
import CustomPanel from "./CustomPanel";
import CustomToasts from "./CustomToasts";

const NotificationsWrapper = () => {
    const { isPanelVisible } = useNotificationsContext();

    // Set the `maxToasts` property to a negative value to allow the toasts wrapper
    // to adjust dynamically to the number of notifications to be displayed.
    return isPanelVisible ? <CustomPanel /> : <CustomToasts maxToasts={-1} />;
};

const App = () => {
    return (
        <NotificationsProvider>
            <NotificationsWrapper />
        </NotificationsProvider>
    );
};

export default App;

Toasts Wrapper

Closing the Notification Panel App

By default, the Notification Panel app will only be hidden when the user tries to close it. If you want the Notification Panel app to close instead of hide, set the hideOnClose property of the <Panel /> component to false:

import React from "react";
import { Panel } from "@glue42/notifications-ui-react";

const CustomPanel = () => {
    return <Panel hideOnClose={false} />
};

export default CustomPanel;

Native File Drag & Drop

The startDrag method of the GDWindow object allows you to save files from a web page to the OS when the user starts dragging a web page element. This is based on the Electron Native File Drag & Drop functionality. You can use this method as a handler for the "dragstart" event when the user starts to drag a web page element:

const myDraggableElement = document.getElementById("draggable");
const myWindow = glue.windows.my();
const myDragHandler = (event) => {
    event.preventDefault();

    const dragOptions = {
        type: "file",
        data: "file-data-as-a-string",
        filename: "my-file.txt"
    };

    await myWindow.startDrag(dragOptions);
};

myDraggableElement.addEventListener(myDragHandler);

Capturing Errors in Web Groups

You can now instruct Glue42 Enterprise to log errors from the Web Group App in the application.log file by using the "captureErrors" property of the "details" top-level key of the webGroup.json configuration file:

{
    "name": "web-group-app",
    "title": "Web Group App",
    "type": "webGroup",
    "hidden": true,
    "details": {
        "url": "http://localhost:3000/",
        "captureErrors": true
    }
}

Window Z-order

Glue42 Windows can now be set to always be on top of the Z-order, despite changes in visibility or joining the window to a window group. The setOnTop() method of the GDWindow object now accepts an "always" value which instructs the window to remain permanently on top of the Z-order:

await myWindow.setOnTop("always");

This behavior can also be achieved via app configuration using the "onTop" property of the "details" top-level key:

{
    "details": {
        "onTop": "always"
    }
}

Preserving the Size of Snapped Windows

The original size of a Glue42 Window can now be preserved when snapping it programmatically to another window. Use the autoAlign property of the SnappingOptions object passed to the snap() method of the GDWindow object to specify the desired behavior:

const targetID = "17508_3";
const options = { autoAlign: false };

await myWindow.snap(targetID, options);

Glue42 Window Runtime Configuration

The WindowsConfiguration object passed to the configure() method now has several additional properties that allow you to use more configuration options for the Glue42 Windows at runtime.

Approaching Distance

To configure the distance in pixels at which the approaching edges of Glue42 Windows will be highlighted indicating that the windows will be snapped together, use the approachingDistance property:

const config = { approachingDistance: 15 };

await glue.windows.configure(config);

Auto Align

To specify whether the size of a Glue42 Window should be aligned automatically to the neighboring windows, or should remain intact, when adding it to a Glue42 Window group, use the autoAlign property:

const config = { autoAlign: false };

await glue.windows.configure(config);

Feedback Button

To specify whether the "Feedback" button should be visible, use the showFeedbackButton property:

const config = { showFeedbackButton: true };

await glue.windows.configure(config);

Default Theme Synchronization

The default theme for Glue42 Enterprise can now be automatically synchronized with the default app mode in your OS through the system.json system configuration file. To specify your preference, use the "syncWithDefaultOSAppMode" property of the "themes" top-level key:

{
    "themes": {
        "syncWithDefaultOSAppMode": true
    }
}

Renaming Group & Window Captions

Renaming the captions of groups and Glue42 Windows participating in them that was previously possible only when using the Glue42 classic groups, is now possible also when using the Glue42 web groups:

Web Groups

Now you can also rename the captions of individual (not joined in a group) flat and tab Glue42 Windows. If you are using the Glue42 classic groups, you must allow this functionality first in the stickywindows.json configuration file of Glue42 Enterprise via the "enableWindowsCaptionEdit" property:

{
    "enableWindowsCaptionEdit": true
}

If your using the Glue42 web groups, then no configuration change is necessary.

Individual Windows

Default Global Layout

You can now disable automatically restoring the default Global Layout by using the "restoreDefaultGlobalOnStartup" property of the "layouts" top-level key in the system.json system configuration file of Glue42 Enterprise:

{
    "layouts": {
        "restoreDefaultGlobalOnStartup": false
    }
}

The default Global Layout can be restored programmatically at a later stage if necessary, using the Layouts APIs:

const defaultLayout = await glue.layouts.getDefaultGlobal();

if (defaultLayout) {
    await glue.layouts.restore(defaultLayout);
};

Client Certificates

Glue42 Enterprise can now be configured to remember client certificates (certificates used in private organizations for user identification) and reuse them for future requests if possible.

To specify the desired settings for the dialog that prompts the user to select a certificate, use the "clientCertificates" property of the "windows" top-level key in the system.json system configuration file of Glue42 Enterprise:

{
    "windows": {
        "clientCertificates": {
            "alwaysUseCheckbox": {
                "enabled": true,
                "checked": true
            }
        }
    }
}

Client Certificates

Channels JavaScript API

Added add() and remove() methods to the Channels JavaScript API that allow you to add or remove Channels at runtime:

const channelContext = { name: "Black", meta: { color: "black" } };

// Adding a new Channel.
const newChannelContext = await glue.channels.add(channelContext);

// Removing a Channel.
await glue.channels.remove("Black");

Note that new dynamically added Channels won't be persisted after restart of Glue42 Enterprise, unless they are recreated. A Channel that has been defined via configuration and is dynamically removed, will be restored on restart of Glue42 Enterprise.

App Management Java API

Added a myInstance() method for retrieving the current app instance:

Optional<ApplicationInstance> myInstance = glue.appManager().myInstance();

Added a registerShuttingDownHandler() for registering a handler that will be invoked when Glue42 Enterprise is about to shut down or restart:

glue.appManager().registerShuttingDownHandler(handler);

Proxy Settings

It's now possible to allow an app to manipulate proxy settings at runtime through the app configuration. Use the "allowProxySettingManipulation" property of the "details" top-level key:

{
    "details": {
        "allowProxySettingManipulation": true
    }
}

Proxy settings can be set from the glue42gd object attached to the global window object:

const settings = {
    useSystemSettings: false,
    url: "https://my-proxy-settings.com"
};

glue42gd.setProxySettings(settings);

Improvements and Bug Fixes

  • Upgraded to Electron 22 (Chromium 108).

  • Fixed a bug where sometimes an error dialog would appear when the user shuts down or restarts their machine with Glue42 Enterprise still running.

  • Fixed a bug where the mode argument of the Workspaces Layouts import() method wasn't taken into account.

  • Fixed a bug where the event for closing a notification toast wasn't published.

  • Minor improvements and bugfixes.