Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New channel proposition #171

Merged
merged 13 commits into from
Feb 27, 2020
51 changes: 49 additions & 2 deletions docs/api/ref/DesktopAgent.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ catch (err){
```ts
getSystemChannels() : Promise<Array<Channel>>;
```
Retrieves a list of the System channels available for the app to join.
Retrieves a list of the System channels available for the app to join. This should include the 'global' channel.

#### Example

Expand Down Expand Up @@ -235,13 +235,14 @@ fdc3.joinChannel(selectedChannel.id);
#### See also
* [`getSystemChannels`](#getSystemChannels)


### `broadcast`

```ts
broadcast(context: Context): void;
```

Publishes context to other apps on the desktop.
Publishes context to other apps on the desktop. Calling `broadcast` at the `DesktopAgent` scope will push the context to whatever `Channel` the app is joined to. If the app is not currently joined to a channel, calling `fdc3.broadcast` will have no effect. Apps can still directly broadcast and listen to context on any channel via the methods on the `Channel` class.

#### Example
```js
Expand All @@ -257,6 +258,52 @@ fdc3.broadcast(instrument);
#### See also
* [addContextListener](#addcontextlistener)



### `leaveCurrentChannel`

```ts
leaveCurrentChannel() : Promise<void>;
```

Removes the app from any channel membership. Context broadcast and listening through the top-level `fdc3.broadcast` and `fdc3.addContextListener` will be in a no-op when the app is not on a channel.


#### Examples

```js
//desktop-agent scope context listener
const fdc3Listener = fdc3.addContextListener(context => {});

await fdc3.leaveCurrentChannel();
//the fdc3Listener will now cease recieving context

//listening on a specific channel though, will continue to work
redChannel.addContextListener(channelListener);

```


### `getCurrentChannel`

```ts
getCurrentChannel() : Promise<Channel>;
```

Returns the `Channel` object for the current channel membership. Returns `null` if the app is not joined to a channel.


#### Examples

```js
//get the current channel membership
let current = await fdc3.getCurrentChannel();
```

#### See also
* [`Channel`](Channel)


### `addContextListener`

```ts
Expand Down
42 changes: 37 additions & 5 deletions docs/api/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,18 +142,50 @@ Context channels allows a set of apps to share a stateful piece of data between

There are two types of channels, which are functionally identical, but have different visibility and discoverability semantics.

1. The 'system' ones, which have a well understood identity. One is called 'default'.
1. The 'system' ones, which have a well understood identity. One is called 'global'.
2. The 'app' ones, which have a transient identity and need to be revealed

The 'system' channels include a 'default' channel which serves as the backwards compatible layer with the 'send/broadcast context' above. There are some reserved channel names for future use. Currently this is just 'global'.


### Joining Channels
Apps can join channels. An app can only be joined to one channel at a time. When an app joins a channel it will automatically recieve the current context for that channel, except if the channel joined is the 'default'.
Apps can join channels. An app can only be joined to one channel at a time. When an app joins a channel it will automatically recieve the current context for that channel.

When an app is joined to a channel, calls to fdc3.broadcast and listeners added through fdc3.addContextListener will be routed to that channel. If an app is not explicitly joined to a channel, it is on the 'default' channel. It is up to the desktop agent to determine the behavior of the 'default' channel, and if context is automaticaly broadcast over it or not.
When an app is joined to a channel, calls to fdc3.broadcast and listeners added through fdc3.addContextListener will be routed to that channel. If an app is not joined to a channel these methods will be no-ops, but apps can still choose to listen and broadcast to specific channels via the methods on the `Channel` class.

It is possible that a call to join a channel could be rejected. If for example, the desktop agent wanted to implement controls around what data apps can access.

Joining channels in FDC3 is intended to be a behavior initiated by the end user. For example: by color linking or apps being grouped in the same workspace. Most of the time, it is expected that apps will be joined to a channel by mechanisms outside of the app. Always, there SHOULD be a clear UX indicator of what channel an app is joined to.

### The 'global' Channel
The 'system' channels include a 'global' channel which serves as the backwards compatible layer with the 'send/broadcast context' behavior in FDC3 1.0. A desktop agent MAY choose to make membership in the 'global' channel the default state for apps on start up.

The 'global' channel should be returned as part of the response from the `fdc3.getSystemChannels` call. Desktop Agents may want to filter out the 'global' option in their UI for system channel pickers.


#### Examples

An app queries the current context of the `global` channel.

```js
const globalChannel = await fdc3.getOrCreateChannel("global");
const context = await globalChannel.getCurrentContext("fdc3.instrument");
```

An app can explicitly receive context events on the `global` (or any other) channel, regardless of what it is currently joined to.

```js
// retrieve current fdc3 context
const context = await fdc3.getCurrentContext("fdc3.instrument")
// context is null, as not currently joined to a channel

const globalChannel = await fdc3.getSystemChannels.filter(c => c.id === "global")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is main reason to have this getSystemChannels.filter example here in addition to getOrCreateChannel example above?
Should you even have to do the filter thing with explicit API to get a channel?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per the APIs, getSystemChannels returns an array of the well-known system channels, e.g. red, global etc.

If it is a system channel, it is just a different way to get the same channel. I just did this to show the alternative.

const globalContext = await fdc3.getCurrentContext("fdc3.instrument")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want await globalChannel.getCurrentContext("fdc3.instrument") here.

// context is instrument AAPL on the global channel

fdc3.joinChannel('global')
const context = await fdc3.getCurrentContext('fdc3.instrument')
// top-level context is now instrument AAPL as well because we have joined the global channel
```

### Direct Listening and Broadcast on Channels
While joining channels automates a lot of the channel behavior for an app, it has the limitation in that an app can belong to only one channel at a time. Listening and Broadcasting to channels using the _Channel.addBroadcastListener_ and the _Channel.broadcast_ APIs provides an app with fine-grained controls for specific channels. This is especially useful for working with dynamic _App Channels_.

Expand Down