Skip to content

Commit 89620fd

Browse files
committed
implement addIntentWithContextListener
1 parent 42b7418 commit 89620fd

File tree

10 files changed

+129
-54
lines changed

10 files changed

+129
-54
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6666
- resolves ([#1487](https://github.com/finos/FDC3/issues/1487))
6767
- resolves ([#1488](https://github.com/finos/FDC3/issues/1488))
6868
* Adjusted reference Desktop Agent implementation for FDC3 for Web to open a new app instance when raiseIntent is called with an appId but no instanceId ([#1556](https://github.com/finos/FDC3/pull/1556))
69+
* Added `addIntentWithContextListener` to `DesktopAgent` and implemented in `DesktopAgentProxy`
6970

7071
### Changed
7172

packages/fdc3-agent-proxy/src/DesktopAgentProxy.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export class DesktopAgentProxy implements DesktopAgent, Connectable {
6666
this.findIntentsByContext = this.findIntentsByContext.bind(this);
6767
this.raiseIntent = this.raiseIntent.bind(this);
6868
this.addIntentListener = this.addIntentListener.bind(this);
69+
this.addIntentListenerWithContext = this.addIntentListenerWithContext.bind(this);
6970
this.raiseIntentForContext = this.raiseIntentForContext.bind(this);
7071
this.open = this.open.bind(this);
7172
this.findInstances = this.findInstances.bind(this);
@@ -183,6 +184,10 @@ export class DesktopAgentProxy implements DesktopAgent, Connectable {
183184
return this.intents.addIntentListener(intent, handler);
184185
}
185186

187+
addIntentListenerWithContext(intent: string, contextType: string | string[], handler: IntentHandler) {
188+
return this.intents.addIntentListenerWithContext(intent, contextType, handler);
189+
}
190+
186191
raiseIntentForContext(context: Context, app?: string | AppIdentifier): Promise<IntentResolution> {
187192
return this.intents.raiseIntentForContext(context, this.ensureAppId(app));
188193
}

packages/fdc3-agent-proxy/src/intents/DefaultIntentSupport.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,23 @@ export class DefaultIntentSupport implements IntentSupport {
217217
}
218218

219219
async addIntentListener(intent: string, handler: IntentHandler): Promise<Listener> {
220-
const out = new DefaultIntentListener(this.messaging, intent, handler, this.messageExchangeTimeout);
220+
const out = new DefaultIntentListener(this.messaging, intent, undefined, handler, this.messageExchangeTimeout);
221+
await out.register();
222+
return out;
223+
}
224+
225+
async addIntentListenerWithContext(
226+
intent: string,
227+
contextType: string | string[],
228+
handler: IntentHandler
229+
): Promise<Listener> {
230+
const out = new DefaultIntentListener(
231+
this.messaging,
232+
intent,
233+
Array.isArray(contextType) ? contextType : [contextType],
234+
handler,
235+
this.messageExchangeTimeout
236+
);
221237
await out.register();
222238
return out;
223239
}

packages/fdc3-agent-proxy/src/intents/IntentSupport.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,9 @@ export interface IntentSupport {
77
raiseIntent(intent: string, context: Context, app?: AppIdentifier): Promise<IntentResolution>;
88
raiseIntentForContext(context: Context, app?: AppIdentifier): Promise<IntentResolution>;
99
addIntentListener(intent: string, handler: IntentHandler): Promise<Listener>;
10+
addIntentListenerWithContext(
11+
intent: string,
12+
contextType: string | string[],
13+
handler: IntentHandler
14+
): Promise<Listener>;
1015
}

packages/fdc3-agent-proxy/src/listeners/DefaultIntentListener.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,34 @@ import {
77
IntentEvent,
88
IntentResultRequest,
99
IntentResultResponse,
10-
//RaiseIntentResponse,
1110
} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes';
1211

1312
export class DefaultIntentListener extends AbstractListener<IntentHandler, AddIntentListenerRequest> {
14-
readonly intent: string;
15-
16-
constructor(messaging: Messaging, intent: string, action: IntentHandler, messageExchangeTimeout: number) {
13+
constructor(
14+
messaging: Messaging,
15+
private readonly intent: string,
16+
private readonly contextTypes: string[] | undefined,
17+
action: IntentHandler,
18+
messageExchangeTimeout: number
19+
) {
1720
super(
1821
messaging,
1922
messageExchangeTimeout,
20-
{ intent },
23+
{ intent, contextTypes },
2124
action,
2225
'addIntentListenerRequest',
2326
'addIntentListenerResponse',
2427
'intentListenerUnsubscribeRequest',
2528
'intentListenerUnsubscribeResponse'
2629
);
27-
this.intent = intent;
2830
}
2931

3032
filter(m: IntentEvent): boolean {
31-
return m.type == 'intentEvent' && m.payload.intent == this.intent;
33+
return (
34+
m.type == 'intentEvent' &&
35+
m.payload.intent == this.intent &&
36+
(this.contextTypes == null || this.contextTypes.includes(m.payload.context.type))
37+
);
3238
}
3339

3440
action(m: IntentEvent): void {

packages/fdc3-get-agent/test/step-definitions/desktop-agent.steps.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ Given('A Dummy Desktop Agent in {string}', async function (this: CustomWorld, fi
223223
raiseIntent: notImplemented,
224224
raiseIntentForContext: notImplemented,
225225
addIntentListener: notImplemented,
226+
addIntentListenerWithContext: notImplemented,
226227
addContextListener: notImplemented,
227228
addEventListener: notImplemented,
228229
getUserChannels: notImplemented,

packages/fdc3-schema/generated/api/BrowserTypes.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,10 @@ export interface AddIntentListenerRequest {
405405
* The message payload typically contains the arguments to FDC3 API functions.
406406
*/
407407
export interface AddIntentListenerRequestPayload {
408+
/**
409+
* The types of context to listen for.
410+
*/
411+
contextTypes?: string[];
408412
/**
409413
* The name of the intent to listen for.
410414
*/
@@ -4856,7 +4860,13 @@ const typeMap: any = {
48564860
],
48574861
false
48584862
),
4859-
AddIntentListenerRequestPayload: o([{ json: 'intent', js: 'intent', typ: '' }], false),
4863+
AddIntentListenerRequestPayload: o(
4864+
[
4865+
{ json: 'contextTypes', js: 'contextTypes', typ: u(undefined, a('')) },
4866+
{ json: 'intent', js: 'intent', typ: '' },
4867+
],
4868+
false
4869+
),
48604870
AddIntentListenerResponse: o(
48614871
[
48624872
{ json: 'meta', js: 'meta', typ: r('AddContextListenerResponseMeta') },
Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,54 @@
11
{
2-
"$schema": "http://json-schema.org/draft-07/schema#",
3-
"$id": "https://fdc3.finos.org/schemas/next/api/addIntentListenerRequest.schema.json",
4-
"type": "object",
5-
"title": "AddIntentListener Request",
6-
"description": "A request to add an Intent listener for a specified intent type.",
7-
"allOf": [
8-
{
9-
"$ref": "appRequest.schema.json"
10-
},
11-
{
12-
"type": "object",
13-
"properties": {
14-
"type": {
15-
"$ref": "#/$defs/AddIntentListenerRequestType"
16-
},
17-
"payload": {
18-
"$ref": "#/$defs/AddIntentListenerRequestPayload"
19-
},
20-
"meta": true
21-
},
22-
"additionalProperties": false
23-
}
24-
],
25-
"$defs": {
26-
"AddIntentListenerRequestType": {
27-
"title": "AddIntentListener Request Message Type",
28-
"const": "addIntentListenerRequest"
29-
},
30-
"AddIntentListenerRequestPayload": {
31-
"title": "AddIntentListener Request Payload",
32-
"type": "object",
33-
"properties": {
34-
"intent": {
35-
"title": "Intent name",
36-
"description": "The name of the intent to listen for.",
37-
"type": "string"
38-
}
39-
},
40-
"additionalProperties": false,
41-
"required": [
42-
"intent"
43-
]
44-
}
45-
}
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://fdc3.finos.org/schemas/next/api/addIntentListenerRequest.schema.json",
4+
"type": "object",
5+
"title": "AddIntentListener Request",
6+
"description": "A request to add an Intent listener for a specified intent type.",
7+
"allOf": [
8+
{
9+
"$ref": "appRequest.schema.json"
10+
},
11+
{
12+
"type": "object",
13+
"properties": {
14+
"type": {
15+
"$ref": "#/$defs/AddIntentListenerRequestType"
16+
},
17+
"payload": {
18+
"$ref": "#/$defs/AddIntentListenerRequestPayload"
19+
},
20+
"meta": true
21+
},
22+
"additionalProperties": false
23+
}
24+
],
25+
"$defs": {
26+
"AddIntentListenerRequestType": {
27+
"title": "AddIntentListener Request Message Type",
28+
"const": "addIntentListenerRequest"
29+
},
30+
"AddIntentListenerRequestPayload": {
31+
"title": "AddIntentListener Request Payload",
32+
"type": "object",
33+
"properties": {
34+
"intent": {
35+
"title": "Intent name",
36+
"description": "The name of the intent to listen for.",
37+
"type": "string"
38+
},
39+
"contextTypes": {
40+
"title": "Context types",
41+
"description": "The types of context to listen for.",
42+
"type": "array",
43+
"items": {
44+
"type": "string"
45+
}
46+
}
47+
},
48+
"additionalProperties": false,
49+
"required": [
50+
"intent"
51+
]
52+
}
53+
}
4654
}

packages/fdc3-standard/src/api/DesktopAgent.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,22 @@ export interface DesktopAgent {
353353
*/
354354
addIntentListener(intent: Intent, handler: IntentHandler): Promise<Listener>;
355355

356+
/**
357+
* Adds a listener for incoming intents raised by other applications, via calls to `fdc3.raiseIntent` or `fdc3.raiseIntentForContext, but filters intents for one or more context types. See `addIntentListener` for details and restrictions for both usage and implementation.
358+
*
359+
* //Handle a raised intent
360+
* const listener = fdc3.addIntentListenerWithContext('StartChat', 'fdc3.contact', context => {
361+
* // start chat has been requested by another application
362+
* return;
363+
* });
364+
*/
365+
366+
addIntentListenerWithContext(
367+
intent: Intent,
368+
contextType: string | string[],
369+
handler: IntentHandler
370+
): Promise<Listener>;
371+
356372
/**
357373
* Adds a listener for incoming context broadcasts from the Desktop Agent (via a User channel or `fdc3.open`API call. If the consumer is only interested in a context of a particular type, they can they can specify that type. If the consumer is able to receive context of any type or will inspect types received, then they can pass `null` as the `contextType` parameter to receive all context types.
358374
*

toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/IntentHandler.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type ListenerRegistration = {
2828
appId: string;
2929
instanceId: string;
3030
intentName: string;
31+
contextTypes?: string[];
3132
listenerUUID: string;
3233
};
3334

@@ -114,6 +115,7 @@ class PendingIntent {
114115
if (
115116
arg0.appId == this.appId.appId &&
116117
arg0.intentName == this.r.intent &&
118+
(arg0.contextTypes == undefined || arg0.contextTypes.includes(this.r.context.type)) &&
117119
(arg0.instanceId == this.appId.instanceId || this.appId.instanceId == undefined)
118120
) {
119121
this.complete = true;
@@ -248,6 +250,7 @@ export class IntentHandler implements MessageHandler {
248250
appId: from.appId,
249251
instanceId: from.instanceId,
250252
intentName: arg0.payload.intent,
253+
contextTypes: arg0.payload.contextTypes,
251254
listenerUUID: sc.createUUID(),
252255
};
253256

@@ -377,7 +380,11 @@ export class IntentHandler implements MessageHandler {
377380
async raiseIntentToAnyApp(arg0: IntentRequest[], sc: ServerContext<AppRegistration>): Promise<void> {
378381
const connectedApps = await sc.getConnectedApps();
379382
const matchingIntents = arg0.flatMap(i => this.directory.retrieveIntents(i.context.type, i.intent, undefined));
380-
const matchingRegistrations = arg0.flatMap(i => this.registrations.filter(r => r.intentName == i.intent));
383+
const matchingRegistrations = arg0.flatMap(i =>
384+
this.registrations.filter(
385+
r => r.intentName == i.intent && (r.contextTypes == null || r.contextTypes.includes(i.context.type))
386+
)
387+
); // Get a list of intent listeners that match the intent and context type
381388
const uniqueIntentNames = [
382389
...matchingIntents.map(i => i.intentName),
383390
...matchingRegistrations.map(r => r.intentName),

0 commit comments

Comments
 (0)