Changelog
io.Connect Browser 3.4
Release date: 05.09.2024
Versions of all main and additional libraries of io.Connect Browser for the current release:
Library | Version |
---|---|
@interopio/browser |
3.4 |
@interopio/browser-platform |
3.4 |
@interopio/browser-worker |
3.4 |
@interopio/cli |
1.4 |
@interopio/fdc3 |
2.4 |
@interopio/home-ui-react |
1.4 |
@interopio/intents-resolver-api |
2.4 |
@interopio/intents-resolver-ui-react |
1.0 |
@interopio/ng |
4.4 |
@interopio/react-hooks |
3.4 |
@interopio/search-api |
2.4 |
@interopio/widget |
1.1 |
@interopio/workspaces-api |
3.4 |
@interopio/workspaces-ui-react |
3.4 |
New Features
⚠️ Note that each new feature is listed under all libraries it affects.
@interopio/browser
- Added configuration for the
allow
attribute of the<iframe>
element in which the app will be started when opened in a Workspace:
const definitions = [ // App definition. { name: "my-app", type: "window", details: { url: "https://example.com", // Permissions policy for the `<iframe>` element in which the app will be started when opened in a Workspace. iframePermissionsPolicy: { // List of flags that will be applied to the `allow` attribute of the `<iframe>` element. flags: "geolocation 'self' https://a.example.com https://b.example.com; fullscreen 'none'" } } } ]; await io.appManager.inMemory.import(definitions);
- Updated the methods of the io.Connect Channels API to be able to send and receive FDC3 context data in order to facilitate using FDC3 User Channel contexts in non-FDC3 interop-enabled apps.
The
data
object in aChannelContext
object may now contain anfdc3
property if FDC3 context data has been published to the Channel. This allows non-FDC3 interop-enabled apps to use FDC3 User Channel contexts more easily. The optionalfdc3
property is an object with a requiredtype
property holding the type of the FDC3 context. This is valid for all methods of the Channels API that utilize theChannelContext
object in any way:
// Example of accessing FDC3 context data by using the `get()` method. // The `ChannelContext` returned by `get()` will contain a `data.fdc3` property if FDC3 context data has been published to the Channel. const context = await io.channels.get("Red"); if (context.data.fdc3) { // The `type` property of the `fdc3` object is required. const contextType = context.data.fdc3.type; console.log(contextType); }; // Example of subscribing for FDC3 context data by using the `subscribe()` method. // The `data` argument received by the callback will have an `fdc3` property if FDC3 context data has been published to the Channel. const handler = (data) => { if (data.fdc3) { // The `type` property of the `fdc3` object is required. const contextType = data.fdc3.type; console.log(contextType); }; }; const unsubscribe = io.channels.subscribe(handler);
The
publish()
method of the Channels API now accepts also aPublishOptions
object as a second optional argument. You can use it to specify the name of the Channel to update and whether the published data is FDC3 context data. This allows non-FDC3 interop-enabled apps to work with FDC3 contexts more easily:
// FDC3 context data to publish. const data = { type: "fdc3.contact", name: "John Doe", id: { email: "john.doe@example.com" } }; const options = { name: "Red", // Specify that the published data is FDC3 context data. fdc3: true }; await io.channels.publish(data, options);
The
get()
,getMy()
,subscribe()
, andsubscribeFor()
methods for retrieving and subscribing to Channel contexts now accept anFDC3Options
object as an optional argument. You can use this argument to specify the type of the FDC3 context in which you are interested. Theget()
andgetMy()
methods will resolve with an empty object if FDC3 context data of the specified type isn't available in the Channel. The callback passed to thesubscribe()
andsubscribeFor()
methods won't be invoked unless FDC3 context data of the specified type is published in the Channel:
// Specifying the type of an FDC3 context. const fdc3Options = { contextType: "fdc3.contact" }; // Retrieving an FDC3 context of a specific type. const fdc3Context = await io.channels.getMy(fdc3Options); // Subscribing to an FDC3 context of a specific type. const handler = (data) => { // The `type` property of the `fdc3` object is required. const contextType = data.fdc3.type; console.log(contextType); }; const unsubscribe = io.channels.subscribe(handler, fdc3Options);
- To clear all previously saved Intent handlers, use the
clearSavedHandlers()
method of the Intents API. To remove a saved handler for a specific Intent, use theclearSavedHandler
property of theIntentRequest
object when raising the Intent:
const intentRequest = { name: "ShowChart", // Clearing a previously saved handler for this Intent. clearSavedHandler: true }; await io.intents.raise(intentRequest); // Clearing all saved handlers for all previously raised Intents. await io.intents.clearSavedHandlers();
@interopio/browser-platform
- io.Insights now comes as a built-in feature of io.Connect Browser. io.Insights is disabled by default. To enable it and configure its features in io.Connect Browser, use the
otel
property of the configuration object when initializing your Main app:
import IOBrowserPlatform from "@interopio/browser-platform"; const config = { licenseKey: "my-license-key", // Enabling io.Insights and providing settings for publishing data. otel: { metrics: { url: "http://localhost:4242/my-metrics-collector", metrics: [ { type: "app_error", enabled: false } ] } } }; const { io } = await IOBrowserPlatform(config);
- New configuration settings are available for adding extra headers to the requests sent to io.Manager, for caching and persisting data from io.Manager locally, and for the timeouts of the requests sent to io.Manager.
To add extra headers to the requests sent to io.Manager, use the
getHeaders
property of themanager
object. Provide a callback that will receive as an argument all current headers and will be invoked on each request to io.Manager. The following example demonstrates how to provide a callback that will obtain and add to the headers a valid access token on each request sent to io.Manager:
import IOBrowserPlatform from "@interopio/browser-platform"; // Callback for handling the request headers. const getHeaders = async () => { // Your custom internal logic for refreshing and retrieving the access token. const token = await getAccessToken(); const extraHeaders = { Authorization: `Bearer ${token}` }; // The returned headers will be merged with the existing ones. return extraHeaders; }; const config = { licenseKey: "my-license-key", manager: { url: "https://my-io-manager.com:4242/api", // Providing a callback that will be invoked on every request sent to io.Manager. getHeaders } }; const { io } = await IOBrowserPlatform(config);
To specify settings for caching data from io.Manager, use the
cache
property of themanager
object. Thecache
object has the following properties:
Property Type Description clearOld
boolean
If true
, on opening a new session to io.Manager, all cache databases from previous sessions will be deleted. Defaults tofalse
.enabled
boolean
If true
(default), will enable caching and persisting data from io.Manager locally (e.g., in case of connection interruptions).To specify settings for the timeouts of the requests sent to io.Manager, use the
requests
property of themanager
object. Therequests
object has the following properties:
Property Type Description closeSessionTimeout
number
Interval in milliseconds to wait for a response to the closeSession
request to io.Manager. Defaults to10000
.openSessionTimeout
number
Interval in milliseconds to wait for a response to the openSession
request to io.Manager before proceeding from cache. Defaults to10000
.timeout
number
Interval in milliseconds to wait for a response from io.Manager. Defaults to 10000
.
- Added global configuration for the
allow
attribute of the<iframe>
elements in Workspaces:
import IOBrowserPlatform from "@interopio/browser-platform"; import IOWorkspaces from "@interopio/workspaces-api"; const config = { licenseKey: "my-license-key", workspaces: { src: "https://my-workspaces-app.com", // Permissions policy for the `<iframe>` elements in a Workspace. iframePermissionsPolicy: { // List of flags that will be applied to the `allow` attribute of each `<iframe>` element in a Workspace. flags: "geolocation 'self' https://a.example.com https://b.example.com; fullscreen 'none'" } }, browser: { libraries: [IOWorkspaces] } }; const { io } = await IOBrowserPlatform(config);
- Added support for saving preferred Intent handlers.
- Exposed details about the initial caller of the Intents Resolver UI.
@interopio/fdc3
Updated the methods of the io.Connect Channels API to be able to send and receive FDC3 context data in order to facilitate using FDC3 User Channel contexts in non-FDC3 interop-enabled apps.
Added support for saving preferred Intent handlers.
@interopio/home-ui-react
- Redesigned and improved the initial platform setup. The platform will now initialize even if the user doesn't grant the necessary browser permissions. Added steps for pop-ups permission and for installing the Home App as a Progressive Web Apps (PWA). If you have created your custom Home App by using the io.Connect CLI, it will be fully configured as a PWA. If you are using the
@interopio/home-ui-react
library directly, you will have to configure your custom Home App as a PWA if you want to use it as such.
- Added a
<SystemLoader />
component to the library that can be used to customize the default loader of the Home App via thecomponents
property of theconfig
object for the<IOConnectHome />
component:
import { IOConnectHome, SystemLoader } from "@interopio/home-ui-react"; import { getConfig } from "./helpers"; import "@interopio/workspaces-ui-react/dist/styles/workspaces.css"; import "@interopio/home-ui-react/src/index.css"; const getIOConnectConfig = await getConfig(); // Configuration for the `<IOConnectHome />` component. const config = { getIOConnectConfig, components: { // Providing a custom icon for the default loader of the Home App. SystemLoader: () => <SystemLoader Logo={() => <span>My Logo</span>} /> } }; const App = () => { return <IOConnectHome config={config} /> }; export default App;
- Added the option for integrating a custom login procedure when using the Home App. When using a custom login procedure, you have to display your own login page to the user, authenticate them, and then display the
<IOConnectHome />
component and pass the user credentials to it:
import { useState } from "react"; import { IOConnectHome } from "@interopio/home-ui-react"; import { getConfig, authenticateUser, logOutUser } from "./helpers"; import MyLoginPage from "./MyLoginPage"; import "@interopio/workspaces-ui-react/dist/styles/workspaces.css"; import "@interopio/home-ui-react/src/index.css"; const App = () => { const [user, setUser] = useState(null); const config = { getIOConnectConfig: getConfig, // Settings for custom login. login: { // Type must be set to `"custom"`. type: "custom", // Provide details about the authenticated user. user: user: { id: user?.id, username: user?.username }, // Callback that will be invoked on logout of the platform. onLogout: () => { // Use your custom logic to log out the user. logOutUser(); setUser(null); } } }; const logInUser = async () => { // Use your custom logic to authenticate the user. const user = await authenticateUser(); if (user) { // Set the user object to provide an ID and a username for the Home App. setUser(user); }; }; // Display the Home App only if the user is logged in. return user ? <IOConnectHome config={config} /> : <MyLoginPage logInUser={logInUser} /> }; export default App;
- The Launchpad now won't be displayed in the Home App if the Home App isn't a Browser Platform app.
@interopio/intents-resolver-api
- Exposed information about the initial calling app of the Intents Resolver UI via the
caller
property of the Intents Resolver API. Thecaller
property returns aResolverCaller
object holding the ID, name and title of the calling app:
const caller = io.intents.resolver.caller;
The callbacks passed to the
onHandlerAdded()
andonHandlerRemoved()
methods now receive anIntentInfo
object as a second optional argument which you can use to obtain details about the Intent that the app can handle.The
sendResponse()
method now accepts aSendResolverResponseOptions
object as a second optional argument. You can use this object to save the chosen Intent handler as a handler for the raised Intent. If the Intents Resolver UI was opened via thefilterHandlers()
method instead of theraise()
method, you also have to specify the name of the Intent for which the handler will be saved:
const options = { saveHandler: true, // Providing the Intent name is necessary only when the Intents Resolver UI // was opened via the `filterHandlers()` method instead of the `raise()` method. name: "ShowChart" }; await io.intents.resolver.sendResponse(selectedIntentHandler, options);
@interopio/intents-resolver-ui-react
- Added the
@interopio/intents-resolver-ui-react
library which exports the<IOConnectIntentsResolverUI />
React component that can be used to create an Intents Resolver App.To use the library in your project, execute the following command:
npm install @interopio/intents-resolver-ui-react
Using the
<IOConnectIntentsResolverUI />
component:
import IOBrowser from "@interopio/browser"; import IOConnectIntentsResolver from "@interopio/intents-resolver-api"; import IOConnectIntentsResolverUI from "@interopio/intents-resolver-ui-react"; // The default styles for the Intents Resolver App must be imported. import "@interopio/intents-resolver-ui-react/styles"; // Provide the factory function for the `@interopio/intents-resolver-api` library. const config = { libraries: [IOConnectIntentsResolver] }; // Initialize the io.Connect API. const io = await IOBrowser(config); const domElement = document.getElementById("root"); const root = ReactDOM.createRoot(domElement); root.render( // Provide the initialized io.Connect API object to the component. <IOConnectIntentsResolverUI config={{ io }} /> );
@interopio/widget
- Added a
displayInWorkspace
property to thewidget
object for configuring the io.Connect widget. If set totrue
, the widget will be displayed in the app even if the app is currently inside a Workspace:
import IOBrowser from "@interopio/browser" import IOBrowserWidget from "@interopio/widget"; import "@interopio/widget/styles"; const config = { libraries: [IOBrowserWidget], widget: { displayInWorkspace: true } }; const io = await IOBrowser(config);
Improvements & Bug Fixes
⚠️ Note that each improvement or bug fix is listed under all libraries it affects.
@interopio/browser
- Added error events and event handlers for platform and client errors.
@interopio/browser-platform
- Added error events and event handlers for platform and client errors.
- Fixed controller variable error that was causing a reference error.
@interopio/fdc3
- Improved handling of dynamic registration of Intent handlers.
- Changed log level to warn instead of error when
broadcast()
is used while not joined to a Channel.
@interopio/home-ui-react
- Improved handling permission and user check when the window isn't a Browser Platform.
- Improved instructions for the notifications permission prompt if it's automatically blocked by the browser.
- Fixed
useBeforeunload()
firing on logout.
@interopio/intents-resolver-api
- Optimized the type of the
IOConnectIntentsResolver()
factory function.- Added
@interopio/browser
as a dependency.
@interopio/widget
- Added a check to prevent the widget from showing in an app if the app is a Workspaces App acting as a Main app.
- Fixed a bug where Channels wouldn't be displayed when switching from default to compact mode.
- Improved types.