@openfin/core 31.74.17 → 31.74.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/api/interop/InteropBroker.js +6 -0
- package/src/api/interop/fdc3/PrivateChannelClient.d.ts +1 -0
- package/src/api/interop/fdc3/PrivateChannelClient.js +15 -7
- package/src/api/interop/fdc3/PrivateChannelProvider.d.ts +15 -1
- package/src/api/interop/fdc3/PrivateChannelProvider.js +80 -21
- package/src/api/interop/fdc3/fdc3-2.0.js +1 -3
- package/src/api/view/Instance.d.ts +4 -0
- package/src/api/view/Instance.js +4 -0
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@ const base_1 = require("../base");
|
|
|
5
5
|
const SessionContextGroupBroker_1 = require("./SessionContextGroupBroker");
|
|
6
6
|
const utils_1 = require("./utils");
|
|
7
7
|
const lodash_1 = require("lodash");
|
|
8
|
+
const PrivateChannelProvider_1 = require("./fdc3/PrivateChannelProvider");
|
|
8
9
|
let contextGroups = [
|
|
9
10
|
{
|
|
10
11
|
id: 'green',
|
|
@@ -1050,6 +1051,11 @@ class InteropBroker extends base_1.Base {
|
|
|
1050
1051
|
channel.register('fdc3v2GetInfo', async (payload, clientIdentity) => {
|
|
1051
1052
|
return this.fdc3HandleGetInfo.bind(this)(payload, clientIdentity);
|
|
1052
1053
|
});
|
|
1054
|
+
channel.register('createPrivateChannelProvider', async (payload) => {
|
|
1055
|
+
const { channelId } = payload;
|
|
1056
|
+
const channelProvider = await this.fin.InterApplicationBus.Channel.create(channelId);
|
|
1057
|
+
PrivateChannelProvider_1.PrivateChannelProvider.init(channelProvider, channelId);
|
|
1058
|
+
});
|
|
1053
1059
|
}
|
|
1054
1060
|
/**
|
|
1055
1061
|
* Can be used to completely prevent a connection. Return false to prevent connections. Allows all connections by default.
|
|
@@ -14,6 +14,7 @@ export declare class PrivateChannelClient {
|
|
|
14
14
|
onAddContextListener(handler: (contextType?: string) => void): Listener;
|
|
15
15
|
onDisconnect(handler: () => void): Listener;
|
|
16
16
|
onUnsubscribe(handler: (contextType?: string) => void): Listener;
|
|
17
|
+
cleanUpAllSubs(): Promise<void>;
|
|
17
18
|
disconnect(): Promise<void>;
|
|
18
19
|
}
|
|
19
20
|
export {};
|
|
@@ -69,14 +69,22 @@ class PrivateChannelClient {
|
|
|
69
69
|
this.client.dispatch(`onUnsubscribeHandlerAdded`, { handlerId });
|
|
70
70
|
return listener;
|
|
71
71
|
}
|
|
72
|
-
async
|
|
73
|
-
const listenerUnsubscribers = Array.from(this.listeners.
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
async cleanUpAllSubs() {
|
|
73
|
+
const listenerUnsubscribers = Array.from(this.listeners.keys());
|
|
74
|
+
listenerUnsubscribers.forEach((handlerId) => {
|
|
75
|
+
this.client.remove(handlerId);
|
|
76
|
+
this.listeners.delete(handlerId);
|
|
76
77
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
}
|
|
79
|
+
async disconnect() {
|
|
80
|
+
try {
|
|
81
|
+
await this.client.dispatch('clientDisconnecting');
|
|
82
|
+
await this.cleanUpAllSubs();
|
|
83
|
+
await this.client.disconnect();
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
throw new Error(error.message);
|
|
87
|
+
}
|
|
80
88
|
}
|
|
81
89
|
}
|
|
82
90
|
exports.PrivateChannelClient = PrivateChannelClient;
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type * as OpenFin from '../../../OpenFin';
|
|
2
2
|
import { ChannelProvider } from '../../interappbus/channel/provider';
|
|
3
3
|
type HandlerId = string;
|
|
4
|
+
type ContextType = string;
|
|
5
|
+
interface PrivateChannelClientState {
|
|
6
|
+
clientIdentity: OpenFin.ClientIdentity;
|
|
7
|
+
handlerIdsByContextTypes: Map<ContextType, HandlerId[]>;
|
|
8
|
+
globalHandler: HandlerId | undefined;
|
|
9
|
+
onAddContextListenerHandlerId: HandlerId | undefined;
|
|
10
|
+
onUnsubscribeHandlerId: HandlerId | undefined;
|
|
11
|
+
onDisconnectHandlerId: HandlerId | undefined;
|
|
12
|
+
}
|
|
4
13
|
export declare class PrivateChannelProvider {
|
|
5
14
|
id: string;
|
|
6
15
|
private provider;
|
|
@@ -35,7 +44,12 @@ export declare class PrivateChannelProvider {
|
|
|
35
44
|
onUnsubscribeHandlerAdded(payload: {
|
|
36
45
|
handlerId: HandlerId;
|
|
37
46
|
}, id: OpenFin.ClientIdentity): void;
|
|
38
|
-
|
|
47
|
+
removeClient(disconnectingClientIdentity: OpenFin.ClientIdentity): void;
|
|
48
|
+
fireOnDisconnectForOtherClients(disconnectingClientIdentity: OpenFin.ClientIdentity): Promise<void>;
|
|
49
|
+
unsubscribeAll(clientIdentity: OpenFin.ClientIdentity): Promise<void>;
|
|
50
|
+
handleClientDisconnecting(disconnectingClientIdentity: OpenFin.ClientIdentity): Promise<void>;
|
|
39
51
|
registerNewClient(clientIdentity: OpenFin.ClientIdentity): void;
|
|
52
|
+
getConnectedClients(): Promise<PrivateChannelClientState[]>;
|
|
53
|
+
static init(channelProvider: OpenFin.ChannelProvider, id: string): PrivateChannelProvider;
|
|
40
54
|
}
|
|
41
55
|
export {};
|
|
@@ -11,7 +11,15 @@ class PrivateChannelProvider {
|
|
|
11
11
|
this.contextByContextType = new Map();
|
|
12
12
|
this.lastContext = undefined;
|
|
13
13
|
this.provider.onConnection((clientIdentity) => this.registerNewClient(clientIdentity));
|
|
14
|
-
this.provider.onDisconnection((clientIdentity) =>
|
|
14
|
+
this.provider.onDisconnection(async (clientIdentity) => {
|
|
15
|
+
const { endpointId } = clientIdentity;
|
|
16
|
+
if (this.clients.has(endpointId)) {
|
|
17
|
+
await this.handleClientDisconnecting(clientIdentity);
|
|
18
|
+
}
|
|
19
|
+
if ((await this.provider.getAllClientInfo()).length === 0) {
|
|
20
|
+
this.provider.destroy();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
15
23
|
}
|
|
16
24
|
getClientState(id) {
|
|
17
25
|
return this.clients.get(id.endpointId);
|
|
@@ -25,7 +33,9 @@ class PrivateChannelProvider {
|
|
|
25
33
|
this.provider.register('onAddContextHandlerAdded', this.onAddContextHandlerAdded.bind(this));
|
|
26
34
|
this.provider.register('onDisconnectHandlerAdded', this.onDisconnectHandlerAdded.bind(this));
|
|
27
35
|
this.provider.register('onUnsubscribeHandlerAdded', this.onUnsubscribeHandlerAdded.bind(this));
|
|
28
|
-
this.provider.register('clientDisconnecting',
|
|
36
|
+
this.provider.register('clientDisconnecting', (payload, clientIdentity) => {
|
|
37
|
+
this.handleClientDisconnecting(clientIdentity);
|
|
38
|
+
});
|
|
29
39
|
}
|
|
30
40
|
broadcast(payload, broadcasterClientIdentity) {
|
|
31
41
|
const { context } = payload;
|
|
@@ -110,17 +120,18 @@ class PrivateChannelProvider {
|
|
|
110
120
|
}
|
|
111
121
|
}
|
|
112
122
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
// getting only valid client connections here, it is possible we haven't removed a disconnected client from the map yet
|
|
124
|
+
// so we need to ensure we don't dispatch to any disconnected client
|
|
125
|
+
// TODO: Take a look at our client disconnection logic and see if we can handle client disconnection cleanly
|
|
126
|
+
const clientsToDispatchTo = await this.getConnectedClients();
|
|
127
|
+
const dispatchPromises = clientsToDispatchTo.map(async (otherClientState) => {
|
|
128
|
+
const { clientIdentity, clientIdentity: { endpointId }, onUnsubscribeHandlerId } = otherClientState;
|
|
129
|
+
if (endpointId !== removingClientIdentity.endpointId && onUnsubscribeHandlerId) {
|
|
130
|
+
await this.provider.dispatch(clientIdentity, onUnsubscribeHandlerId, contextType);
|
|
120
131
|
}
|
|
121
|
-
}
|
|
132
|
+
});
|
|
122
133
|
try {
|
|
123
|
-
await Promise.all(
|
|
134
|
+
await Promise.all(dispatchPromises);
|
|
124
135
|
}
|
|
125
136
|
catch (error) {
|
|
126
137
|
console.error(`Problem when attempting to dispatch to onUnsubscribeHandlers. Error: ${error} Removing Client: ${handlerId}. uuid: ${removingClientIdentity.uuid}. name: ${removingClientIdentity.name}. endpointId: ${removingClientIdentity.endpointId}`);
|
|
@@ -181,32 +192,68 @@ class PrivateChannelProvider {
|
|
|
181
192
|
}
|
|
182
193
|
clientState.onUnsubscribeHandlerId = handlerId;
|
|
183
194
|
}
|
|
184
|
-
|
|
195
|
+
removeClient(disconnectingClientIdentity) {
|
|
185
196
|
const disconnectingClientState = this.getClientState(disconnectingClientIdentity);
|
|
186
197
|
if (!disconnectingClientState) {
|
|
187
198
|
throw new Error(`Client with Identity: ${disconnectingClientIdentity.uuid} ${disconnectingClientIdentity.name}, tried to call disconnect, is not connected to this Private Channel`);
|
|
188
199
|
}
|
|
189
200
|
disconnectingClientState.handlerIdsByContextTypes.clear();
|
|
190
201
|
this.clients.delete(disconnectingClientIdentity.endpointId);
|
|
191
|
-
|
|
202
|
+
}
|
|
203
|
+
async fireOnDisconnectForOtherClients(disconnectingClientIdentity) {
|
|
192
204
|
// TODO: call onDisconnect Handler of the other client only.
|
|
193
205
|
// CURRENTLY, just calling the onDisconnect handler for all the other clients. Once we limit it to just one other client, we can eliminate all the iteration code.
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
206
|
+
const { endpointId } = disconnectingClientIdentity;
|
|
207
|
+
// getting only valid client connections here, it is possible we haven't removed a disconnected client from the map yet
|
|
208
|
+
// so we need to ensure we don't dispatch to any disconnected client
|
|
209
|
+
// TODO: Take a look at our client disconnection logic and see if we can handle client disconnection cleanly
|
|
210
|
+
const clientsToDispatchTo = await this.getConnectedClients();
|
|
211
|
+
const dispatchPromises = clientsToDispatchTo.map(async (otherClientState) => {
|
|
212
|
+
const { clientIdentity: { endpointId: otherClientEndpointId }, onDisconnectHandlerId } = otherClientState;
|
|
213
|
+
if (otherClientEndpointId !== endpointId && onDisconnectHandlerId) {
|
|
214
|
+
await this.provider.dispatch(otherClientState.clientIdentity, onDisconnectHandlerId);
|
|
200
215
|
}
|
|
201
|
-
}
|
|
216
|
+
});
|
|
202
217
|
try {
|
|
203
|
-
await Promise.all(
|
|
218
|
+
await Promise.all(dispatchPromises);
|
|
204
219
|
}
|
|
205
220
|
catch (error) {
|
|
206
221
|
console.error(`Problem when attempting to dispatch to onDisconnectHandlers. Error: ${error} Disconnecting Client: uuid: ${disconnectingClientIdentity.uuid}. name: ${disconnectingClientIdentity.name}. endpointId: ${disconnectingClientIdentity.endpointId}`);
|
|
207
222
|
throw new Error(error);
|
|
208
223
|
}
|
|
209
224
|
}
|
|
225
|
+
async unsubscribeAll(clientIdentity) {
|
|
226
|
+
const { endpointId } = clientIdentity;
|
|
227
|
+
const state = this.clients.get(endpointId);
|
|
228
|
+
if (state) {
|
|
229
|
+
const contextTypeHandlerIds = Array.from(state.handlerIdsByContextTypes.values()).flat();
|
|
230
|
+
const globalHandlerId = state.globalHandler;
|
|
231
|
+
if (contextTypeHandlerIds.length > 0) {
|
|
232
|
+
const unsubPromises = contextTypeHandlerIds.map(async (handlerId) => {
|
|
233
|
+
return this.contextHandlerRemoved({ handlerId }, clientIdentity);
|
|
234
|
+
});
|
|
235
|
+
try {
|
|
236
|
+
await Promise.all(unsubPromises);
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
console.error(error.message);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (globalHandlerId) {
|
|
243
|
+
try {
|
|
244
|
+
await this.contextHandlerRemoved({ handlerId: globalHandlerId }, clientIdentity);
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
console.error(error.message);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async handleClientDisconnecting(disconnectingClientIdentity) {
|
|
253
|
+
await this.unsubscribeAll(disconnectingClientIdentity);
|
|
254
|
+
this.removeClient(disconnectingClientIdentity);
|
|
255
|
+
await this.fireOnDisconnectForOtherClients(disconnectingClientIdentity);
|
|
256
|
+
}
|
|
210
257
|
registerNewClient(clientIdentity) {
|
|
211
258
|
if (!this.clients.has(clientIdentity.endpointId)) {
|
|
212
259
|
const clientSubscriptionState = {
|
|
@@ -220,5 +267,17 @@ class PrivateChannelProvider {
|
|
|
220
267
|
this.clients.set(clientIdentity.endpointId, clientSubscriptionState);
|
|
221
268
|
}
|
|
222
269
|
}
|
|
270
|
+
async getConnectedClients() {
|
|
271
|
+
const allClientInfo = await this.provider.getAllClientInfo();
|
|
272
|
+
return Array.from(this.clients.values()).filter((clientState) => {
|
|
273
|
+
const { uuid, name } = clientState.clientIdentity;
|
|
274
|
+
return allClientInfo.some(clientInfo => {
|
|
275
|
+
return name === clientInfo.name && uuid === clientInfo.uuid;
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
static init(channelProvider, id) {
|
|
280
|
+
return new PrivateChannelProvider(channelProvider, id);
|
|
281
|
+
}
|
|
223
282
|
}
|
|
224
283
|
exports.PrivateChannelProvider = PrivateChannelProvider;
|
|
@@ -6,7 +6,6 @@ const InteropClient_1 = require("../InteropClient");
|
|
|
6
6
|
const utils_2 = require("./utils");
|
|
7
7
|
const fdc3_1_2_1 = require("./fdc3-1.2");
|
|
8
8
|
const PrivateChannelClient_1 = require("./PrivateChannelClient");
|
|
9
|
-
const PrivateChannelProvider_1 = require("./PrivateChannelProvider");
|
|
10
9
|
/**
|
|
11
10
|
* @typedef { object } AppIdentifier
|
|
12
11
|
* @summary Identifies an application, or instance of an application, and is used to target FDC3 API calls at specific applications.
|
|
@@ -389,8 +388,7 @@ class Fdc3Module2 extends base_1.Base {
|
|
|
389
388
|
*/
|
|
390
389
|
async createPrivateChannel() {
|
|
391
390
|
const channelId = (0, utils_1.generateId)();
|
|
392
|
-
|
|
393
|
-
const newPrivateChannelProvider = new PrivateChannelProvider_1.PrivateChannelProvider(channelProvider, channelId);
|
|
391
|
+
await InteropClient_1.InteropClient.ferryFdc3Call(this.fin.me.interop, 'createPrivateChannelProvider', { channelId });
|
|
394
392
|
const channelClient = await this.fin.InterApplicationBus.Channel.connect(channelId);
|
|
395
393
|
const newPrivateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId);
|
|
396
394
|
return (0, utils_2.buildPrivateChannelObject)(newPrivateChannelClient);
|
|
@@ -457,6 +457,10 @@ export declare class View extends WebContents<ViewEvent> {
|
|
|
457
457
|
* **NOTE**: Internal use only.
|
|
458
458
|
* Attaches this view to an HTML element in the current context. The view will resize responsively when the element bounds change.
|
|
459
459
|
*
|
|
460
|
+
* **Known issue**: View.bindToElement does not track position changes, if the element has fixed px width and height values it is possible for the view to not update responsively.
|
|
461
|
+
*
|
|
462
|
+
* **Known issue**: When View.bindToElement is used on a element that takes up the entire page in a platform window, the bound view will not respond responsively when the window is resized to be smaller.
|
|
463
|
+
*
|
|
460
464
|
* @param {HTMLElement} element - HTML element to attach the view to.
|
|
461
465
|
* @return {Function} - Cleanup function that will disconnect the element resize observer.
|
|
462
466
|
* @internal
|
package/src/api/view/Instance.js
CHANGED
|
@@ -461,6 +461,10 @@ class View extends main_1.WebContents {
|
|
|
461
461
|
* **NOTE**: Internal use only.
|
|
462
462
|
* Attaches this view to an HTML element in the current context. The view will resize responsively when the element bounds change.
|
|
463
463
|
*
|
|
464
|
+
* **Known issue**: View.bindToElement does not track position changes, if the element has fixed px width and height values it is possible for the view to not update responsively.
|
|
465
|
+
*
|
|
466
|
+
* **Known issue**: When View.bindToElement is used on a element that takes up the entire page in a platform window, the bound view will not respond responsively when the window is resized to be smaller.
|
|
467
|
+
*
|
|
464
468
|
* @param {HTMLElement} element - HTML element to attach the view to.
|
|
465
469
|
* @return {Function} - Cleanup function that will disconnect the element resize observer.
|
|
466
470
|
* @internal
|