Skip to content

Commit

Permalink
Updating 19.1 beta to support modular platform overrides (#741)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnman authored Aug 30, 2024
1 parent 8d46d0d commit 0b8cd32
Show file tree
Hide file tree
Showing 53 changed files with 3,816 additions and 1,255 deletions.
47 changes: 0 additions & 47 deletions how-to/integrate-with-snap/client/src/preload.ts

This file was deleted.

7 changes: 6 additions & 1 deletion how-to/workspace-platform-starter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## v19.1.0

- Breaking Change (if you do not update your manifest): Added modules as an option for platformProvider settings and made the workspace platform starter platform override a module (so you can decide to load it, chain it with other overrides or exclude it). Please see the new document [how to customize your platform override](./docs/how-to-customize-your-platform-override.md). If you want the default platform override to check endpoints to for saving/fetching workspaces and pages then you need to add the default-wps-platform module id to the endpoint clients array in the endpointProvider (see the manifest.fin.json as an example).
- Updated module ids for default interop override to reflect new naming of modules for platform override: default-wps-interop instead of wps-interop-override.

## v19.0.0

- Updated manifests to remove verbose logging --v=1 --inspect from the runtime.arguments setting: <https://developers.openfin.co/of-docs/docs/debugging#verbose-logging>
- Updated manifests to disable app logging (where console log entries are written to disk). You can still see console log messages in dev tools or you can turn it back on by setting enableAppLogging to true.
- Added new v38 runtime setting appLogsTimezone and set it to utc for when you do capture logs to disk.
Expand All @@ -28,7 +33,7 @@
- Updated: modules/composite/default-workspace/lifecycle logic to listen out for the new `apply` action.
- Improved performance of switching schemes
- Improved performance of computing dock configuration, especially on theme changes.
- Breaking Change (if you do not update your manifest): Added modules as an option for platformProvider.interop settings and made the workspace platform starter interop override a module (so you can decide to load it, chain it with other overrides or exclude it). Please see the new document [how to customize your interop broker](./docs/how-to-customize-your-interop-broker.md). If you want the default interop broker to check endpoints to see if a context type should be enriched through an endpoint then you need to add the wps-interop-override module id to the endpoint clients array in the endpointProvider (see the manifest.fin.json as an example).
- Breaking Change (if you do not update your manifest): Added modules as an option for platformProvider.interop settings and made the workspace platform starter interop override a module (so you can decide to load it, chain it with other overrides or exclude it). Please see the new document [how to customize your interop broker](./docs/how-to-customize-your-interop-broker.md). If you want the default interop broker to check endpoints to see if a context type should be enriched through an endpoint then you need to add the default-wps-interop module id to the endpoint clients array in the endpointProvider (see the manifest.fin.json as an example).
- Added support for a title to be specified in the browserProvider that will be used as the platform name in the browser Quit menu option and the confirmation dialog.

## v17.2.0
Expand Down
1 change: 1 addition & 0 deletions how-to/workspace-platform-starter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The information below provides information related to configuring and using the
| [Add Intent Support To Your App](./docs/how-to-add-intent-support-to-your-app.md) | If you have added one or more apps to your platform you may want one to trigger a workflow in another using FDC3. |
| [Configure Your Platform's Intent Support](./docs/how-to-configure-fdc3-intents.md) | How to configure your platform's Intent support. What UI to present to the user if they have to make an application selection after an intent is raised. |
| [Add FDC3 Open Support To Your App](./docs/how-to-add-open-support-to-your-app.md) | If you have added one or more apps to your platform you may wish to have them easily opened using fdc3.open with the option of passing context. |
| [Customize Your Platform through Overrides](./docs/how-to-customize-your-platform-override.md) | You now have control over the platform logic beyond settings. You can use the default implementation that workspace platform starter provides, replace it or extend it without having to touch the main codebase. |
| [Customize Your Interop Broker](./docs/how-to-customize-your-interop-broker.md) | You now have control over the interop broker beyond settings. You can use the default implementation, replace it or extend it without having to touch the main codebase. |
| [Add Cloud Interop To Your Interop Broker](./docs/how-to-add-cloud-interop-to-your-interop-broker.md) | OpenFin supports sharing context across platforms and devices using our cloud offering. You can now easily add your cloud interop settings to our cloud interop module and simply enable it to see it in action. |
| [Use Notifications](./docs/how-to-use-notifications.md) | Your platform or you app(s) may want to get the end user's attention and capture a response. |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { createLogger } from "./logger-provider";
import { closedownModules, initializeModules, loadModules } from "./modules";
import type {
AnalyticsModule,
AnalyticsProviderOptions,
PlatformAnalyticsEvent
import {
MODULE_ANALYTICS_SOURCE,
type AnalyticsClient,
type AnalyticsModule,
type AnalyticsProviderOptions,
type ModuleAnalyticsEvent,
type PlatformAnalyticsEvent
} from "./shapes/analytics-shapes";
import type { ModuleEntry, ModuleHelpers } from "./shapes/module-shapes";

Expand Down Expand Up @@ -60,3 +63,40 @@ export async function handleAnalytics(events: PlatformAnalyticsEvent[]): Promise
await analyticsModule.implementation.handleAnalytics(events);
}
}

/**
* Get analytics client.
* @returns The analytics client.
*/
export async function getAnalyticsModuleClient(): Promise<AnalyticsClient | undefined> {
if (!isEnabled()) {
return;
}
return {
handleAnalytics: async (events: ModuleAnalyticsEvent[]): Promise<void> => {
if (Array.isArray(events)) {
const platformAnalyticEvents: PlatformAnalyticsEvent[] = events.map<PlatformAnalyticsEvent>(
(entry) => ({ ...entry, source: MODULE_ANALYTICS_SOURCE })
);
return handleAnalytics(platformAnalyticEvents);
}
}
};
}

/**
* Get analytics client for platform override use.
* @returns The analytics client.
*/
export async function getAnalyticsPlatformClient(): Promise<AnalyticsClient | undefined> {
if (!isEnabled()) {
return;
}
return {
handleAnalytics: async (events: PlatformAnalyticsEvent[]): Promise<void> => {
if (Array.isArray(events)) {
return handleAnalytics(events);
}
}
};
}
157 changes: 127 additions & 30 deletions how-to/workspace-platform-starter/client/src/framework/connections.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import type OpenFin from "@openfin/core";
import * as endpointProvider from "./endpoint";
import { launch } from "./launch";
import { createLogger } from "./logger-provider";
import { MANIFEST_TYPES } from "./manifest-types";
import type { PlatformApp } from "./shapes/app-shapes";
import type { ClientSnapshot, PlatformApp } from "./shapes/app-shapes";
import type {
AppSourceConnection,
Connection,
ConnectionClient,
ConnectionPayloadVerificationRequest,
ConnectionPayloadVerificationResponse,
ConnectionProviderOptions,
ConnectionValidationOptions,
ConnectionValidationResponse,
PlatformConnectionClient,
SnapshotSourceConnection
} from "./shapes/connection-shapes";
import { isEmpty, isStringValue, objectClone } from "./utils";
Expand Down Expand Up @@ -145,35 +148,6 @@ export function clearAction(actionName: string): boolean {
return true;
}

/**
* Get any connections that support apps.
* @returns The list of connections supporting apps.
*/
export async function getConnectedAppSourceClients(): Promise<
{
identity: OpenFin.Identity;
connectionData: AppSourceConnection;
}[]
> {
const connectionsToReturn: {
identity: OpenFin.Identity;
connectionData: AppSourceConnection;
}[] = [];

const availableConnections = Object.values(connectedClients);
for (const connection of availableConnections) {
const matchedConnection = connection.connectionTypes.find(
(supportedConnectionType) => supportedConnectionType.type === APP_SOURCE_TYPE_ID
);

if (matchedConnection?.type === APP_SOURCE_TYPE_ID) {
connectionsToReturn.push({ identity: connection.identity, connectionData: matchedConnection });
}
}

return connectionsToReturn;
}

/**
* Get any connected apps.
* @returns The list of connected apps.
Expand Down Expand Up @@ -345,6 +319,129 @@ export async function isConnectionValid<T>(
return responseToReturn;
}

/**
* Decorate a snapshot with the native window information.
* @param snapshot The snapshot to decorate.
* @returns The decorated snapshot.
*/
export async function decorateSnapshot(snapshot: OpenFin.Snapshot): Promise<OpenFin.Snapshot> {
const sources = await getConnectedSnapshotSourceClients();

if (sources.length === 0) {
return snapshot;
}

const clientSnapshots: (ClientSnapshot | undefined)[] = await Promise.all(
sources.map(async (entry) => {
const snapShotSource = await fin.SnapshotSource.wrap({ uuid: entry.identity.uuid });
try {
logger.info(`Snapshot source: ${entry.identity.uuid}. Requesting a snapshot.`);
const sourceSnapshot = (await snapShotSource.getSnapshot()) as Extract<"snapshot", ClientSnapshot>;
return { identity: entry.identity, snapshot: sourceSnapshot };
} catch {
logger.info(`Snapshot source: ${entry.identity.uuid} was not available.`);
}
})
);

const decoratedSnapshot: OpenFin.Snapshot = Object.assign(snapshot, {
clientSnapshots: clientSnapshots.filter((snapshotSource) => !isEmpty(snapshotSource))
});

return decoratedSnapshot;
}

/**
* Apply connected client to a snapshot.
* @param snapshot The snapshot.
*/
export async function applyClientSnapshot(
snapshot: OpenFin.Snapshot & { clientSnapshots?: ClientSnapshot[] }
): Promise<void> {
if (Array.isArray(snapshot?.clientSnapshots)) {
const sources = await getConnectedSnapshotSourceClients();
await Promise.all(
snapshot.clientSnapshots.map(async (clientSnapshot: ClientSnapshot) => {
if (clientSnapshot) {
if (sources.some((source) => source.identity.uuid === clientSnapshot.identity.uuid)) {
try {
const snapShotSource = await fin.SnapshotSource.wrap(clientSnapshot.identity);
logger.info(
`Snapshot source: ${clientSnapshot.identity.uuid} is running and has a snapshot entry. Applying snapshot.`
);
await snapShotSource.applySnapshot(clientSnapshot.snapshot);
} catch {
logger.warn(
`Snapshot source: ${clientSnapshot.identity.uuid} is not able to apply the snapshot.`
);
}
} else if (!isEmpty(clientSnapshot?.snapshot)) {
const sn = clientSnapshot?.snapshot;
const app: PlatformApp | undefined = sn?.App ?? sn?.app;
if (!isEmpty(app)) {
logger.info(
`Client not connected but snapshot contains an app definition. Launching app definition for ${clientSnapshot.identity.uuid}`
);
logger.debug("Client app definition:", app);
await launch(app);
}
} else {
logger.warn(
`Client snapshot was available but the source ${clientSnapshot.identity.uuid} was not connected and it didn't provide an app/App entry as part of the snapshot to trigger a launch.`
);
}
}
})
);
}
}

/**
* Returns a client that can be used by modules to interact with connections.
* @returns The connection client.
*/
export async function getConnectionClient(): Promise<ConnectionClient> {
return { isConnectionValid };
}

/**
* Returns a connection client to be passed to platform override modules.
* @returns The platform connection client.
*/
export async function getPlatformConnectionClient(): Promise<PlatformConnectionClient> {
const client = await getConnectionClient();
return { ...client, decorateSnapshot, applyClientSnapshot };
}

/**
* Get any connections that support apps.
* @returns The list of connections supporting apps.
*/
async function getConnectedAppSourceClients(): Promise<
{
identity: OpenFin.Identity;
connectionData: AppSourceConnection;
}[]
> {
const connectionsToReturn: {
identity: OpenFin.Identity;
connectionData: AppSourceConnection;
}[] = [];

const availableConnections = Object.values(connectedClients);
for (const connection of availableConnections) {
const matchedConnection = connection.connectionTypes.find(
(supportedConnectionType) => supportedConnectionType.type === APP_SOURCE_TYPE_ID
);

if (matchedConnection?.type === APP_SOURCE_TYPE_ID) {
connectionsToReturn.push({ identity: connection.identity, connectionData: matchedConnection });
}
}

return connectionsToReturn;
}

/**
* Is the specified action supported by the connection.
* @param identity The identity of the connection to test.
Expand Down
Loading

0 comments on commit 0b8cd32

Please sign in to comment.