-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
112 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,38 +4,121 @@ | |
|
||
# Window Level App Channel | ||
|
||
If you want to share information across all views in a window then you can use an FDC3 app channel or an Interop Session Context Group to share that information. | ||
If you want to share information in a custom way e.g. across all views in a window then you can use an FDC3 app channel or an Interop Session Context Group to share that information. Alternatively you can look at creating a custom implementation using a custom interop broker to create user groups per window and ensuring the views are assigned and removed from those groups as they get added and removed from a window. | ||
|
||
The important piece is to have a common key shared across all views (and panels if you are using the Browser Fixed panel support). Views are created and initially assigned to your provider window until the target window is created and the view is moved. | ||
This example uses app channels and the window name as the key. This logic could be packaged as reusable packages for your views. The important piece is to have a common key shared across all views (and panels if you are using the Browser Fixed panel support). Views are created and initially assigned to your provider window until the target window is created and the view is moved. | ||
|
||
If you request the parent window early from a view (e.g. inside of a preload script or early on in the process) then you may initially see the provider id as the window identity which is not what you want. | ||
## Listening for window level messages | ||
|
||
```js | ||
/** | ||
* Get the identity of the window containing a view. | ||
* @param view The view to get the containing window identity. | ||
* @returns The identity of the containing window. | ||
*/ | ||
private async getViewWindowIdentity(view: OpenFin.View): Promise<OpenFin.Identity> { | ||
const currentWindow = await view.getCurrentWindow(); | ||
|
||
// If the view is not yet attached to a window, wait for the | ||
// target-changed event which means it has been attached | ||
if (currentWindow.identity.name === undefined || currentWindow.identity.name === currentWindow.identity.uuid) { | ||
return new Promise<OpenFin.Identity>((resolve, reject) => { | ||
// eslint-disable-next-line jsdoc/require-jsdoc | ||
async function hostWindowChanged(): Promise<void> { | ||
const hostWindow = await view.getCurrentWindow(); | ||
if (hostWindow.identity.name !== hostWindow.identity.uuid) { | ||
await view.removeListener("target-changed", hostWindowChanged); | ||
resolve(hostWindow.identity); | ||
} | ||
let windowLevelChannelListener; | ||
|
||
async function listenToWindowLevelChannel(contextType, callbackToReceiveContext) { | ||
if(window.fdc3 !== undefined && window.fin !== undefined) { | ||
if(windowLevelChannelListener !== undefined) { | ||
// We are currently listening to something. Lets dispose of this as we ay be setting up | ||
// a new listener. | ||
console.log("Unsubscribing from previous channel."); | ||
windowLevelChannelListener.unsubscribe(); | ||
} | ||
try { | ||
const currentWindow = await fin.me.getCurrentWindow(); | ||
const windowIdentity = currentWindow.identity; | ||
if(windowIdentity.name !== undefined && windowIdentity.name !== windowIdentity.uuid) { | ||
// the view has been assigned to a window, start listening. | ||
console.log("Creating or fetching app channel with name:", windowIdentity.name); | ||
const appChannel = await window.fdc3.getOrCreateChannel(windowIdentity.name); | ||
// start listening | ||
windowLevelChannelListener = appChannel.addContextListener(contextType, callbackToReceiveContext); | ||
} | ||
} catch (err){ | ||
//app could not register the channel | ||
console.error("Error registering the window channel", err); | ||
windowLevelChannelListener = undefined; | ||
} | ||
view | ||
.on("target-changed", hostWindowChanged) | ||
.catch(() => {}); | ||
}); | ||
} else { | ||
console.warn("Unable to listen to window level context as the fdc3 and/or fin api is not available."); | ||
} | ||
return currentWindow.identity; | ||
} | ||
} | ||
|
||
async function contextHandler(ctx) { | ||
console.log("This is the function that would be passed the window level context", ctx); | ||
} | ||
|
||
async function init() { | ||
// listen for messages sent to the window. | ||
// this is using fdc3.contact as an example. You can pass null if you want to listen for all messages | ||
await listenToWindowLevelChannel("fdc3.contact", contextHandler); | ||
|
||
// listen for times that the view is moved from one window to another and update | ||
// your listener. | ||
fin.me.on("target-changed", async ()=> { | ||
// this is using fdc3.contact as an example. You can pass null if you want to listen for all messages | ||
await listenToWindowLevelChannel("fdc3.contact", contextHandler); | ||
}); | ||
} | ||
|
||
// trigger the init call e.g. when the document is loaded. | ||
await init(); | ||
``` | ||
|
||
## Publishing window level messages | ||
|
||
```js | ||
let windowChannel; | ||
|
||
async function assignWindowLevelChannel() { | ||
if(window.fdc3 !== undefined && window.fin !== undefined) { | ||
try { | ||
const currentWindow = await fin.me.getCurrentWindow(); | ||
const windowIdentity = currentWindow.identity; | ||
if(windowIdentity.name !== undefined && windowIdentity.name !== windowIdentity.uuid) { | ||
// the view has been assigned to a window, get a channel to use for broadcasting. | ||
console.log("Creating or fetching app channel with name:", windowIdentity.name); | ||
windowChannel = await window.fdc3.getOrCreateChannel(windowIdentity.name); | ||
} | ||
} catch (err){ | ||
//app could not register the channel | ||
console.error("Error getting or retrieving the channel", err); | ||
windowChannel = undefined; | ||
} | ||
} else { | ||
console.warn("Unable to create a window level channel as fdc3 is not available."); | ||
} | ||
} | ||
|
||
async function init() { | ||
// create the window level channel | ||
await assignWindowLevelChannel(); | ||
|
||
// listen for times that the view is moved from one window to another and update | ||
// the window level channel. | ||
fin.me.on("target-changed", async ()=> { | ||
await assignWindowLevelChannel(); | ||
}); | ||
} | ||
|
||
async function broadcastContext(contact){ | ||
// this is using fdc3.contact as an example but you could be sending any context type. | ||
if(windowChannel !== undefined) { | ||
console.log("Broadcasting context:", contact); | ||
windowChannel.broadcast(contact); | ||
} else { | ||
console.warn("Window level channel is not available yet. Ensure you have called the init function before trying to broadcast."); | ||
} | ||
} | ||
|
||
// initialize your code e.g. on document load | ||
await init(); | ||
// in your code you might have something that is listening for a contact selection from a | ||
// grid and then triggers the broadcast like the following: | ||
|
||
const selectedContact = { | ||
type: "fdc3.contact", | ||
name: "Joe Smith", | ||
id: { | ||
email: "[email protected]" | ||
} | ||
}; | ||
broadcastContext(selectedContact); | ||
``` |