mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
SDA-4770 Expose openfin (#2264)
This commit is contained in:
parent
8a6704b449
commit
b27faedc28
@ -47,5 +47,11 @@
|
||||
"userDataPath": "",
|
||||
"chromeFlags": "",
|
||||
"betaAutoUpdateChannelEnabled": true,
|
||||
"latestAutoUpdateChannelEnabled": true
|
||||
"latestAutoUpdateChannelEnabled": true,
|
||||
"openfin": {
|
||||
"uuid": "",
|
||||
"licenseKey": "",
|
||||
"runtimeVersion": "",
|
||||
"autoConnect": false
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +123,10 @@ if [ "$EUID" -ne 0 ]; then
|
||||
defaults write "$plistFilePath" betaAutoUpdateChannelEnabled -bool true
|
||||
defaults write "$plistFilePath" latestAutoUpdateChannelEnabled -bool true
|
||||
defaults write "$plistFilePath" installVariant -string "$uuid"
|
||||
defaults write "$plistFilePath" uuid -string ""
|
||||
defaults write "$plistFilePath" licenseKey -string ""
|
||||
defaults write "$plistFilePath" runtimeVersion -string ""
|
||||
defaults write "$plistFilePath" autoConnect -bool false
|
||||
else
|
||||
sudo -u "$userName" defaults write "$plistFilePath" url -string "$pod_url"
|
||||
sudo -u "$userName" defaults write "$plistFilePath" autoUpdateUrl -string ""
|
||||
@ -168,6 +172,10 @@ else
|
||||
sudo -u "$userName" defaults write "$plistFilePath" betaAutoUpdateChannelEnabled -bool true
|
||||
sudo -u "$userName" defaults write "$plistFilePath" latestAutoUpdateChannelEnabled -bool true
|
||||
sudo -u "$userName" defaults write "$plistFilePath" installVariant -string "$uuid"
|
||||
sudo -u "$userName" defaults write "$plistFilePath" uuid -string ""
|
||||
sudo -u "$userName" defaults write "$plistFilePath" licenseKey -string ""
|
||||
sudo -u "$userName" defaults write "$plistFilePath" runtimeVersion -string ""
|
||||
sudo -u "$userName" defaults write "$plistFilePath" autoConnect -bool false
|
||||
fi
|
||||
|
||||
## Remove the temp settings & permissions file created ##
|
||||
|
56
package-lock.json
generated
56
package-lock.json
generated
@ -10,6 +10,7 @@
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@openfin/node-adapter": "^40.101.1",
|
||||
"@types/lazy-brush": "^1.0.0",
|
||||
"adm-zip": "^0.5.10",
|
||||
"bplist-parser": "^0.3.2",
|
||||
@ -2636,6 +2637,59 @@
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@openfin/core": {
|
||||
"version": "40.101.1",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/@openfin/core/-/core-40.101.1.tgz",
|
||||
"integrity": "sha512-jXAsWz0R+g26k+6+Jps9BaAsAR3VURnjX1ZVFZ4toyS7q+NHysF1oUxE4nBKSKTgOBAqX+TqAvO7ZaUhPTrlNw==",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"dependencies": {
|
||||
"@types/node": "^20.14.2",
|
||||
"lodash": "^4.17.21",
|
||||
"ws": "^7.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@openfin/core/node_modules/@types/node": {
|
||||
"version": "20.17.13",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/@types/node/-/node-20.17.13.tgz",
|
||||
"integrity": "sha512-RNf+4dEeV69PIvyp++4IKM2vnLXtmp/JovfeQm5P5+qpKb6wHoH7INywLdZ7z+gVX46kgBP/fwJJvZYaHxtdyw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@openfin/core/node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@openfin/node-adapter": {
|
||||
"version": "40.101.1",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/@openfin/node-adapter/-/node-adapter-40.101.1.tgz",
|
||||
"integrity": "sha512-b3uKfE8OulvV2xp3aAB7QMvY013LI8GBPjypEYgZx7qW0b5g6SNHu2eVzOJf5Nl3SJVUoBu6TawtpKZo8Qtewg==",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"dependencies": {
|
||||
"@openfin/core": "40.101.1",
|
||||
"@types/node": "^20.14.2",
|
||||
"lodash": "^4.17.21",
|
||||
"ws": "^7.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@openfin/node-adapter/node_modules/@types/node": {
|
||||
"version": "20.17.6",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/@types/node/-/node-20.17.6.tgz",
|
||||
"integrity": "sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@openfin/node-adapter/node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
@ -12038,7 +12092,6 @@
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
@ -17820,7 +17873,6 @@
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "7.4.4",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
|
@ -221,6 +221,7 @@
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@openfin/node-adapter": "^40.101.1",
|
||||
"@types/lazy-brush": "^1.0.0",
|
||||
"adm-zip": "^0.5.10",
|
||||
"bplist-parser": "^0.3.2",
|
||||
|
@ -98,6 +98,7 @@ describe('config', () => {
|
||||
'latestAutoUpdateChannelEnabled',
|
||||
'betaAutoUpdateChannelEnabled',
|
||||
'browserLoginRetryTimeout',
|
||||
'openfin',
|
||||
];
|
||||
const globalConfig: object = { url: 'test' };
|
||||
const userConfig: object = { configVersion: '4.0.1' };
|
||||
|
@ -86,6 +86,10 @@ jest.mock('../src/renderer/notification', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@openfin/node-adapter', () => ({
|
||||
connect: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('electron-log');
|
||||
|
||||
describe('dialog handler', () => {
|
||||
|
@ -2,6 +2,7 @@ import { activityDetection } from '../src/app/activity-detection';
|
||||
import * as c9PipeHandler from '../src/app/c9-pipe-handler';
|
||||
import { downloadHandler } from '../src/app/download-handler';
|
||||
import '../src/app/main-api-handler';
|
||||
import { openfinHandler } from '../src/app/openfin-handler';
|
||||
import { protocolHandler } from '../src/app/protocol-handler';
|
||||
import { screenSnippet } from '../src/app/screen-snippet-handler';
|
||||
import * as windowActions from '../src/app/window-actions';
|
||||
@ -10,9 +11,56 @@ import * as utils from '../src/app/window-utils';
|
||||
import { apiCmds, apiName } from '../src/common/api-interface';
|
||||
import { logger } from '../src/common/logger';
|
||||
import { BrowserWindow, ipcMain } from './__mocks__/electron';
|
||||
import { connect } from '@openfin/node-adapter';
|
||||
|
||||
jest.mock('electron-log');
|
||||
|
||||
jest.mock('../src/app/openfin-handler', () => {
|
||||
return {
|
||||
openfinHandler: {
|
||||
connect: jest.fn(),
|
||||
fireIntent: jest.fn(),
|
||||
joinContextGroup: jest.fn(),
|
||||
getContextGroups: jest.fn(),
|
||||
getConnectionStatus: jest.fn(),
|
||||
getInfo: jest.fn(),
|
||||
getAllClientsInContextGroup: jest.fn(),
|
||||
registerIntentHandler: jest.fn(),
|
||||
unregisterIntentHandler: jest.fn(),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@openfin/node-adapter', () => ({
|
||||
connect: jest.fn(),
|
||||
}));
|
||||
|
||||
(connect as jest.Mock).mockResolvedValue({
|
||||
Interop: {
|
||||
connectSync: jest.fn().mockReturnValue({
|
||||
onDisconnection: jest.fn(),
|
||||
fireIntent: jest.fn(),
|
||||
registerIntentHandler: jest.fn(),
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
jest.mock('../src/app/config-handler', () => {
|
||||
return {
|
||||
config: {
|
||||
getConfigFields: jest.fn(() => {
|
||||
return {
|
||||
openfin: {
|
||||
uuid: 'some-uuid',
|
||||
licenseKey: 'some-license-key',
|
||||
runtimeVersion: 'some-runtime-version',
|
||||
},
|
||||
};
|
||||
}),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../src/app/protocol-handler', () => {
|
||||
return {
|
||||
protocolHandler: {
|
||||
@ -553,4 +601,114 @@ describe('main api handler', () => {
|
||||
expect(spy).toBeCalledWith(...expectedValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('openfin api events', () => {
|
||||
beforeEach(() => {
|
||||
(connect as jest.Mock).mockResolvedValue({
|
||||
Interop: {
|
||||
connectSync: jest.fn().mockReturnValue({
|
||||
onDisconnection: jest.fn(),
|
||||
}),
|
||||
},
|
||||
});
|
||||
(windowHandler.getMainWebContents as jest.Mock).mockReturnValue({
|
||||
send: jest.fn(),
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should call `connect` correctly', () => {
|
||||
const spy = jest.spyOn(openfinHandler, 'connect');
|
||||
const value = {
|
||||
cmd: apiCmds.openfinConnect,
|
||||
};
|
||||
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should call `fireIntent`', () => {
|
||||
const spy = jest.spyOn(openfinHandler, 'fireIntent');
|
||||
const value = {
|
||||
cmd: apiCmds.openfinFireIntent,
|
||||
intent: {
|
||||
name: 'ViewContact',
|
||||
context: {
|
||||
type: 'fdc3.contact',
|
||||
name: 'Andy Young',
|
||||
id: {
|
||||
email: 'andy.young@example.com',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should call `registerIntentHandler`', () => {
|
||||
const spy = jest.spyOn(openfinHandler, 'registerIntentHandler');
|
||||
const value = {
|
||||
cmd: apiCmds.openfinRegisterIntentHandler,
|
||||
intentName: 'ViewContact',
|
||||
};
|
||||
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should call `unregisterIntentHandler`', () => {
|
||||
const spy = jest.spyOn(openfinHandler, 'unregisterIntentHandler');
|
||||
const value = {
|
||||
cmd: apiCmds.openfinUnregisterIntentHandler,
|
||||
intentName: 'ViewContact',
|
||||
};
|
||||
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should call `joinContextGroup`', () => {
|
||||
const spy = jest.spyOn(openfinHandler, 'joinContextGroup');
|
||||
const value = {
|
||||
cmd: apiCmds.openfinJoinContextGroup,
|
||||
contextGroupId: 'group-id',
|
||||
};
|
||||
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should call `getContextGroups`', () => {
|
||||
const spy = jest.spyOn(openfinHandler, 'getContextGroups');
|
||||
const value = {
|
||||
cmd: apiCmds.openfinGetContextGroups,
|
||||
};
|
||||
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should call `getAllClientsInContextGroup`', () => {
|
||||
const spy = jest.spyOn(openfinHandler, 'getAllClientsInContextGroup');
|
||||
const value = {
|
||||
cmd: apiCmds.openfinGetAllClientsInContextGroup,
|
||||
contextGroupId: 'group-id',
|
||||
};
|
||||
|
||||
ipcMain.send(apiName.symphonyApi, value);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
130
spec/openfinHandler.spec.ts
Normal file
130
spec/openfinHandler.spec.ts
Normal file
@ -0,0 +1,130 @@
|
||||
import { openfinHandler } from '../src/app/openfin-handler';
|
||||
import { connect } from '@openfin/node-adapter';
|
||||
|
||||
jest.mock('@openfin/node-adapter', () => ({
|
||||
connect: jest.fn(),
|
||||
}));
|
||||
|
||||
(connect as jest.Mock).mockResolvedValue({
|
||||
Interop: {
|
||||
connectSync: jest.fn().mockReturnValue({
|
||||
onDisconnection: jest.fn(),
|
||||
fireIntent: jest.fn(),
|
||||
registerIntentHandler: jest.fn(),
|
||||
getAllClientsInContextGroup: jest.fn(),
|
||||
joinContextGroup: jest.fn(),
|
||||
getContextGroups: jest.fn(),
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
jest.mock('../src/app/config-handler', () => ({
|
||||
config: {
|
||||
getConfigFields: jest.fn(() => ({
|
||||
openfin: {
|
||||
uuid: 'mock-uuid',
|
||||
licenseKey: 'mock-license',
|
||||
runtimeVersion: 'mock-version',
|
||||
},
|
||||
})),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../src/app/window-handler', () => {
|
||||
return {
|
||||
windowHandler: {
|
||||
getMainWebContents: jest.fn(),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('Openfin', () => {
|
||||
let connectMock;
|
||||
beforeAll(async () => {
|
||||
connectMock = await connect({} as any);
|
||||
});
|
||||
|
||||
it('should not be connected', () => {
|
||||
const info = openfinHandler.getInfo();
|
||||
const isConnected = openfinHandler.getConnectionStatus();
|
||||
|
||||
expect(info.isConnected).toBeFalsy();
|
||||
expect(isConnected).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should connect', async () => {
|
||||
const connectSyncSpy = jest.spyOn(connectMock.Interop, 'connectSync');
|
||||
|
||||
await openfinHandler.connect();
|
||||
const info = openfinHandler.getInfo();
|
||||
const isConnected = openfinHandler.getConnectionStatus();
|
||||
|
||||
expect(connect).toHaveBeenCalled();
|
||||
expect(connectSyncSpy).toHaveBeenCalledTimes(1);
|
||||
expect(info.isConnected).toBeTruthy();
|
||||
expect(isConnected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should fire an intent', async () => {
|
||||
const connectSyncMock = await connectMock.Interop.connectSync();
|
||||
const fireIntentSpy = jest.spyOn(connectSyncMock, 'fireIntent');
|
||||
|
||||
await openfinHandler.connect();
|
||||
const customIntent = {
|
||||
type: 'fdc3.contact',
|
||||
name: 'Andy Young',
|
||||
id: {
|
||||
email: 'andy.young@example.com',
|
||||
},
|
||||
};
|
||||
await openfinHandler.fireIntent(customIntent);
|
||||
|
||||
expect(fireIntentSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should register an intent handler', async () => {
|
||||
const connectSyncMock = await connectMock.Interop.connectSync();
|
||||
const intentHandlerRegistrationSpy = jest.spyOn(
|
||||
connectSyncMock,
|
||||
'registerIntentHandler',
|
||||
);
|
||||
|
||||
await openfinHandler.connect();
|
||||
await openfinHandler.registerIntentHandler('my-intent');
|
||||
|
||||
expect(intentHandlerRegistrationSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should join a context group', async () => {
|
||||
const connectSyncMock = await connectMock.Interop.connectSync();
|
||||
const joinContextGroupSpy = jest.spyOn(connectSyncMock, 'joinContextGroup');
|
||||
|
||||
await openfinHandler.connect();
|
||||
await openfinHandler.joinContextGroup('contextGroupId');
|
||||
|
||||
expect(joinContextGroupSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should return all context groups', async () => {
|
||||
const connectSyncMock = await connectMock.Interop.connectSync();
|
||||
const getContextGroupsSpy = jest.spyOn(connectSyncMock, 'getContextGroups');
|
||||
|
||||
await openfinHandler.connect();
|
||||
await openfinHandler.getContextGroups();
|
||||
|
||||
expect(getContextGroupsSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should return all clients in a given context group', async () => {
|
||||
const connectSyncMock = await connectMock.Interop.connectSync();
|
||||
const getAllClientsInContextGroupSpy = jest.spyOn(
|
||||
connectSyncMock,
|
||||
'getAllClientsInContextGroup',
|
||||
);
|
||||
|
||||
await openfinHandler.connect();
|
||||
await openfinHandler.getAllClientsInContextGroup('contextGroup1');
|
||||
|
||||
expect(getAllClientsInContextGroupSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
@ -91,6 +91,12 @@ describe('Plist Handler', () => {
|
||||
whitelistUrl: undefined,
|
||||
chromeFlags: undefined,
|
||||
latestAutoUpdateChannelEnabled: undefined,
|
||||
openfin: {
|
||||
autoConnect: undefined,
|
||||
licenseKey: undefined,
|
||||
runtimeVersion: undefined,
|
||||
uuid: undefined,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -34,6 +34,7 @@ describe('Shell Script Field Validation', () => {
|
||||
'notificationSettings',
|
||||
'customFlags',
|
||||
'permissions',
|
||||
'openfin',
|
||||
]);
|
||||
|
||||
// Read fields from post install script file
|
||||
@ -54,12 +55,12 @@ describe('Shell Script Field Validation', () => {
|
||||
'notificationSettings',
|
||||
'customFlags',
|
||||
'permissions',
|
||||
'openfin',
|
||||
]);
|
||||
|
||||
// Read fields from post install script file
|
||||
const scriptFields = extractSystemDefaults(scriptFilePath);
|
||||
scriptFields.splice(scriptFields.indexOf('ApplicationName'), 1);
|
||||
|
||||
expect(isArraySubset(scriptFields, filteredFields)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -83,6 +83,7 @@ export interface IConfig {
|
||||
isPodUrlEditable?: boolean;
|
||||
sdaInstallerMsiUrlEnabledVisible?: boolean;
|
||||
sdaInstallerMsiUrlBetaEnabledVisible?: boolean;
|
||||
openfin?: IOpenfin;
|
||||
}
|
||||
|
||||
export interface IGlobalConfig {
|
||||
@ -163,6 +164,13 @@ export interface ICustomRectangle extends Partial<Electron.Rectangle> {
|
||||
isFullScreen?: boolean;
|
||||
}
|
||||
|
||||
export interface IOpenfin {
|
||||
uuid: string;
|
||||
licenseKey: string;
|
||||
runtimeVersion: string;
|
||||
autoConnect: boolean;
|
||||
}
|
||||
|
||||
class Config {
|
||||
public userConfig: IConfig | {};
|
||||
public globalConfig: IConfig | {};
|
||||
|
@ -59,6 +59,7 @@ import { getCommandLineArgs } from '../common/utils';
|
||||
import callNotificationHelper from '../renderer/call-notification-helper';
|
||||
import { autoUpdate, AutoUpdateTrigger } from './auto-update-handler';
|
||||
import { SDAUserSessionActionTypes } from './bi/interface';
|
||||
import { openfinHandler } from './openfin-handler';
|
||||
import { presenceStatus } from './presence-status-handler';
|
||||
import { appStats } from './stats';
|
||||
import { presenceStatusStore, sdaMenuStore } from './stores/index';
|
||||
@ -559,6 +560,21 @@ ipcMain.on(
|
||||
|
||||
helpMenu.setValue(helpCenter);
|
||||
break;
|
||||
case apiCmds.openfinConnect:
|
||||
openfinHandler.connect();
|
||||
break;
|
||||
case apiCmds.openfinFireIntent:
|
||||
openfinHandler.fireIntent(arg.intent);
|
||||
break;
|
||||
case apiCmds.openfinJoinContextGroup:
|
||||
openfinHandler.joinContextGroup(arg.contextGroupId, arg.target);
|
||||
break;
|
||||
case apiCmds.openfinRegisterIntentHandler:
|
||||
openfinHandler.registerIntentHandler(arg.intentName);
|
||||
break;
|
||||
case apiCmds.openfinUnregisterIntentHandler:
|
||||
openfinHandler.unregisterIntentHandler(arg.intentName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -627,6 +643,14 @@ ipcMain.handle(
|
||||
return getContentWindowHandle(windowHandle);
|
||||
}
|
||||
break;
|
||||
case apiCmds.openfinGetConnectionStatus:
|
||||
return openfinHandler.getConnectionStatus();
|
||||
case apiCmds.openfinGetInfo:
|
||||
return openfinHandler.getInfo();
|
||||
case apiCmds.openfinGetContextGroups:
|
||||
return openfinHandler.getContextGroups();
|
||||
case apiCmds.openfinGetAllClientsInContextGroup:
|
||||
return openfinHandler.getAllClientsInContextGroup(arg.contextGroupId);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
140
src/app/openfin-handler.ts
Normal file
140
src/app/openfin-handler.ts
Normal file
@ -0,0 +1,140 @@
|
||||
import { connect } from '@openfin/node-adapter';
|
||||
import { logger } from '../common/openfin-logger';
|
||||
import { config, IConfig } from './config-handler';
|
||||
import { windowHandler } from './window-handler';
|
||||
|
||||
export class OpenfinHandler {
|
||||
private interopClient;
|
||||
private intentHandlerSubscriptions = new Map();
|
||||
private isConnected: boolean = false;
|
||||
|
||||
/**
|
||||
* Connection to interop brocker
|
||||
*/
|
||||
public async connect() {
|
||||
logger.info('openfin-handler: connecting');
|
||||
const { openfin }: IConfig = config.getConfigFields(['openfin']);
|
||||
if (openfin) {
|
||||
const fin = await connect({
|
||||
uuid: openfin.uuid,
|
||||
licenseKey: openfin.licenseKey,
|
||||
runtime: {
|
||||
version: openfin.runtimeVersion,
|
||||
},
|
||||
});
|
||||
logger.info('openfin-handler: connected');
|
||||
logger.info('openfin-handler: connecting to interop broker');
|
||||
this.interopClient = fin.Interop.connectSync(
|
||||
'workspace-platform-starter',
|
||||
);
|
||||
this.isConnected = true;
|
||||
this.interopClient.onDisconnection((event) => {
|
||||
const { brokerName } = event;
|
||||
logger.warn(
|
||||
`openfin-handler: Disconnected from Interop Broker ${brokerName} `,
|
||||
);
|
||||
this.clearSubscriptions();
|
||||
});
|
||||
return;
|
||||
}
|
||||
logger.error('openfin-handler: missing openfin params to connect.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an intent to the Interop Broker
|
||||
*/
|
||||
public fireIntent(intent) {
|
||||
this.interopClient.fireIntent(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an intent handler for incoming intents
|
||||
*/
|
||||
public async registerIntentHandler(intentName: string) {
|
||||
const unsubscriptionCallback =
|
||||
await this.interopClient.registerIntentHandler(
|
||||
this.intentHandler,
|
||||
intentName,
|
||||
);
|
||||
this.intentHandlerSubscriptions.set(intentName, unsubscriptionCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an intent handler for a given intent
|
||||
*/
|
||||
public unregisterIntentHandler(intentName) {
|
||||
const unsubscriptionCallback =
|
||||
this.intentHandlerSubscriptions.get(intentName);
|
||||
unsubscriptionCallback.unsubscribe();
|
||||
this.intentHandlerSubscriptions.delete(intentName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join all Interop Clients at the given identity to context group contextGroupId. If no target is specified, it adds the sender to the context group.
|
||||
*/
|
||||
public async joinContextGroup(contextGroupId: string, target?: any) {
|
||||
await this.interopClient.joinContextGroup(contextGroupId, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Interop-Broker-defined context groups available for an entity to join.
|
||||
*/
|
||||
public async getContextGroups() {
|
||||
return this.interopClient.getContextGroups();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all clients for a context group.
|
||||
*/
|
||||
public getAllClientsInContextGroup(contextGroupId: string) {
|
||||
return this.interopClient.getAllClientsInContextGroup(contextGroupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all openfin subscriptions
|
||||
*/
|
||||
public clearSubscriptions() {
|
||||
this.isConnected = false;
|
||||
this.interopClient = undefined;
|
||||
this.intentHandlerSubscriptions.forEach(
|
||||
(unsubscriptionCallback, intent) => {
|
||||
try {
|
||||
unsubscriptionCallback.unsubscribe();
|
||||
} catch (e) {
|
||||
logger.error(
|
||||
`openfin-handler: Error unsubscribing from intent ${intent}:`,
|
||||
e,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
this.intentHandlerSubscriptions.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns openfin connection status
|
||||
*/
|
||||
public getConnectionStatus(): boolean {
|
||||
return this.isConnected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns connection status and provider name
|
||||
*/
|
||||
public getInfo() {
|
||||
return {
|
||||
provider: 'Openfin',
|
||||
isConnected: this.getConnectionStatus(),
|
||||
};
|
||||
}
|
||||
|
||||
private intentHandler = (intent: any) => {
|
||||
logger.info('openfin-handler: intent received - ', intent);
|
||||
const mainWebContents = windowHandler.getMainWebContents();
|
||||
mainWebContents?.send('intent-received', intent.name);
|
||||
};
|
||||
}
|
||||
|
||||
const openfinHandler = new OpenfinHandler();
|
||||
|
||||
export { openfinHandler };
|
@ -65,6 +65,13 @@ const PERMISSIONS = {
|
||||
openExternal: 'boolean',
|
||||
};
|
||||
|
||||
const OPENFIN = {
|
||||
uuid: 'string',
|
||||
licenseKey: 'string',
|
||||
runtimeVersion: 'string',
|
||||
autoConnect: 'boolean',
|
||||
};
|
||||
|
||||
export const getAllUserDefaults = (): IConfig => {
|
||||
const settings: any = {};
|
||||
|
||||
@ -113,6 +120,14 @@ export const getAllUserDefaults = (): IConfig => {
|
||||
PERMISSIONS[key],
|
||||
);
|
||||
});
|
||||
|
||||
Object.keys(OPENFIN).map((key) => {
|
||||
if (!settings.openfin) {
|
||||
settings.openfin = {};
|
||||
}
|
||||
settings.openfin[key] = systemPreferences.getUserDefault(key, OPENFIN[key]);
|
||||
});
|
||||
|
||||
logger.info('plist-handler: getting all user defaults', settings);
|
||||
return settings;
|
||||
};
|
||||
@ -161,6 +176,18 @@ export const setPlistFromPreviousSettings = (
|
||||
}
|
||||
systemPreferences.setUserDefault(key, PERMISSIONS[key], value);
|
||||
});
|
||||
|
||||
Object.keys(OPENFIN).map((key) => {
|
||||
let value = settings?.openfin?.[key];
|
||||
if (value === undefined) {
|
||||
if (appGlobalConfig?.openfin?.[key] === undefined) {
|
||||
return;
|
||||
}
|
||||
value = appGlobalConfig.openfin[key];
|
||||
}
|
||||
systemPreferences.setUserDefault(key, OPENFIN[key], value);
|
||||
});
|
||||
|
||||
systemPreferences.setUserDefault('installVariant', 'string', getGuid());
|
||||
};
|
||||
|
||||
|
@ -55,6 +55,7 @@ import { notification } from '../renderer/notification';
|
||||
import { autoLaunchInstance } from './auto-launch-controller';
|
||||
import { autoUpdate, AutoUpdateTrigger } from './auto-update-handler';
|
||||
import { mainEvents } from './main-event-handler';
|
||||
import { openfinHandler } from './openfin-handler';
|
||||
import { presenceStatus } from './presence-status-handler';
|
||||
import { presenceStatusStore } from './stores';
|
||||
interface IStyles {
|
||||
@ -472,7 +473,8 @@ export const sanitize = (windowName: string): void => {
|
||||
if (mainWindow && windowName === mainWindow.winName) {
|
||||
// reset the badge count whenever an user refreshes the electron client
|
||||
showBadgeCount(0);
|
||||
|
||||
// Clear all openfin subscriptions
|
||||
openfinHandler.clearSubscriptions();
|
||||
// Terminates the screen snippet process and screen share indicator frame on reload
|
||||
if (!isMac || !isLinux) {
|
||||
logger.info(
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { UUID } from 'crypto';
|
||||
import { NativeImage, Size, Tray } from 'electron';
|
||||
import { AutoUpdateTrigger } from '../app/auto-update-handler';
|
||||
|
||||
@ -82,6 +83,16 @@ export enum apiCmds {
|
||||
registerPhoneNumberServices = 'register-phone-numbers-services',
|
||||
unregisterPhoneNumberServices = 'unregister-phone-numbers-services',
|
||||
getHelpInfo = 'get-help-info',
|
||||
// Openfin API commands
|
||||
openfinConnect = 'openfin-connect',
|
||||
openfinFireIntent = 'openfin-fire-intent',
|
||||
openfinRegisterIntentHandler = 'openfin-register-intent-handler',
|
||||
openfinUnregisterIntentHandler = 'openfin-unregister-intent-handler',
|
||||
openfinGetConnectionStatus = 'openfin-get-connection-status',
|
||||
openfinGetInfo = 'openfin-get-info',
|
||||
openfinJoinContextGroup = 'openfin-join-context-group',
|
||||
openfinGetContextGroups = 'openfin-get-context-groups',
|
||||
openfinGetAllClientsInContextGroup = 'openfin-get-all-clients-in-context-group',
|
||||
}
|
||||
|
||||
export enum apiName {
|
||||
@ -149,6 +160,18 @@ export interface IApiArgs {
|
||||
status: IPresenceStatus;
|
||||
protocols: PhoneNumberProtocol[];
|
||||
menu?: any;
|
||||
handler: any;
|
||||
uuid: UUID;
|
||||
intent: any;
|
||||
intentHandler: any;
|
||||
intentName: any;
|
||||
infoForIntentOptions: any;
|
||||
context: any;
|
||||
sessionContextGroupId: any;
|
||||
contextForIntent: any;
|
||||
contextType: any;
|
||||
contextGroupId: string;
|
||||
target: any;
|
||||
}
|
||||
|
||||
export type Themes = 'light' | 'dark';
|
||||
|
@ -8,4 +8,10 @@ export const ConfigFieldsDefaultValues: Partial<IConfig> = {
|
||||
latestAutoUpdateChannelEnabled: true,
|
||||
betaAutoUpdateChannelEnabled: true,
|
||||
browserLoginRetryTimeout: '5',
|
||||
openfin: {
|
||||
uuid: '',
|
||||
licenseKey: '',
|
||||
runtimeVersion: '',
|
||||
autoConnect: false,
|
||||
},
|
||||
};
|
||||
|
5
src/common/openfin-logger.ts
Normal file
5
src/common/openfin-logger.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { Logger } from './loggerBase';
|
||||
|
||||
const logger = new Logger('openfin');
|
||||
|
||||
export { logger };
|
@ -105,6 +105,19 @@ if (ssfWindow.ssf) {
|
||||
registerPhoneNumberServices: ssfWindow.ssf.registerPhoneNumberServices,
|
||||
unregisterPhoneNumberServices: ssfWindow.ssf.unregisterPhoneNumberServices,
|
||||
});
|
||||
|
||||
contextBridge.exposeInMainWorld('openfin', {
|
||||
init: ssfWindow.ssf.openfinInit,
|
||||
getInfo: ssfWindow.ssf.openfinGetInfo,
|
||||
getConnectionStatus: ssfWindow.ssf.openfinGetConnectionStatus,
|
||||
fireIntent: ssfWindow.ssf.openfinFireIntent,
|
||||
registerIntentHandler: ssfWindow.ssf.openfinRegisterIntentHandler,
|
||||
unregisterIntentHandler: ssfWindow.ssf.openfinUnregisterIntentHandler,
|
||||
getContextGroups: ssfWindow.ssf.openfinGetContextGroups,
|
||||
joinContextGroup: ssfWindow.ssf.openfinJoinContextGroup,
|
||||
getAllClientsInContextGroup:
|
||||
ssfWindow.ssf.openfinGetAllClientsInContextGroup,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,12 +66,14 @@ export interface ILocalObject {
|
||||
c9MessageCallback?: (status: IShellStatus) => void;
|
||||
updateMyPresenceCallback?: (presence: EPresenceStatusCategory) => void;
|
||||
phoneNumberCallback?: (arg: string) => void;
|
||||
intentsCallbacks: {};
|
||||
writeImageToClipboard?: (blob: string) => void;
|
||||
getHelpInfo?: () => Promise<IPodSettingsClientSpecificSupportLink>;
|
||||
}
|
||||
|
||||
const local: ILocalObject = {
|
||||
ipcRenderer,
|
||||
intentsCallbacks: {},
|
||||
};
|
||||
|
||||
const notificationActionCallbacks = new Map<
|
||||
@ -952,6 +954,107 @@ export class SSFApi {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Openfin Interop client initialization
|
||||
*/
|
||||
public openfinInit(): void {
|
||||
local.ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.openfinConnect,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns provider and connection status
|
||||
*/
|
||||
public async openfinGetInfo() {
|
||||
const info = await local.ipcRenderer.invoke(apiName.symphonyApi, {
|
||||
cmd: apiCmds.openfinGetInfo,
|
||||
});
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires an intent
|
||||
*/
|
||||
public openfinFireIntent(intent: any): void {
|
||||
local.ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.openfinFireIntent,
|
||||
intent,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns Openfin connection status
|
||||
*/
|
||||
public async openfinGetConnectionStatus() {
|
||||
const connectionStatus = await local.ipcRenderer.invoke(
|
||||
apiName.symphonyApi,
|
||||
{
|
||||
cmd: apiCmds.openfinGetConnectionStatus,
|
||||
},
|
||||
);
|
||||
return connectionStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a handler for a given intent
|
||||
*/
|
||||
public openfinRegisterIntentHandler(
|
||||
intentHandler: any,
|
||||
intentName: any,
|
||||
): void {
|
||||
local.intentsCallbacks[intentName] = intentHandler;
|
||||
local.ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.openfinRegisterIntentHandler,
|
||||
intentName,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a handler based on a given intent name
|
||||
* @param intentName
|
||||
*/
|
||||
public openfinUnregisterIntentHandler(intentName: string): void {
|
||||
local.ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.openfinUnregisterIntentHandler,
|
||||
intentName,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns openfin context groups
|
||||
*/
|
||||
public async openfinGetContextGroups() {
|
||||
const contextGroups = await local.ipcRenderer.invoke(apiName.symphonyApi, {
|
||||
cmd: apiCmds.openfinGetContextGroups,
|
||||
});
|
||||
return contextGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to join an Openfin context group
|
||||
* @param contextGroupId
|
||||
* @param target
|
||||
*/
|
||||
public openfinJoinContextGroup(contextGroupId: string, target?: any) {
|
||||
local.ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.openfinJoinContextGroup,
|
||||
contextGroupId,
|
||||
target,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns registered clients in a given context group
|
||||
*/
|
||||
public openfinGetAllClientsInContextGroup(contextGroupId: string) {
|
||||
return local.ipcRenderer.invoke(apiName.symphonyApi, {
|
||||
cmd: apiCmds.openfinGetAllClientsInContextGroup,
|
||||
contextGroupId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows JS to register SDA for phone numbers clicks
|
||||
* @param {Function} phoneNumberCallback callback function invoked when receiving a phone number for calls/sms
|
||||
@ -1290,6 +1393,12 @@ local.ipcRenderer.on(
|
||||
},
|
||||
);
|
||||
|
||||
local.ipcRenderer.on('intent-received', (_event: Event, intentName: string) => {
|
||||
if (typeof intentName === 'string' && local.intentsCallbacks[intentName]) {
|
||||
local.intentsCallbacks[intentName]();
|
||||
}
|
||||
});
|
||||
|
||||
// Invoked whenever the app is reloaded/navigated
|
||||
const sanitize = (): void => {
|
||||
if (window.name === apiName.mainWindowName) {
|
||||
@ -1298,6 +1407,7 @@ const sanitize = (): void => {
|
||||
windowName: window.name,
|
||||
});
|
||||
}
|
||||
local.intentsCallbacks = {};
|
||||
};
|
||||
|
||||
// listens for the online/offline events and updates the main process
|
||||
|
Loading…
Reference in New Issue
Block a user