mirror of
https://github.com/finos/SymphonyElectron.git
synced 2024-11-26 02:40:24 -06:00
Merge branch 'master' into master
This commit is contained in:
commit
cb27e2022f
@ -1,14 +1,16 @@
|
||||
{
|
||||
"url":"https://foundation-dev.symphony.com",
|
||||
"minimizeOnClose" : true,
|
||||
"launchOnStartup" : true,
|
||||
"alwaysOnTop" : false,
|
||||
"bringToFront": false,
|
||||
"minimizeOnClose" : "ENABLED",
|
||||
"launchOnStartup" : "ENABLED",
|
||||
"alwaysOnTop" : "DISABLED",
|
||||
"bringToFront": "DISABLED",
|
||||
"whitelistUrl": "*",
|
||||
"isCustomTitleBar": true,
|
||||
"memoryRefresh": true,
|
||||
"isCustomTitleBar": "ENABLED",
|
||||
"memoryRefresh": "ENABLED",
|
||||
"memoryThreshold": "800",
|
||||
"devToolsEnabled": true,
|
||||
"contextIsolation": true,
|
||||
"disableGpu": false,
|
||||
"ctWhitelist": [],
|
||||
"podWhitelist": [],
|
||||
"notificationSettings": {
|
||||
@ -18,7 +20,6 @@
|
||||
"customFlags": {
|
||||
"authServerWhitelist": "",
|
||||
"authNegotiateDelegateWhitelist": "",
|
||||
"disableGpu": false,
|
||||
"disableThrottling": false
|
||||
},
|
||||
"permissions": {
|
||||
|
@ -12,7 +12,7 @@ delete_app()
|
||||
compare_versions()
|
||||
{
|
||||
# Get the installer version:
|
||||
CURRENT_VERSION=6.0.0
|
||||
CURRENT_VERSION=APP_VERSION
|
||||
|
||||
# Get the currently installed version:
|
||||
INSTALLED_VERSION=$(plutil -p /Applications/Symphony.app/Contents/Info.plist | awk '/CFBundleShortVersionString/ {print substr($3, 2, length($3)-2)}')
|
||||
|
32
package-lock.json
generated
32
package-lock.json
generated
@ -4736,9 +4736,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"electron": {
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/electron/-/electron-6.1.5.tgz",
|
||||
"integrity": "sha1-HxvFQEJYfYNo7dQ//ssM58hMq4c=",
|
||||
"version": "6.1.7",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/electron/-/electron-6.1.7.tgz",
|
||||
"integrity": "sha1-pnaV+B9ct3Hjlbz5cRVgUg40fFQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "^10.12.18",
|
||||
@ -4747,9 +4747,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "10.17.6",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/@types/node/-/node-10.17.6.tgz",
|
||||
"integrity": "sha1-Gqq9b2Rwpqw4JKselNcxyhMm2T0=",
|
||||
"version": "10.17.13",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/@types/node/-/node-10.17.13.tgz",
|
||||
"integrity": "sha1-zOvNuZC9YTnNFuhMOdwvsQI8qQw=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@ -12701,6 +12701,12 @@
|
||||
"integrity": "sha1-LpZJFZmpbN4bUV1WdKj3qRRSkmo=",
|
||||
"dev": true
|
||||
},
|
||||
"run-script-os": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/run-script-os/-/run-script-os-1.0.7.tgz",
|
||||
"integrity": "sha1-fNURRKGcbKNk/maEM/VbR7q/R0k=",
|
||||
"optional": true
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "5.5.11",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/rxjs/-/rxjs-5.5.11.tgz",
|
||||
@ -13060,9 +13066,12 @@
|
||||
}
|
||||
},
|
||||
"screen-share-indicator-frame": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "git+https://github.com/symphonyoss/ScreenShareIndicatorFrame.git#14cf6452610252458650056d568918345abf4eb4",
|
||||
"optional": true
|
||||
"version": "1.4.0",
|
||||
"resolved": "git+https://github.com/symphonyoss/ScreenShareIndicatorFrame.git#adc3fdb0fa96629773ea2bc13b20b9ffd109ac1d",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"run-script-os": "1.0.7"
|
||||
}
|
||||
},
|
||||
"screen-snippet": {
|
||||
"version": "1.0.6",
|
||||
@ -13908,6 +13917,11 @@
|
||||
"acorn-node": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"systeminformation": {
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/systeminformation/-/systeminformation-4.21.0.tgz",
|
||||
"integrity": "sha1-BAmd3CGK1CmQxL6A98IexO/2upw="
|
||||
},
|
||||
"tar": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/tar/-/tar-2.2.1.tgz",
|
||||
|
@ -142,7 +142,8 @@
|
||||
"react": "16.9.0",
|
||||
"react-dom": "16.9.0",
|
||||
"ref-napi": "1.4.1",
|
||||
"shell-path": "2.1.0"
|
||||
"shell-path": "2.1.0",
|
||||
"systeminformation": "4.21.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"screen-snippet": "git+https://github.com/symphonyoss/ScreenSnippet2.git#v1.0.6",
|
||||
|
@ -32,14 +32,10 @@ exports[`about app should render correctly 1`] = `
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div
|
||||
className="AboutApp-main-container"
|
||||
>
|
||||
<section>
|
||||
<h4>
|
||||
Symphony
|
||||
</h4>
|
||||
<ul
|
||||
className="AboutApp-symphony-section"
|
||||
>
|
||||
@ -50,13 +46,6 @@ exports[`about app should render correctly 1`] = `
|
||||
|
||||
N/A (N/A)
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
SFE:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
SDA:
|
||||
@ -64,99 +53,9 @@ exports[`about app should render correctly 1`] = `
|
||||
|
||||
N/A (N/A)
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<h4>
|
||||
Electron
|
||||
</h4>
|
||||
<ul
|
||||
className="AboutApp-electron-section"
|
||||
>
|
||||
<li>
|
||||
<b>
|
||||
Electron:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
Chrome:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
V8:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
Node:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<h4>
|
||||
Others
|
||||
</h4>
|
||||
<ul
|
||||
className="AboutApp-others-section"
|
||||
>
|
||||
<li>
|
||||
<b>
|
||||
openssl:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
zlib:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
uv:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
ares:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
http_parser:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
Swift Search
|
||||
:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
</li>
|
||||
<li>
|
||||
<b>
|
||||
Swift Search API
|
||||
:
|
||||
SFE:
|
||||
</b>
|
||||
|
||||
N/A
|
||||
@ -164,7 +63,6 @@ exports[`about app should render correctly 1`] = `
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<button
|
||||
className="AboutApp-copy-button"
|
||||
|
@ -39,14 +39,20 @@ jest.mock('../src/app/auto-launch-controller', () => {
|
||||
|
||||
jest.mock('../src/app/config-handler', () => {
|
||||
return {
|
||||
CloudConfigDataTypes: {
|
||||
NOT_SET: 'NOT_SET',
|
||||
ENABLED: 'ENABLED',
|
||||
DISABLED: 'DISABLED',
|
||||
},
|
||||
config: {
|
||||
getConfigFields: jest.fn(() => {
|
||||
return {
|
||||
minimizeOnClose: true,
|
||||
launchOnStartup: true,
|
||||
alwaysOnTop: true,
|
||||
isAlwaysOnTop: true,
|
||||
bringToFront: true,
|
||||
minimizeOnClose: 'ENABLED',
|
||||
launchOnStartup: 'ENABLED',
|
||||
alwaysOnTop: 'ENABLED',
|
||||
isAlwaysOnTop: 'ENABLED',
|
||||
bringToFront: 'ENABLED',
|
||||
devToolsEnabled: true,
|
||||
};
|
||||
}),
|
||||
getGlobalConfigFields: jest.fn(() => {
|
||||
@ -54,6 +60,16 @@ jest.mock('../src/app/config-handler', () => {
|
||||
devToolsEnabled: true,
|
||||
};
|
||||
}),
|
||||
getFilteredCloudConfigFields: jest.fn(() => {
|
||||
return {
|
||||
devToolsEnabled: true,
|
||||
};
|
||||
}),
|
||||
getCloudConfigFields: jest.fn(() => {
|
||||
return {
|
||||
devToolsEnabled: true,
|
||||
};
|
||||
}),
|
||||
updateUserConfig: jest.fn(),
|
||||
},
|
||||
};
|
||||
@ -202,7 +218,7 @@ describe('app menu', () => {
|
||||
it('should disable `AutoLaunch` when click is triggered', async () => {
|
||||
const spyFn = 'disableAutoLaunch';
|
||||
const spyConfig = jest.spyOn(config, updateUserFnLabel);
|
||||
const expectedValue = { launchOnStartup: false };
|
||||
const expectedValue = { launchOnStartup: 'NOT_SET' };
|
||||
const spy = jest.spyOn(autoLaunchInstance, spyFn);
|
||||
const customItem = {
|
||||
checked: false,
|
||||
@ -215,7 +231,7 @@ describe('app menu', () => {
|
||||
it('should enable `AutoLaunch` when click is triggered', async () => {
|
||||
const spyFn = 'enableAutoLaunch';
|
||||
const spyConfig = jest.spyOn(config, updateUserFnLabel);
|
||||
const expectedValue = { launchOnStartup: true };
|
||||
const expectedValue = { launchOnStartup: 'ENABLED' };
|
||||
const spy = jest.spyOn(autoLaunchInstance, spyFn);
|
||||
await autoLaunchMenuItem.click(item);
|
||||
expect(spy).toBeCalled();
|
||||
@ -231,7 +247,7 @@ describe('app menu', () => {
|
||||
|
||||
it('should update `minimizeOnClose` value when click is triggered', async () => {
|
||||
const spyConfig = jest.spyOn(config, updateUserFnLabel);
|
||||
const expectedValue = { minimizeOnClose: true };
|
||||
const expectedValue = { minimizeOnClose: 'ENABLED' };
|
||||
const menuItem = findMenuItemBuildWindowMenu('Minimize on Close');
|
||||
await menuItem.click(item);
|
||||
expect(spyConfig).lastCalledWith(expectedValue);
|
||||
@ -240,7 +256,7 @@ describe('app menu', () => {
|
||||
describe('`bringToFront`', () => {
|
||||
it('should update `bringToFront` value when click is triggered', async () => {
|
||||
const spyConfig = jest.spyOn(config, updateUserFnLabel);
|
||||
const expectedValue = { bringToFront: true };
|
||||
const expectedValue = { bringToFront: 'ENABLED' };
|
||||
const menuItem = findMenuItemBuildWindowMenu('Bring to Front on Notifications');
|
||||
await menuItem.click(item);
|
||||
expect(spyConfig).lastCalledWith(expectedValue);
|
||||
|
@ -3,17 +3,17 @@ import { config } from '../src/app/config-handler';
|
||||
import { isDevEnv, isLinux, isMac, isWindowsOS } from '../src/common/env';
|
||||
import { app } from './__mocks__/electron';
|
||||
|
||||
jest.mock('../src/common/utils', () => {
|
||||
jest.mock('../src/app/config-handler', () => {
|
||||
return {
|
||||
config: {
|
||||
getGlobalConfigFields: jest.fn(() => {
|
||||
getConfigFields: jest.fn(() => {
|
||||
return {
|
||||
customFlags: {
|
||||
authServerWhitelist: 'url',
|
||||
authNegotiateDelegateWhitelist: 'whitelist',
|
||||
disableGpu: true,
|
||||
disableThrottling: false,
|
||||
},
|
||||
disableGpu: true,
|
||||
};
|
||||
}),
|
||||
},
|
||||
@ -35,13 +35,13 @@ describe('chrome flags', () => {
|
||||
(isMac as any) = true;
|
||||
(isWindowsOS as any) = false;
|
||||
(isLinux as any) = false;
|
||||
config.getGlobalConfigFields = jest.fn(() => {
|
||||
config.getConfigFields = jest.fn(() => {
|
||||
return {
|
||||
customFlags: {
|
||||
authServerWhitelist: 'url',
|
||||
authNegotiateDelegateWhitelist: 'whitelist',
|
||||
disableGpu: true,
|
||||
},
|
||||
disableGpu: true,
|
||||
};
|
||||
});
|
||||
jest.clearAllMocks();
|
||||
@ -59,7 +59,7 @@ describe('chrome flags', () => {
|
||||
});
|
||||
|
||||
it('should call `setChromeFlags` correctly when `disableGpu` is false', () => {
|
||||
config.getGlobalConfigFields = jest.fn(() => {
|
||||
config.getConfigFields = jest.fn(() => {
|
||||
return {
|
||||
customFlags: {
|
||||
authServerWhitelist: 'url',
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { IConfig } from '../src/app/config-handler';
|
||||
import { IConfig, IGlobalConfig } from '../src/app/config-handler';
|
||||
|
||||
jest.mock('electron-log');
|
||||
|
||||
@ -75,7 +75,7 @@ describe('config', () => {
|
||||
configInstance.readUserConfig();
|
||||
configInstance.readGlobalConfig();
|
||||
|
||||
const configField: IConfig = configInstance.getConfigFields(fieldMock);
|
||||
const configField: IGlobalConfig = configInstance.getGlobalConfigFields(fieldMock);
|
||||
|
||||
expect(configField.url).toBe('something');
|
||||
});
|
||||
|
@ -71,10 +71,15 @@ jest.mock('../src/common/logger', () => {
|
||||
|
||||
jest.mock('../src/app/config-handler', () => {
|
||||
return {
|
||||
CloudConfigDataTypes: {
|
||||
NOT_SET: 'NOT_SET',
|
||||
ENABLED: 'ENABLED',
|
||||
DISABLED: 'DISABLED',
|
||||
},
|
||||
config: {
|
||||
getConfigFields: jest.fn(() => {
|
||||
return {
|
||||
bringToFront: true,
|
||||
bringToFront: 'ENABLED',
|
||||
};
|
||||
}),
|
||||
},
|
||||
|
@ -10,8 +10,8 @@ import {
|
||||
MenuActionTypes,
|
||||
} from './analytics-handler';
|
||||
import { autoLaunchInstance as autoLaunch } from './auto-launch-controller';
|
||||
import { config, IConfig } from './config-handler';
|
||||
import { titleBarChangeDialog } from './dialog-handler';
|
||||
import { CloudConfigDataTypes, config, IConfig } from './config-handler';
|
||||
import { gpuRestartDialog, titleBarChangeDialog } from './dialog-handler';
|
||||
import { exportCrashDumps, exportLogs } from './reports-handler';
|
||||
import { updateAlwaysOnTop } from './window-actions';
|
||||
import { ICustomBrowserWindow, windowHandler } from './window-handler';
|
||||
@ -25,11 +25,6 @@ export const menuSections = {
|
||||
help: 'help', // tslint:disable-line
|
||||
};
|
||||
|
||||
enum TitleBarStyles {
|
||||
CUSTOM,
|
||||
NATIVE,
|
||||
}
|
||||
|
||||
const windowsAccelerator = Object.assign({
|
||||
close: 'Ctrl+W',
|
||||
copy: 'Ctrl+C',
|
||||
@ -52,12 +47,16 @@ let {
|
||||
alwaysOnTop: isAlwaysOnTop,
|
||||
bringToFront,
|
||||
memoryRefresh,
|
||||
isCustomTitleBar,
|
||||
devToolsEnabled,
|
||||
} = config.getConfigFields([
|
||||
'minimizeOnClose',
|
||||
'launchOnStartup',
|
||||
'alwaysOnTop',
|
||||
'bringToFront',
|
||||
'memoryRefresh',
|
||||
'isCustomTitleBar',
|
||||
'devToolsEnabled',
|
||||
]) as IConfig;
|
||||
let initialAnalyticsSent = false;
|
||||
|
||||
@ -66,29 +65,30 @@ const menuItemsArray = Object.keys(menuSections)
|
||||
.filter((value) => isMac ?
|
||||
true : value !== menuSections.about);
|
||||
|
||||
const { devToolsEnabled } = config.getGlobalConfigFields([ 'devToolsEnabled' ]);
|
||||
|
||||
export class AppMenu {
|
||||
private menu: Electron.Menu | undefined;
|
||||
private menuList: Electron.MenuItemConstructorOptions[];
|
||||
private locale: LocaleType;
|
||||
private titleBarStyle: TitleBarStyles;
|
||||
private cloudConfig: IConfig | {};
|
||||
|
||||
private readonly menuItemConfigFields: string[];
|
||||
private disableGpu: boolean;
|
||||
|
||||
constructor() {
|
||||
this.menuList = [];
|
||||
this.locale = i18n.getLocale();
|
||||
this.titleBarStyle = config.getConfigFields([ 'isCustomTitleBar' ]).isCustomTitleBar
|
||||
? TitleBarStyles.CUSTOM
|
||||
: TitleBarStyles.NATIVE;
|
||||
this.menuItemConfigFields = [ 'minimizeOnClose', 'launchOnStartup', 'alwaysOnTop', 'bringToFront', 'memoryRefresh', 'isCustomTitleBar', 'devToolsEnabled' ];
|
||||
this.cloudConfig = config.getFilteredCloudConfigFields(this.menuItemConfigFields);
|
||||
this.disableGpu = config.getConfigFields(['disableGpu']).disableGpu;
|
||||
this.buildMenu();
|
||||
// send initial analytic
|
||||
if (!initialAnalyticsSent) {
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.MINIMIZE_ON_CLOSE, minimizeOnClose);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.AUTO_LAUNCH_ON_START_UP, launchOnStartup);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.ALWAYS_ON_TOP, isAlwaysOnTop);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.FLASH_NOTIFICATION_IN_TASK_BAR, bringToFront);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.REFRESH_APP_IN_IDLE, memoryRefresh);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.HAMBURGER_MENU, (isMac || isLinux) ? false : this.titleBarStyle === TitleBarStyles.CUSTOM);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.MINIMIZE_ON_CLOSE, minimizeOnClose === CloudConfigDataTypes.ENABLED);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.AUTO_LAUNCH_ON_START_UP, launchOnStartup === CloudConfigDataTypes.ENABLED);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.ALWAYS_ON_TOP, isAlwaysOnTop === CloudConfigDataTypes.ENABLED);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.FLASH_NOTIFICATION_IN_TASK_BAR, bringToFront === CloudConfigDataTypes.ENABLED);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.REFRESH_APP_IN_IDLE, memoryRefresh === CloudConfigDataTypes.ENABLED);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.HAMBURGER_MENU, (isMac || isLinux) ? false : isCustomTitleBar === CloudConfigDataTypes.ENABLED);
|
||||
}
|
||||
initialAnalyticsSent = true;
|
||||
}
|
||||
@ -97,6 +97,9 @@ export class AppMenu {
|
||||
* Builds the menu items for all the menu
|
||||
*/
|
||||
public buildMenu(): void {
|
||||
// updates the global variables
|
||||
this.updateGlobals();
|
||||
|
||||
this.menuList = menuItemsArray.reduce((map: Electron.MenuItemConstructorOptions, key: string) => {
|
||||
map[ key ] = this.buildMenuKey(key);
|
||||
return map;
|
||||
@ -133,6 +136,23 @@ export class AppMenu {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the global variables
|
||||
*/
|
||||
public updateGlobals(): void {
|
||||
const configData = config.getConfigFields(this.menuItemConfigFields) as IConfig;
|
||||
minimizeOnClose = configData.minimizeOnClose;
|
||||
launchOnStartup = configData.launchOnStartup;
|
||||
isAlwaysOnTop = configData.alwaysOnTop;
|
||||
bringToFront = configData.bringToFront;
|
||||
memoryRefresh = configData.memoryRefresh;
|
||||
isCustomTitleBar = configData.isCustomTitleBar;
|
||||
devToolsEnabled = configData.devToolsEnabled;
|
||||
|
||||
// fetch updated cloud config
|
||||
this.cloudConfig = config.getFilteredCloudConfigFields(this.menuItemConfigFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays popup application at the x,y coordinates
|
||||
*
|
||||
@ -257,51 +277,63 @@ export class AppMenu {
|
||||
private buildWindowMenu(): Electron.MenuItemConstructorOptions {
|
||||
logger.info(`app-menu: building window menu`);
|
||||
|
||||
const {
|
||||
alwaysOnTop: isAlwaysOnTopCC,
|
||||
minimizeOnClose: minimizeOnCloseCC,
|
||||
launchOnStartup: launchOnStartupCC,
|
||||
bringToFront: bringToFrontCC,
|
||||
memoryRefresh: memoryRefreshCC,
|
||||
isCustomTitleBar: isCustomTitleBarCC,
|
||||
} = this.cloudConfig as IConfig;
|
||||
|
||||
const submenu: MenuItemConstructorOptions[] = [
|
||||
this.assignRoleOrLabel({ role: 'minimize', label: i18n.t('Minimize')() }),
|
||||
this.assignRoleOrLabel({ role: 'close', label: i18n.t('Close')() }),
|
||||
this.buildSeparator(),
|
||||
{
|
||||
checked: launchOnStartup,
|
||||
checked: launchOnStartup === CloudConfigDataTypes.ENABLED,
|
||||
click: async (item) => {
|
||||
if (item.checked) {
|
||||
autoLaunch.enableAutoLaunch();
|
||||
} else {
|
||||
autoLaunch.disableAutoLaunch();
|
||||
}
|
||||
launchOnStartup = item.checked;
|
||||
launchOnStartup = item.checked ? CloudConfigDataTypes.ENABLED : CloudConfigDataTypes.NOT_SET;
|
||||
await config.updateUserConfig({ launchOnStartup });
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.AUTO_LAUNCH_ON_START_UP, item.checked);
|
||||
},
|
||||
label: i18n.t('Auto Launch On Startup')(),
|
||||
type: 'checkbox',
|
||||
visible: !isLinux,
|
||||
enabled: !launchOnStartupCC || launchOnStartupCC === CloudConfigDataTypes.NOT_SET,
|
||||
},
|
||||
{
|
||||
checked: isAlwaysOnTop,
|
||||
checked: isAlwaysOnTop === CloudConfigDataTypes.ENABLED,
|
||||
click: async (item) => {
|
||||
isAlwaysOnTop = item.checked;
|
||||
isAlwaysOnTop = item.checked ? CloudConfigDataTypes.ENABLED : CloudConfigDataTypes.NOT_SET;
|
||||
await updateAlwaysOnTop(item.checked, true);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.ALWAYS_ON_TOP, item.checked);
|
||||
},
|
||||
label: i18n.t('Always on Top')(),
|
||||
type: 'checkbox',
|
||||
visible: !isLinux,
|
||||
enabled: !isAlwaysOnTopCC || isAlwaysOnTopCC === CloudConfigDataTypes.NOT_SET,
|
||||
},
|
||||
{
|
||||
checked: minimizeOnClose,
|
||||
checked: minimizeOnClose === CloudConfigDataTypes.ENABLED,
|
||||
click: async (item) => {
|
||||
minimizeOnClose = item.checked;
|
||||
minimizeOnClose = item.checked ? CloudConfigDataTypes.ENABLED : CloudConfigDataTypes.NOT_SET;
|
||||
await config.updateUserConfig({ minimizeOnClose });
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.MINIMIZE_ON_CLOSE, item.checked);
|
||||
},
|
||||
label: i18n.t('Minimize on Close')(),
|
||||
type: 'checkbox',
|
||||
enabled: !minimizeOnCloseCC || minimizeOnCloseCC === CloudConfigDataTypes.NOT_SET,
|
||||
},
|
||||
{
|
||||
checked: bringToFront,
|
||||
checked: bringToFront === CloudConfigDataTypes.ENABLED,
|
||||
click: async (item) => {
|
||||
bringToFront = item.checked;
|
||||
bringToFront = item.checked ? CloudConfigDataTypes.ENABLED : CloudConfigDataTypes.NOT_SET;
|
||||
await config.updateUserConfig({ bringToFront });
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.FLASH_NOTIFICATION_IN_TASK_BAR, item.checked);
|
||||
},
|
||||
@ -309,30 +341,30 @@ export class AppMenu {
|
||||
? i18n.t('Flash Notification in Taskbar')()
|
||||
: i18n.t('Bring to Front on Notifications')(),
|
||||
type: 'checkbox',
|
||||
enabled: !bringToFrontCC || bringToFrontCC === CloudConfigDataTypes.NOT_SET,
|
||||
},
|
||||
this.buildSeparator(),
|
||||
{
|
||||
label: this.titleBarStyle === TitleBarStyles.NATIVE
|
||||
label: (isCustomTitleBar === CloudConfigDataTypes.DISABLED || isCustomTitleBar === CloudConfigDataTypes.NOT_SET)
|
||||
? i18n.t('Enable Hamburger menu')()
|
||||
: i18n.t('Disable Hamburger menu')(),
|
||||
visible: isWindowsOS,
|
||||
click: () => {
|
||||
const isNativeStyle = this.titleBarStyle === TitleBarStyles.NATIVE;
|
||||
|
||||
this.titleBarStyle = isNativeStyle ? TitleBarStyles.NATIVE : TitleBarStyles.CUSTOM;
|
||||
titleBarChangeDialog(isNativeStyle);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.HAMBURGER_MENU, this.titleBarStyle === TitleBarStyles.CUSTOM);
|
||||
titleBarChangeDialog(isCustomTitleBar === CloudConfigDataTypes.DISABLED ? CloudConfigDataTypes.ENABLED : CloudConfigDataTypes.DISABLED);
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.HAMBURGER_MENU, isCustomTitleBar === CloudConfigDataTypes.ENABLED);
|
||||
},
|
||||
enabled: !isCustomTitleBarCC || isCustomTitleBarCC === CloudConfigDataTypes.NOT_SET,
|
||||
},
|
||||
{
|
||||
checked: memoryRefresh,
|
||||
checked: memoryRefresh === CloudConfigDataTypes.ENABLED,
|
||||
click: async (item) => {
|
||||
memoryRefresh = item.checked;
|
||||
memoryRefresh = item.checked ? CloudConfigDataTypes.ENABLED : CloudConfigDataTypes.NOT_SET;
|
||||
await config.updateUserConfig({ memoryRefresh });
|
||||
this.sendAnalytics(AnalyticsElements.MENU, MenuActionTypes.REFRESH_APP_IN_IDLE, item.checked);
|
||||
},
|
||||
label: i18n.t('Refresh app when idle')(),
|
||||
type: 'checkbox',
|
||||
enabled: !memoryRefreshCC || memoryRefreshCC === CloudConfigDataTypes.NOT_SET,
|
||||
},
|
||||
{
|
||||
click: (_item, focusedWindow) => {
|
||||
@ -387,6 +419,7 @@ export class AppMenu {
|
||||
if (isLinux) {
|
||||
showCrashesLabel = i18n.t('Show crash dump in File Manager')();
|
||||
}
|
||||
const { devToolsEnabled: isDevToolsEnabledCC } = this.cloudConfig as IConfig;
|
||||
|
||||
return {
|
||||
label: i18n.t('Help')(),
|
||||
@ -409,7 +442,7 @@ export class AppMenu {
|
||||
}, {
|
||||
label: i18n.t('Toggle Developer Tools')(),
|
||||
accelerator: isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I',
|
||||
visible: devToolsEnabled,
|
||||
visible: isDevToolsEnabledCC,
|
||||
click(_item, focusedWindow) {
|
||||
if (!focusedWindow || !windowExists(focusedWindow)) {
|
||||
return;
|
||||
@ -419,6 +452,14 @@ export class AppMenu {
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: this.disableGpu
|
||||
? i18n.t('Enable GPU')()
|
||||
: i18n.t('Disable GPU')(),
|
||||
click: () => {
|
||||
gpuRestartDialog(!this.disableGpu);
|
||||
},
|
||||
} ],
|
||||
}, {
|
||||
label: i18n.t('About Symphony')(),
|
||||
|
@ -4,7 +4,7 @@ import { isMac } from '../common/env';
|
||||
import { logger } from '../common/logger';
|
||||
import { config, IConfig } from './config-handler';
|
||||
|
||||
const { autoLaunchPath }: IConfig = config.getGlobalConfigFields([ 'autoLaunchPath' ]);
|
||||
const { autoLaunchPath }: IConfig = config.getConfigFields([ 'autoLaunchPath' ]);
|
||||
|
||||
const props = isMac ? {
|
||||
mac: {
|
||||
|
@ -215,7 +215,7 @@ export const handleChildWindow = (webContents: WebContents): void => {
|
||||
}
|
||||
|
||||
// Updates media permissions for preload context
|
||||
const { permissions } = config.getGlobalConfigFields([ 'permissions' ]);
|
||||
const { permissions } = config.getConfigFields([ 'permissions' ]);
|
||||
browserWin.webContents.send('is-screen-share-enabled', permissions.media);
|
||||
}
|
||||
});
|
||||
|
@ -15,16 +15,16 @@ const specialArgs = [ '--url', '--multiInstance', '--userDataPath=', 'symphony:/
|
||||
*/
|
||||
export const setChromeFlags = () => {
|
||||
logger.info(`chrome-flags: Checking if we need to set chrome flags!`);
|
||||
const { customFlags } = config.getGlobalConfigFields([ 'customFlags' ]) as IConfig;
|
||||
|
||||
const flagsConfig = config.getConfigFields(['customFlags', 'disableGpu']) as IConfig;
|
||||
const configFlags: object = {
|
||||
'auth-negotiate-delegate-whitelist': customFlags.authServerWhitelist,
|
||||
'auth-server-whitelist': customFlags.authNegotiateDelegateWhitelist,
|
||||
'auth-negotiate-delegate-whitelist': flagsConfig.customFlags.authServerWhitelist,
|
||||
'auth-server-whitelist': flagsConfig.customFlags.authNegotiateDelegateWhitelist,
|
||||
'disable-background-timer-throttling': 'true',
|
||||
'disable-d3d11': customFlags.disableGpu || null,
|
||||
'disable-gpu': customFlags.disableGpu || null,
|
||||
'disable-gpu-compositing': customFlags.disableGpu || null,
|
||||
'disable-renderer-backgrounding': customFlags.disableThrottling || null,
|
||||
'disable-d3d11': flagsConfig.disableGpu || null,
|
||||
'disable-gpu': flagsConfig.disableGpu || null,
|
||||
'disable-gpu-compositing': flagsConfig.disableGpu || null,
|
||||
'disable-renderer-backgrounding': flagsConfig.customFlags.disableThrottling || null,
|
||||
};
|
||||
|
||||
for (const key in configFlags) {
|
||||
@ -72,7 +72,7 @@ export const setChromeFlags = () => {
|
||||
*/
|
||||
export const setSessionProperties = () => {
|
||||
logger.info(`chrome-flags: Settings session properties`);
|
||||
const { customFlags } = config.getGlobalConfigFields([ 'customFlags' ]) as IConfig;
|
||||
const { customFlags } = config.getConfigFields([ 'customFlags' ]) as IConfig;
|
||||
|
||||
if (session.defaultSession && customFlags && customFlags.authServerWhitelist && customFlags.authServerWhitelist !== '') {
|
||||
session.defaultSession.allowNTLMCredentialsForDomains(customFlags.authServerWhitelist);
|
||||
|
@ -6,33 +6,82 @@ import * as util from 'util';
|
||||
import { buildNumber } from '../../package.json';
|
||||
import { isDevEnv, isElectronQA, isLinux, isMac } from '../common/env';
|
||||
import { logger } from '../common/logger';
|
||||
import { pick } from '../common/utils';
|
||||
import { filterOutSelectedValues, pick } from '../common/utils';
|
||||
import { getDefaultUserConfig } from './config-utils';
|
||||
|
||||
const writeFile = util.promisify(fs.writeFile);
|
||||
|
||||
export interface IConfig {
|
||||
export enum CloudConfigDataTypes {
|
||||
NOT_SET = 'NOT_SET',
|
||||
ENABLED = 'ENABLED',
|
||||
DISABLED = 'DISABLED',
|
||||
}
|
||||
|
||||
export interface IGlobalConfig {
|
||||
url: string;
|
||||
minimizeOnClose: boolean;
|
||||
launchOnStartup: boolean;
|
||||
alwaysOnTop: boolean;
|
||||
bringToFront: boolean;
|
||||
whitelistUrl: string;
|
||||
isCustomTitleBar: boolean;
|
||||
memoryRefresh: boolean;
|
||||
devToolsEnabled: boolean;
|
||||
contextIsolation: boolean;
|
||||
}
|
||||
|
||||
export interface IConfig {
|
||||
minimizeOnClose: CloudConfigDataTypes;
|
||||
launchOnStartup: CloudConfigDataTypes;
|
||||
alwaysOnTop: CloudConfigDataTypes;
|
||||
bringToFront: CloudConfigDataTypes;
|
||||
whitelistUrl: string;
|
||||
isCustomTitleBar: CloudConfigDataTypes;
|
||||
memoryRefresh: CloudConfigDataTypes;
|
||||
memoryThreshold: string;
|
||||
disableGpu: boolean;
|
||||
devToolsEnabled: boolean;
|
||||
ctWhitelist: string[];
|
||||
podWhitelist: string[];
|
||||
configVersion: string;
|
||||
buildNumber: string;
|
||||
autoLaunchPath: string;
|
||||
notificationSettings: INotificationSetting;
|
||||
permissions: IPermission;
|
||||
customFlags: ICustomFlag;
|
||||
buildNumber?: string;
|
||||
configVersion?: string;
|
||||
notificationSettings: INotificationSetting;
|
||||
mainWinPos?: ICustomRectangle;
|
||||
locale?: string;
|
||||
}
|
||||
|
||||
export interface ICloudConfig {
|
||||
configVersion?: string;
|
||||
podLevelEntitlements: IPodLevelEntitlements;
|
||||
acpFeatureLevelEntitlements: IACPFeatureLevelEntitlements;
|
||||
pmpEntitlements: IPMPEntitlements;
|
||||
}
|
||||
|
||||
export interface IPodLevelEntitlements {
|
||||
minimizeOnClose: CloudConfigDataTypes;
|
||||
isCustomTitleBar: CloudConfigDataTypes;
|
||||
alwaysOnTop: CloudConfigDataTypes;
|
||||
memoryRefresh: CloudConfigDataTypes;
|
||||
bringToFront: CloudConfigDataTypes;
|
||||
disableThrottling: CloudConfigDataTypes;
|
||||
launchOnStartup: CloudConfigDataTypes;
|
||||
memoryThreshold: string;
|
||||
ctWhitelist: string;
|
||||
podWhitelist: string;
|
||||
authNegotiateDelegateWhitelist: string;
|
||||
whitelistUrl: string;
|
||||
authServerWhitelist: string;
|
||||
autoLaunchPath: string;
|
||||
}
|
||||
|
||||
export interface IACPFeatureLevelEntitlements {
|
||||
devToolsEnabled: boolean;
|
||||
permissions: IPermission;
|
||||
}
|
||||
|
||||
export interface IPMPEntitlements {
|
||||
minimizeOnClose: CloudConfigDataTypes;
|
||||
bringToFront: CloudConfigDataTypes;
|
||||
memoryRefresh: CloudConfigDataTypes;
|
||||
refreshAppThreshold: CloudConfigDataTypes;
|
||||
disableThrottling: CloudConfigDataTypes;
|
||||
}
|
||||
|
||||
export interface IPermission {
|
||||
media: boolean;
|
||||
geolocation: boolean;
|
||||
@ -46,7 +95,6 @@ export interface IPermission {
|
||||
export interface ICustomFlag {
|
||||
authServerWhitelist: string;
|
||||
authNegotiateDelegateWhitelist: string;
|
||||
disableGpu: boolean;
|
||||
disableThrottling: boolean;
|
||||
}
|
||||
|
||||
@ -63,15 +111,19 @@ export interface ICustomRectangle extends Partial<Electron.Rectangle> {
|
||||
class Config {
|
||||
private userConfig: IConfig | {};
|
||||
private globalConfig: IConfig | {};
|
||||
private cloudConfig: ICloudConfig | {};
|
||||
private filteredCloudConfig: ICloudConfig | {};
|
||||
private isFirstTime: boolean = true;
|
||||
private readonly configFileName: string;
|
||||
private readonly userConfigPath: string;
|
||||
private readonly appPath: string;
|
||||
private readonly globalConfigPath: string;
|
||||
private readonly cloudConfigPath: string;
|
||||
|
||||
constructor() {
|
||||
this.configFileName = 'Symphony.config';
|
||||
this.userConfigPath = path.join(app.getPath('userData'), this.configFileName);
|
||||
this.cloudConfigPath = path.join(app.getPath('userData'), 'cloudConfig.config');
|
||||
this.appPath = isDevEnv ? app.getAppPath() : path.dirname(app.getPath('exe'));
|
||||
this.globalConfigPath = isDevEnv
|
||||
? path.join(this.appPath, path.join('config', this.configFileName))
|
||||
@ -83,8 +135,11 @@ class Config {
|
||||
|
||||
this.globalConfig = {};
|
||||
this.userConfig = {};
|
||||
this.cloudConfig = {};
|
||||
this.filteredCloudConfig = {};
|
||||
this.readUserConfig();
|
||||
this.readGlobalConfig();
|
||||
this.readCloudConfig();
|
||||
|
||||
this.checkFirstTimeLaunch();
|
||||
}
|
||||
@ -96,8 +151,8 @@ class Config {
|
||||
* @param fields
|
||||
*/
|
||||
public getConfigFields(fields: string[]): IConfig {
|
||||
logger.info(`config-handler: Trying to get config values for the fields`, fields);
|
||||
return { ...this.getGlobalConfigFields(fields), ...this.getUserConfigFields(fields) } as IConfig;
|
||||
logger.info(`config-handler: Trying to get cloud config values for the fields`, fields);
|
||||
return { ...this.getGlobalConfigFields(fields), ...this.getUserConfigFields(fields), ...this.getFilteredCloudConfigFields(fields) } as IConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,9 +170,28 @@ class Config {
|
||||
*
|
||||
* @param fields {Array}
|
||||
*/
|
||||
public getGlobalConfigFields(fields: string[]): IConfig {
|
||||
public getGlobalConfigFields(fields: string[]): IGlobalConfig {
|
||||
logger.info(`config-handler: Trying to get global config values for the fields`, fields);
|
||||
return pick(this.globalConfig, fields) as IConfig;
|
||||
return pick(this.globalConfig, fields) as IGlobalConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns filtered & prioritised fields from cloud config file
|
||||
*
|
||||
* @param fields {Array}
|
||||
*/
|
||||
public getFilteredCloudConfigFields(fields: string[]): IConfig | {} {
|
||||
return pick(this.filteredCloudConfig, fields) as IConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual cloud config with priority
|
||||
* @param fields
|
||||
*/
|
||||
public getCloudConfigFields(fields: string[]): IConfig {
|
||||
const { acpFeatureLevelEntitlements, podLevelEntitlements, pmpEntitlements } = this.cloudConfig as ICloudConfig;
|
||||
const cloudConfig = { ...acpFeatureLevelEntitlements, ...podLevelEntitlements, ...pmpEntitlements };
|
||||
return pick(cloudConfig, fields) as IConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,6 +211,25 @@ class Config {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* updates new data to the cloud config
|
||||
*
|
||||
* @param data {IConfig}
|
||||
*/
|
||||
public async updateCloudConfig(data: Partial<ICloudConfig>): Promise<void> {
|
||||
logger.info(`config-handler: Updating the cloud config data from SFE: `, data);
|
||||
this.cloudConfig = { ...this.cloudConfig, ...data };
|
||||
// recalculate cloud config when we have data from SFE
|
||||
this.filterCloudConfig();
|
||||
logger.info(`config-handler: prioritized and filtered cloud config: `, this.filteredCloudConfig);
|
||||
try {
|
||||
await writeFile(this.cloudConfigPath, JSON.stringify(this.cloudConfig), { encoding: 'utf8' });
|
||||
logger.info(`config-handler: writting cloud config values to file`);
|
||||
} catch (error) {
|
||||
logger.error(`config-handler: failed to update cloud config file with ${data}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the app is launched for the first time
|
||||
* otherwise false
|
||||
@ -157,7 +250,6 @@ class Config {
|
||||
minimizeOnClose,
|
||||
launchOnStartup,
|
||||
alwaysOnTop,
|
||||
url,
|
||||
memoryRefresh,
|
||||
bringToFront,
|
||||
isCustomTitleBar,
|
||||
@ -169,6 +261,21 @@ class Config {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* filters out the cloud config
|
||||
*/
|
||||
private filterCloudConfig(): void {
|
||||
const { acpFeatureLevelEntitlements, podLevelEntitlements, pmpEntitlements } = this.cloudConfig as ICloudConfig;
|
||||
|
||||
// Filter out some values
|
||||
const filteredACP = filterOutSelectedValues(acpFeatureLevelEntitlements, [ true, 'NOT_SET' ]);
|
||||
const filteredPod = filterOutSelectedValues(podLevelEntitlements, [ true, 'NOT_SET' ]);
|
||||
const filteredPMP = filterOutSelectedValues(pmpEntitlements, [ true, 'NOT_SET' ]);
|
||||
|
||||
// priority is PMP > ACP > SDA
|
||||
this.filteredCloudConfig = { ...filteredACP, ...filteredPod, ...filteredPMP };
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the config data string
|
||||
*
|
||||
@ -201,7 +308,7 @@ class Config {
|
||||
// Need to wait until app ready event to access user data
|
||||
await app.whenReady();
|
||||
logger.info(`config-handler: user config doesn't exist! will create new one and update config`);
|
||||
await this.updateUserConfig({ configVersion: app.getVersion().toString(), buildNumber } as IConfig);
|
||||
await this.updateUserConfig({ configVersion: app.getVersion().toString(), buildNumber, ...getDefaultUserConfig() } as IConfig);
|
||||
}
|
||||
this.userConfig = this.parseConfigData(fs.readFileSync(this.userConfigPath, 'utf8'));
|
||||
logger.info(`config-handler: User configuration: `, this.userConfig);
|
||||
@ -215,6 +322,23 @@ class Config {
|
||||
logger.info(`config-handler: Global configuration: `, this.globalConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and stores the cloud config file
|
||||
*
|
||||
* If cloud config doesn't exits?
|
||||
* this creates a new one with { }
|
||||
*/
|
||||
private async readCloudConfig() {
|
||||
if (!fs.existsSync(this.cloudConfigPath)) {
|
||||
await app.whenReady();
|
||||
await this.updateCloudConfig({ configVersion: app.getVersion().toString() });
|
||||
}
|
||||
this.cloudConfig = this.parseConfigData(fs.readFileSync(this.cloudConfigPath, 'utf8'));
|
||||
// recalculate cloud config when we the application starts
|
||||
this.filterCloudConfig();
|
||||
logger.info(`config-handler: Cloud configuration: `, this.userConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the application is launched for the first time
|
||||
*/
|
||||
|
40
src/app/config-utils.ts
Normal file
40
src/app/config-utils.ts
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Returns the default user config data
|
||||
*/
|
||||
import { CloudConfigDataTypes, IConfig } from './config-handler';
|
||||
|
||||
export const getDefaultUserConfig = (): IConfig => {
|
||||
return {
|
||||
minimizeOnClose: CloudConfigDataTypes.ENABLED,
|
||||
launchOnStartup: CloudConfigDataTypes.ENABLED,
|
||||
alwaysOnTop: CloudConfigDataTypes.DISABLED,
|
||||
bringToFront: CloudConfigDataTypes.DISABLED,
|
||||
whitelistUrl: '*',
|
||||
isCustomTitleBar: CloudConfigDataTypes.ENABLED,
|
||||
memoryRefresh: CloudConfigDataTypes.ENABLED,
|
||||
memoryThreshold: '800',
|
||||
disableGpu: false,
|
||||
devToolsEnabled: true,
|
||||
ctWhitelist: [],
|
||||
podWhitelist: [],
|
||||
notificationSettings: {
|
||||
position: 'upper-right',
|
||||
display: '',
|
||||
},
|
||||
customFlags: {
|
||||
authServerWhitelist: '',
|
||||
authNegotiateDelegateWhitelist: '',
|
||||
disableThrottling: false,
|
||||
},
|
||||
permissions: {
|
||||
media: true,
|
||||
geolocation: true,
|
||||
notifications: true,
|
||||
midiSysex: true,
|
||||
pointerLock: true,
|
||||
fullscreen: true,
|
||||
openExternal: true,
|
||||
},
|
||||
autoLaunchPath: '',
|
||||
};
|
||||
};
|
@ -3,7 +3,7 @@ import { app } from 'electron';
|
||||
|
||||
import { i18n } from '../common/i18n';
|
||||
import { logger } from '../common/logger';
|
||||
import { config } from './config-handler';
|
||||
import { CloudConfigDataTypes, config } from './config-handler';
|
||||
import { ICustomBrowserWindow, windowHandler } from './window-handler';
|
||||
import { windowExists } from './window-utils';
|
||||
|
||||
@ -146,7 +146,7 @@ export const showNetworkConnectivityError = (browserWindow: Electron.BrowserWind
|
||||
*
|
||||
* @param isNativeStyle {boolean}
|
||||
*/
|
||||
export const titleBarChangeDialog = async (isNativeStyle: boolean) => {
|
||||
export const titleBarChangeDialog = async (isNativeStyle: CloudConfigDataTypes) => {
|
||||
const focusedWindow = electron.BrowserWindow.getFocusedWindow();
|
||||
if (!focusedWindow || !windowExists(focusedWindow)) {
|
||||
return;
|
||||
@ -161,7 +161,32 @@ export const titleBarChangeDialog = async (isNativeStyle: boolean) => {
|
||||
};
|
||||
const { response } = await electron.dialog.showMessageBox(focusedWindow, options);
|
||||
if (response === 0) {
|
||||
await config.updateUserConfig({ isCustomTitleBar: isNativeStyle });
|
||||
logger.error(`test`, isNativeStyle);
|
||||
await config.updateUserConfig({ isCustomTitleBar: isNativeStyle });
|
||||
app.relaunch();
|
||||
app.exit();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays a dialog to restart app upon changing gpu settings
|
||||
* @param disableGpu
|
||||
*/
|
||||
export const gpuRestartDialog = async (disableGpu: boolean) => {
|
||||
const focusedWindow = electron.BrowserWindow.getFocusedWindow();
|
||||
if (!focusedWindow || !windowExists(focusedWindow)) {
|
||||
return;
|
||||
}
|
||||
const options = {
|
||||
type: 'question',
|
||||
title: i18n.t('Relaunch Application')(),
|
||||
message: i18n.t('Would you like to restart and apply these new settings now?')(),
|
||||
buttons: [ i18n.t('Restart')(), i18n.t('Later')() ],
|
||||
cancelId: 1,
|
||||
};
|
||||
const { response } = await electron.dialog.showMessageBox(focusedWindow, options);
|
||||
await config.updateUserConfig({ disableGpu });
|
||||
if (response === 0) {
|
||||
app.relaunch();
|
||||
app.exit();
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { LocaleType } from '../common/i18n';
|
||||
import { logger } from '../common/logger';
|
||||
import { activityDetection } from './activity-detection';
|
||||
import { analytics } from './analytics-handler';
|
||||
import { config } from './config-handler';
|
||||
import { CloudConfigDataTypes, config, ICloudConfig } from './config-handler';
|
||||
import { memoryMonitor } from './memory-monitor';
|
||||
import { protocolHandler } from './protocol-handler';
|
||||
import { finalizeLogExports, registerLogRetriever } from './reports-handler';
|
||||
@ -19,6 +19,7 @@ import {
|
||||
setDataUrl,
|
||||
showBadgeCount,
|
||||
showPopupMenu,
|
||||
updateFeaturesForCloudConfig,
|
||||
updateLocale,
|
||||
windowExists,
|
||||
} from './window-utils';
|
||||
@ -27,7 +28,7 @@ import {
|
||||
* Handle API related ipc messages from renderers. Only messages from windows
|
||||
* we have created are allowed.
|
||||
*/
|
||||
ipcMain.on(apiName.symphonyApi, (event: Electron.IpcMainEvent, arg: IApiArgs) => {
|
||||
ipcMain.on(apiName.symphonyApi, async (event: Electron.IpcMainEvent, arg: IApiArgs) => {
|
||||
if (!isValidWindow(BrowserWindow.fromWebContents(event.sender))) {
|
||||
logger.error(`main-api-handler: invalid window try to perform action, ignoring action`, arg.cmd);
|
||||
return;
|
||||
@ -99,7 +100,7 @@ ipcMain.on(apiName.symphonyApi, (event: Electron.IpcMainEvent, arg: IApiArgs) =>
|
||||
// validates the user bring to front config and activates the wrapper
|
||||
if (typeof arg.reason === 'string' && arg.reason === 'notification') {
|
||||
const { bringToFront } = config.getConfigFields([ 'bringToFront' ]);
|
||||
if (bringToFront) {
|
||||
if (bringToFront === CloudConfigDataTypes.ENABLED) {
|
||||
activate(arg.windowName, false);
|
||||
}
|
||||
}
|
||||
@ -168,6 +169,14 @@ ipcMain.on(apiName.symphonyApi, (event: Electron.IpcMainEvent, arg: IApiArgs) =>
|
||||
case apiCmds.registerAnalyticsHandler:
|
||||
analytics.registerPreloadWindow(event.sender);
|
||||
break;
|
||||
case apiCmds.setCloudConfig:
|
||||
const { podLevelEntitlements, acpFeatureLevelEntitlements, pmpEntitlements, ...rest } = arg.cloudConfig as ICloudConfig;
|
||||
logger.info('main-api-handler: ignored other values from SFE', rest);
|
||||
await config.updateCloudConfig({ podLevelEntitlements, acpFeatureLevelEntitlements, pmpEntitlements });
|
||||
await updateFeaturesForCloudConfig();
|
||||
if (windowHandler.appMenu) {
|
||||
windowHandler.appMenu.buildMenu();
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ import * as electron from 'electron';
|
||||
|
||||
import { isMac } from '../common/env';
|
||||
import { logger } from '../common/logger';
|
||||
import { config } from './config-handler';
|
||||
import { CloudConfigDataTypes, config } from './config-handler';
|
||||
import { windowHandler } from './window-handler';
|
||||
import { windowExists } from './window-utils';
|
||||
|
||||
@ -11,9 +11,9 @@ class MemoryMonitor {
|
||||
private isInMeeting: boolean;
|
||||
private canReload: boolean;
|
||||
private lastReloadTime?: number;
|
||||
private memoryThreshold: number;
|
||||
|
||||
private readonly maxIdleTime: number;
|
||||
private readonly memoryThreshold: number;
|
||||
private readonly memoryRefreshThreshold: number;
|
||||
|
||||
constructor() {
|
||||
@ -46,13 +46,22 @@ class MemoryMonitor {
|
||||
logger.info(`memory-monitor: setting meeting status to ${isInMeeting}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the memory threshold
|
||||
*
|
||||
* @param memoryThreshold
|
||||
*/
|
||||
public setMemoryThreshold(memoryThreshold: number): void {
|
||||
this.memoryThreshold = memoryThreshold * 1024;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the predefined conditions and refreshes the client
|
||||
*/
|
||||
private validateMemory(): void {
|
||||
logger.info(`memory-monitor: validating memory refresh conditions`);
|
||||
const { memoryRefresh } = config.getConfigFields([ 'memoryRefresh' ]);
|
||||
if (!memoryRefresh) {
|
||||
if (memoryRefresh !== CloudConfigDataTypes.ENABLED) {
|
||||
logger.info(`memory-monitor: memory reload is disabled in the config, not going to refresh!`);
|
||||
return;
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ import { logger } from '../common/logger';
|
||||
import { config, IConfig } from './config-handler';
|
||||
|
||||
export const handlePerformanceSettings = () => {
|
||||
const { customFlags } = config.getGlobalConfigFields([ 'customFlags' ]) as IConfig;
|
||||
const { customFlags } = config.getCloudConfigFields([ 'customFlags' ]) as IConfig;
|
||||
|
||||
if (customFlags.disableThrottling) {
|
||||
if (customFlags && customFlags.disableThrottling) {
|
||||
logger.info(`perf-handler: Disabling power throttling!`);
|
||||
powerSaveBlocker.start('prevent-display-sleep');
|
||||
return;
|
||||
|
@ -47,7 +47,7 @@ class ScreenSnippet {
|
||||
if (mainWindow && windowExists(mainWindow) && isWindowsOS) {
|
||||
this.shouldUpdateAlwaysOnTop = mainWindow.isAlwaysOnTop();
|
||||
if (this.shouldUpdateAlwaysOnTop) {
|
||||
await updateAlwaysOnTop(false, false);
|
||||
await updateAlwaysOnTop(false, false, false);
|
||||
}
|
||||
}
|
||||
logger.info(`screen-snippet-handler: Starting screen capture!`);
|
||||
@ -179,7 +179,7 @@ class ScreenSnippet {
|
||||
*/
|
||||
private async verifyAndUpdateAlwaysOnTop(): Promise<void> {
|
||||
if (this.shouldUpdateAlwaysOnTop) {
|
||||
await updateAlwaysOnTop(true, false);
|
||||
await updateAlwaysOnTop(true, false, false);
|
||||
this.shouldUpdateAlwaysOnTop = false;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { app } from 'electron';
|
||||
import * as os from 'os';
|
||||
import * as si from 'systeminformation';
|
||||
import { logger } from '../common/logger';
|
||||
|
||||
export class AppStats {
|
||||
@ -16,6 +17,7 @@ export class AppStats {
|
||||
this.logAppMetrics();
|
||||
this.logConfigurationData();
|
||||
this.logAppEvents();
|
||||
this.logAllStats();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,6 +98,16 @@ export class AppStats {
|
||||
logger.info(`stats: Electron Version? ${process.versions.electron}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log all system statistics
|
||||
*/
|
||||
private async logAllStats() {
|
||||
try {
|
||||
logger.info(`All Data: ${JSON.stringify(await si.getAllData())}`);
|
||||
} catch (e) {
|
||||
logger.error(`Error gathering all data: ${e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const appStats = new AppStats();
|
||||
|
@ -2,7 +2,7 @@ import { net } from 'electron';
|
||||
import * as nodeURL from 'url';
|
||||
import { buildNumber, clientVersion, optionalDependencies, searchAPIVersion, sfeVersion, version } from '../../package.json';
|
||||
import { logger } from '../common/logger';
|
||||
import { config, IConfig } from './config-handler';
|
||||
import { config, IGlobalConfig } from './config-handler';
|
||||
|
||||
interface IVersionInfo {
|
||||
clientVersion: string;
|
||||
@ -69,7 +69,7 @@ class VersionHandler {
|
||||
this.mainUrl = mainUrl;
|
||||
}
|
||||
|
||||
const { url: podUrl }: IConfig = config.getGlobalConfigFields(['url']);
|
||||
const { url: podUrl }: IGlobalConfig = config.getGlobalConfigFields(['url']);
|
||||
|
||||
if (!this.mainUrl || !nodeURL.parse(this.mainUrl)) {
|
||||
this.mainUrl = podUrl;
|
||||
|
@ -6,7 +6,7 @@ import { i18n } from '../common/i18n';
|
||||
import { logger } from '../common/logger';
|
||||
import { throttle } from '../common/utils';
|
||||
import { notification } from '../renderer/notification';
|
||||
import { config } from './config-handler';
|
||||
import { CloudConfigDataTypes, config } from './config-handler';
|
||||
import { ICustomBrowserWindow, windowHandler } from './window-handler';
|
||||
import { showPopupMenu, windowExists } from './window-utils';
|
||||
|
||||
@ -146,14 +146,18 @@ export const activate = (windowName: string, shouldFocus: boolean = true): void
|
||||
*
|
||||
* @param shouldSetAlwaysOnTop {boolean} - Whether to enable always on top or not
|
||||
* @param shouldActivateMainWindow {boolean} - Whether to active main window
|
||||
* @param shouldUpdateUserConfig {boolean} - whether to update config file
|
||||
*/
|
||||
export const updateAlwaysOnTop = async (
|
||||
shouldSetAlwaysOnTop: boolean,
|
||||
shouldActivateMainWindow: boolean = true,
|
||||
shouldUpdateUserConfig: boolean = true,
|
||||
): Promise<void> => {
|
||||
logger.info(`window-actions: Should we set always on top? ${shouldSetAlwaysOnTop}!`);
|
||||
const browserWins: ICustomBrowserWindow[] = BrowserWindow.getAllWindows() as ICustomBrowserWindow[];
|
||||
await config.updateUserConfig({ alwaysOnTop: shouldSetAlwaysOnTop });
|
||||
if (shouldUpdateUserConfig) {
|
||||
await config.updateUserConfig({ alwaysOnTop: shouldSetAlwaysOnTop ? CloudConfigDataTypes.ENABLED : CloudConfigDataTypes.NOT_SET });
|
||||
}
|
||||
if (browserWins.length > 0) {
|
||||
browserWins
|
||||
.filter((browser) => typeof browser.notificationData !== 'object')
|
||||
@ -310,7 +314,7 @@ export const handlePermissionRequests = (webContents: Electron.webContents): voi
|
||||
}
|
||||
const { session } = webContents;
|
||||
|
||||
const { permissions } = config.getGlobalConfigFields([ 'permissions' ]);
|
||||
const { permissions } = config.getConfigFields([ 'permissions' ]);
|
||||
if (!permissions) {
|
||||
logger.error('permissions configuration is invalid, so, everything will be true by default!');
|
||||
return;
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { ChildProcess, ExecException, execFile } from 'child_process';
|
||||
import * as electron from 'electron';
|
||||
import { app, BrowserWindow, BrowserWindowConstructorOptions, crashReporter, globalShortcut, ipcMain } from 'electron';
|
||||
import { app, BrowserWindow, BrowserWindowConstructorOptions, crashReporter, DesktopCapturerSource, globalShortcut, ipcMain } from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { format, parse } from 'url';
|
||||
|
||||
import { ChildProcess, ExecException, execFile } from 'child_process';
|
||||
import { apiName, WindowTypes } from '../common/api-interface';
|
||||
import { isDevEnv, isMac, isWindowsOS } from '../common/env';
|
||||
import { i18n, LocaleType } from '../common/i18n';
|
||||
@ -13,10 +13,9 @@ import { getCommandLineArgs, getGuid } from '../common/utils';
|
||||
import { notification } from '../renderer/notification';
|
||||
import { AppMenu } from './app-menu';
|
||||
import { handleChildWindow } from './child-window-handler';
|
||||
import { config, IConfig } from './config-handler';
|
||||
import { CloudConfigDataTypes, config, IConfig, IGlobalConfig } from './config-handler';
|
||||
import { SpellChecker } from './spell-check-handler';
|
||||
import { checkIfBuildExpired } from './ttl-handler';
|
||||
import DesktopCapturerSource = Electron.DesktopCapturerSource;
|
||||
import { versionHandler } from './version-handler';
|
||||
import { handlePermissionRequests, monitorWindowActions } from './window-actions';
|
||||
import {
|
||||
@ -47,8 +46,6 @@ export interface ICustomBrowserWindow extends Electron.BrowserWindow {
|
||||
const DEFAULT_WIDTH: number = 900;
|
||||
const DEFAULT_HEIGHT: number = 900;
|
||||
|
||||
const {devToolsEnabled} = config.getGlobalConfigFields(['devToolsEnabled']);
|
||||
|
||||
export class WindowHandler {
|
||||
|
||||
/**
|
||||
@ -75,11 +72,12 @@ export class WindowHandler {
|
||||
public spellchecker: SpellChecker | undefined;
|
||||
public isCustomTitleBar: boolean;
|
||||
public isWebPageLoading: boolean = true;
|
||||
public screenShareIndicatorFrameUtil: string;
|
||||
|
||||
private readonly contextIsolation: boolean;
|
||||
private readonly backgroundThrottling: boolean;
|
||||
private readonly windowOpts: ICustomBrowserWindowConstructorOpts;
|
||||
private readonly globalConfig: IConfig;
|
||||
private readonly globalConfig: IGlobalConfig;
|
||||
private readonly config: IConfig;
|
||||
// Window reference
|
||||
private readonly windows: object;
|
||||
@ -92,22 +90,23 @@ export class WindowHandler {
|
||||
private screenSharingFrameWindow: Electron.BrowserWindow | null = null;
|
||||
private basicAuthWindow: Electron.BrowserWindow | null = null;
|
||||
private notificationSettingsWindow: Electron.BrowserWindow | null = null;
|
||||
private screenShareIndicatorFrameUtil: string;
|
||||
|
||||
constructor(opts?: Electron.BrowserViewConstructorOptions) {
|
||||
// Use these variables only on initial setup
|
||||
this.config = config.getConfigFields([ 'isCustomTitleBar', 'mainWinPos', 'minimizeOnClose', 'notificationSettings', 'alwaysOnTop', 'locale' ]);
|
||||
this.globalConfig = config.getGlobalConfigFields(['url', 'contextIsolation', 'customFlags']);
|
||||
const {url, contextIsolation, customFlags}: IConfig = this.globalConfig;
|
||||
this.config = config.getConfigFields([ 'isCustomTitleBar', 'mainWinPos', 'minimizeOnClose', 'notificationSettings', 'alwaysOnTop', 'locale', 'customFlags' ]);
|
||||
logger.info(`window-handler: main windows initialized with following config data`, this.config);
|
||||
this.globalConfig = config.getGlobalConfigFields([ 'url', 'contextIsolation' ]);
|
||||
const { url, contextIsolation }: IGlobalConfig = this.globalConfig;
|
||||
const { customFlags } = this.config;
|
||||
|
||||
this.windows = {};
|
||||
this.contextIsolation = contextIsolation || false;
|
||||
this.backgroundThrottling = !customFlags.disableThrottling;
|
||||
this.contextIsolation = contextIsolation || false;
|
||||
this.isCustomTitleBar = isWindowsOS && this.config.isCustomTitleBar;
|
||||
this.isCustomTitleBar = isWindowsOS && this.config.isCustomTitleBar === CloudConfigDataTypes.ENABLED;
|
||||
this.windowOpts = {
|
||||
...this.getWindowOpts({
|
||||
alwaysOnTop: this.config.alwaysOnTop || false,
|
||||
alwaysOnTop: this.config.alwaysOnTop === CloudConfigDataTypes.ENABLED || false,
|
||||
frame: !this.isCustomTitleBar,
|
||||
minHeight: 300,
|
||||
minWidth: 300,
|
||||
@ -185,7 +184,7 @@ export class WindowHandler {
|
||||
// Event needed to hide native menu bar on Windows 10 as we use custom menu bar
|
||||
this.mainWindow.webContents.once('did-start-loading', () => {
|
||||
logger.info(`window-handler: main window web contents started loading!`);
|
||||
if ((this.config.isCustomTitleBar && isWindowsOS) && this.mainWindow && windowExists(this.mainWindow)) {
|
||||
if ((this.config.isCustomTitleBar === CloudConfigDataTypes.ENABLED && isWindowsOS) && this.mainWindow && windowExists(this.mainWindow)) {
|
||||
this.mainWindow.setMenuBarVisibility(false);
|
||||
}
|
||||
// monitors network connection and
|
||||
@ -202,7 +201,7 @@ export class WindowHandler {
|
||||
if (urlFromCmd) {
|
||||
const commandLineUrl = urlFromCmd.substr(6);
|
||||
logger.info(`window-handler: trying to set url ${commandLineUrl} from command line.`);
|
||||
const { podWhitelist } = config.getGlobalConfigFields([ 'podWhitelist' ]);
|
||||
const { podWhitelist } = config.getConfigFields([ 'podWhitelist' ]);
|
||||
logger.info(`window-handler: checking pod whitelist.`);
|
||||
if (podWhitelist.length > 0) {
|
||||
logger.info(`window-handler: pod whitelist is not empty ${podWhitelist}`);
|
||||
@ -245,7 +244,7 @@ export class WindowHandler {
|
||||
isMainWindow: true,
|
||||
});
|
||||
this.appMenu = new AppMenu();
|
||||
const { permissions } = config.getGlobalConfigFields(['permissions']);
|
||||
const { permissions } = config.getConfigFields([ 'permissions' ]);
|
||||
this.mainWindow.webContents.send('is-screen-share-enabled', permissions.media);
|
||||
});
|
||||
|
||||
@ -304,8 +303,8 @@ export class WindowHandler {
|
||||
return this.destroyAllWindows();
|
||||
}
|
||||
|
||||
const {minimizeOnClose} = config.getConfigFields(['minimizeOnClose']);
|
||||
if (minimizeOnClose) {
|
||||
const { minimizeOnClose } = config.getConfigFields([ 'minimizeOnClose' ]);
|
||||
if (minimizeOnClose === CloudConfigDataTypes.ENABLED) {
|
||||
event.preventDefault();
|
||||
this.mainWindow.minimize();
|
||||
return;
|
||||
@ -516,8 +515,8 @@ export class WindowHandler {
|
||||
const selectedParentWindow = getWindowByName(windowName);
|
||||
|
||||
const opts: BrowserWindowConstructorOptions = this.getWindowOpts({
|
||||
width: 550,
|
||||
height: isWindowsOS ? 745 : 705,
|
||||
width: 440,
|
||||
height: 305,
|
||||
modal: true,
|
||||
alwaysOnTop: isMac,
|
||||
resizable: false,
|
||||
@ -716,7 +715,7 @@ export class WindowHandler {
|
||||
if (app.isReady()) {
|
||||
screens = electron.screen.getAllDisplays();
|
||||
}
|
||||
const {position, display} = config.getConfigFields(['notificationSettings']).notificationSettings;
|
||||
const { position, display } = config.getConfigFields([ 'notificationSettings' ]).notificationSettings;
|
||||
this.notificationSettingsWindow.webContents.send('notification-settings-data', {screens, position, display});
|
||||
}
|
||||
});
|
||||
@ -919,6 +918,28 @@ export class WindowHandler {
|
||||
delete this.windows[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given command via a child process
|
||||
*
|
||||
* @param util {string}
|
||||
* @param utilArgs {ReadonlyArray<string>}
|
||||
*/
|
||||
public execCmd(util: string, utilArgs: ReadonlyArray<string>): Promise<ChildProcess> {
|
||||
logger.info(`window handler: execCmd: util: ${util} utilArgs: ${utilArgs}`);
|
||||
return new Promise<ChildProcess>((resolve, reject) => {
|
||||
return execFile(util, utilArgs, (error: ExecException | null) => {
|
||||
if (error) {
|
||||
logger.info(`window handler: execCmd: error: ${error}`);
|
||||
}
|
||||
if (error && error.killed) {
|
||||
// processs was killed, just resolve with no data.
|
||||
return reject(error);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the about panel details for macOS
|
||||
*/
|
||||
@ -965,6 +986,7 @@ export class WindowHandler {
|
||||
if (!focusedWindow || !windowExists(focusedWindow)) {
|
||||
return;
|
||||
}
|
||||
const { devToolsEnabled } = config.getConfigFields([ 'devToolsEnabled' ]);
|
||||
if (devToolsEnabled) {
|
||||
focusedWindow.webContents.toggleDevTools();
|
||||
return;
|
||||
@ -1047,27 +1069,6 @@ export class WindowHandler {
|
||||
|
||||
return {...defaultWindowOpts, ...windowOpts};
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given command via a child process
|
||||
*
|
||||
* @param util {string}
|
||||
* @param utilArgs {ReadonlyArray<string>}
|
||||
*/
|
||||
private execCmd(util: string, utilArgs: ReadonlyArray<string>): Promise<ChildProcess> {
|
||||
logger.info(`window handler: execCmd: util: ${util} utilArgs: ${utilArgs}`);
|
||||
return new Promise<ChildProcess>((resolve, reject) => {
|
||||
return execFile(util, utilArgs, (error: ExecException | null) => {
|
||||
logger.info(`window handler: execCmd: error: ${error}`);
|
||||
if (error && error.killed) {
|
||||
// processs was killed, just resolve with no data.
|
||||
return reject(error);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const windowHandler = new WindowHandler();
|
||||
|
@ -12,8 +12,11 @@ import { i18n, LocaleType } from '../common/i18n';
|
||||
import { logger } from '../common/logger';
|
||||
import { getGuid } from '../common/utils';
|
||||
import { whitelistHandler } from '../common/whitelist-handler';
|
||||
import { config, ICustomRectangle } from './config-handler';
|
||||
import { autoLaunchInstance } from './auto-launch-controller';
|
||||
import { CloudConfigDataTypes, config, IConfig, ICustomRectangle } from './config-handler';
|
||||
import { memoryMonitor } from './memory-monitor';
|
||||
import { screenSnippet } from './screen-snippet-handler';
|
||||
import { updateAlwaysOnTop } from './window-actions';
|
||||
import { ICustomBrowserWindow, windowHandler } from './window-handler';
|
||||
|
||||
interface IStyles {
|
||||
@ -28,7 +31,8 @@ enum styleNames {
|
||||
}
|
||||
|
||||
const checkValidWindow = true;
|
||||
const { url: configUrl, ctWhitelist } = config.getGlobalConfigFields([ 'url', 'ctWhitelist' ]);
|
||||
const { url: configUrl } = config.getGlobalConfigFields([ 'url' ]);
|
||||
const { ctWhitelist } = config.getConfigFields([ 'ctWhitelist' ]);
|
||||
|
||||
// Network status check variables
|
||||
const networkStatusCheckInterval = 10 * 1000;
|
||||
@ -543,6 +547,9 @@ export const reloadWindow = (browserWindow: ICustomBrowserWindow) => {
|
||||
if (windowName === apiName.mainWindowName) {
|
||||
logger.info(`window-utils: reloading the main window`);
|
||||
browserWindow.reload();
|
||||
|
||||
windowHandler.execCmd(windowHandler.screenShareIndicatorFrameUtil, []);
|
||||
|
||||
return;
|
||||
}
|
||||
// Send an event to SFE that restarts the pop-out window
|
||||
@ -581,6 +588,36 @@ export const getWindowByName = (windowName: string): BrowserWindow | undefined =
|
||||
});
|
||||
};
|
||||
|
||||
export const updateFeaturesForCloudConfig = async (): Promise<void> => {
|
||||
const {
|
||||
alwaysOnTop: isAlwaysOnTop,
|
||||
launchOnStartup,
|
||||
memoryRefresh,
|
||||
memoryThreshold,
|
||||
} = config.getConfigFields([
|
||||
'launchOnStartup',
|
||||
'alwaysOnTop',
|
||||
'memoryRefresh',
|
||||
'memoryThreshold',
|
||||
]) as IConfig;
|
||||
|
||||
const mainWindow = windowHandler.getMainWindow();
|
||||
|
||||
// Update Always on top feature
|
||||
await updateAlwaysOnTop(isAlwaysOnTop === CloudConfigDataTypes.ENABLED, false, false);
|
||||
|
||||
// Update launch on start up
|
||||
launchOnStartup === CloudConfigDataTypes.ENABLED ? autoLaunchInstance.enableAutoLaunch() : autoLaunchInstance.disableAutoLaunch();
|
||||
|
||||
if (mainWindow && windowExists(mainWindow)) {
|
||||
if (memoryRefresh) {
|
||||
logger.info(`window-utils: updating the memory threshold`, memoryThreshold);
|
||||
memoryMonitor.setMemoryThreshold(parseInt(memoryThreshold, 10));
|
||||
mainWindow.webContents.send('initialize-memory-refresh');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Monitors network requests and displays red banner on failure
|
||||
*/
|
||||
|
@ -35,6 +35,7 @@ export enum apiCmds {
|
||||
swiftSearch = 'swift-search',
|
||||
getConfigUrl = 'get-config-url',
|
||||
registerRestartFloater = 'register-restart-floater',
|
||||
setCloudConfig = 'set-cloud-config',
|
||||
}
|
||||
|
||||
export enum apiName {
|
||||
@ -67,6 +68,7 @@ export interface IApiArgs {
|
||||
type: string;
|
||||
logName: string;
|
||||
logs: ILogs;
|
||||
cloudConfig: object;
|
||||
}
|
||||
|
||||
export type WindowTypes = 'screen-picker' | 'screen-sharing-indicator' | 'notification-settings';
|
||||
|
@ -153,6 +153,25 @@ export const pick = (object: object, fields: string[]) => {
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Filters out truthy values
|
||||
*
|
||||
* @param data {Object} { test: true, test1: false, test2: 'NOT_SET' }
|
||||
* @param values {Array} [ true, "NOT_SET" ]
|
||||
* @return {Object} { test1: false }
|
||||
*/
|
||||
export const filterOutSelectedValues = (data: object, values): object => {
|
||||
if (!data) {
|
||||
return {};
|
||||
}
|
||||
return Object.keys(data).reduce((obj, key) => {
|
||||
if (values.indexOf(data[key]) <= -1) {
|
||||
obj[key] = data[key];
|
||||
}
|
||||
return obj;
|
||||
}, {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Limits your function to be called at most every milliseconds
|
||||
*
|
||||
|
@ -18,7 +18,7 @@ export class WhitelistHandler {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public isWhitelisted(url: string): boolean {
|
||||
const { whitelistUrl } = config.getGlobalConfigFields([ 'whitelistUrl' ]);
|
||||
const { whitelistUrl } = config.getConfigFields([ 'whitelistUrl' ]);
|
||||
|
||||
return this.checkWhitelist(url, whitelistUrl);
|
||||
}
|
||||
|
@ -55,6 +55,7 @@
|
||||
"Dev Tools disabled": "Dev Tools disabled",
|
||||
"Dev Tools has been disabled! Please contact your system administrator to enable it!": "Dev Tools has been disabled! Please contact your system administrator to enable it!",
|
||||
"Disable Hamburger menu": "Disable Hamburger menu",
|
||||
"Disable GPU": "Disable GPU",
|
||||
"DownloadManager": {
|
||||
"downloaded": "downloaded",
|
||||
"File not Found": "File not Found",
|
||||
@ -65,6 +66,7 @@
|
||||
},
|
||||
"Edit": "Edit",
|
||||
"Enable Hamburger menu": "Enable Hamburger menu",
|
||||
"Enable GPU": "Enable GPU",
|
||||
"Error loading configuration": "Error loading configuration",
|
||||
"Error loading URL": "Error loading URL",
|
||||
"Error loading window": "Error loading window",
|
||||
@ -76,6 +78,7 @@
|
||||
"Hide Others": "Hide Others",
|
||||
"Hide Symphony": "Hide Symphony",
|
||||
"Ignore": "Ignore",
|
||||
"Later": "Later",
|
||||
"Learn More": "Learn More",
|
||||
"Loading Error": "Loading Error",
|
||||
"Minimize": "Minimize",
|
||||
@ -126,6 +129,7 @@
|
||||
"Redo": "Redo",
|
||||
"Refresh app when idle": "Refresh app when idle",
|
||||
"Relaunch": "Relaunch",
|
||||
"Restart": "Restart",
|
||||
"Relaunch Application": "Relaunch Application",
|
||||
"Reload": "Reload",
|
||||
"Renderer Process Crashed": "Renderer Process Crashed",
|
||||
@ -192,6 +196,7 @@
|
||||
"Updating Title bar style requires Symphony to relaunch.": "Updating Title bar style requires Symphony to relaunch.",
|
||||
"View": "View",
|
||||
"Window": "Window",
|
||||
"Would you like to restart and apply these new settings now?": "Would you like to restart and apply these new settings now?",
|
||||
"Your administrator has disabled": "Your administrator has disabled",
|
||||
"Zoom": "Zoom",
|
||||
"Zoom In": "Zoom In",
|
||||
|
@ -55,6 +55,7 @@
|
||||
"Dev Tools disabled": "Dev Tools disabled",
|
||||
"Dev Tools has been disabled! Please contact your system administrator to enable it!": "Dev Tools has been disabled! Please contact your system administrator to enable it!",
|
||||
"Disable Hamburger menu": "Disable Hamburger menu",
|
||||
"Disable GPU": "Disable GPU",
|
||||
"DownloadManager": {
|
||||
"downloaded": "downloaded",
|
||||
"File not Found": "File not Found",
|
||||
@ -65,6 +66,7 @@
|
||||
},
|
||||
"Edit": "Edit",
|
||||
"Enable Hamburger menu": "Enable Hamburger menu",
|
||||
"Enable GPU": "Enable GPU",
|
||||
"Error loading configuration": "Error loading configuration",
|
||||
"Error loading URL": "Error loading URL",
|
||||
"Error loading window": "Error loading window",
|
||||
@ -76,6 +78,7 @@
|
||||
"Hide Others": "Hide Others",
|
||||
"Hide Symphony": "Hide Symphony",
|
||||
"Ignore": "Ignore",
|
||||
"Later": "Later",
|
||||
"Learn More": "Learn More",
|
||||
"Loading Error": "Loading Error",
|
||||
"Minimize": "Minimize",
|
||||
@ -126,6 +129,7 @@
|
||||
"Redo": "Redo",
|
||||
"Refresh app when idle": "Refresh app when idle",
|
||||
"Relaunch": "Relaunch",
|
||||
"Restart": "Restart",
|
||||
"Relaunch Application": "Relaunch Application",
|
||||
"Reload": "Reload",
|
||||
"Renderer Process Crashed": "Renderer Process Crashed",
|
||||
@ -192,6 +196,7 @@
|
||||
"Updating Title bar style requires Symphony to relaunch.": "Updating Title bar style requires Symphony to relaunch.",
|
||||
"View": "View",
|
||||
"Window": "Window",
|
||||
"Would you like to restart and apply these new settings now?": "Would you like to restart and apply these new settings now?",
|
||||
"Your administrator has disabled": "Your administrator has disabled",
|
||||
"Zoom": "Zoom",
|
||||
"Zoom In": "Zoom In",
|
||||
|
@ -31,6 +31,7 @@
|
||||
"Build expired": "Construit expiré",
|
||||
"Cancel": "Annuler",
|
||||
"Certificate Error": "Erreur de certificat",
|
||||
"Changing GPU settings requires Symphony to relaunch.": "La modification des paramètres du GPU nécessite la relance de Symphony.",
|
||||
"Clear cache and Reload": "Vider le cache et rafraîchir Symphony",
|
||||
"Close": "Fermer",
|
||||
"ContextMenu": {
|
||||
@ -55,6 +56,7 @@
|
||||
"Dev Tools disabled": "Outils de développement désactivés",
|
||||
"Dev Tools has been disabled! Please contact your system administrator to enable it!": "Dev Tools a été désactivé ! Veuillez contacter votre administrateur système pour l’activer !",
|
||||
"Disable Hamburger menu": "Désactiver le menu Hamburger",
|
||||
"Disable GPU": "Désactiver le GPU",
|
||||
"DownloadManager": {
|
||||
"downloaded": "téléchargé",
|
||||
"File not Found": "Fichier non trouvé",
|
||||
@ -65,6 +67,7 @@
|
||||
},
|
||||
"Edit": "Modifier",
|
||||
"Enable Hamburger menu": "Activer le menu Hamburger",
|
||||
"Enable GPU": "Activer le GPU",
|
||||
"Error loading configuration": "Erreur de chargement de la configuration",
|
||||
"Error loading URL": "Erreur de chargement de l'URL",
|
||||
"Error loading window": "Erreur de chargement de la fenêtre",
|
||||
@ -76,6 +79,7 @@
|
||||
"Hide Others": "Cacher les autres applications",
|
||||
"Hide Symphony": "Cacher Symphony",
|
||||
"Ignore": "Ignorer",
|
||||
"Later": "Plus tard",
|
||||
"Learn More": "En savoir plus sur Symphony",
|
||||
"Loading Error": "Erreur lors du chargement",
|
||||
"Minimize": "Minimiser",
|
||||
@ -126,6 +130,7 @@
|
||||
"Redo": "Répéter la dernière opération",
|
||||
"Refresh app when idle": "Rafraîchir Symphony pendant les périodes d'inactivité",
|
||||
"Relaunch": "Redémarrer",
|
||||
"Restart": "Redémarrer",
|
||||
"Relaunch Application": "Redémarrer l'application",
|
||||
"Reload": "Recharger",
|
||||
"Renderer Process Crashed": "Processus de rendu a eu un crash",
|
||||
@ -192,6 +197,7 @@
|
||||
"Updating Title bar style requires Symphony to relaunch.": "La mise à jour du style de la barre de titre nécessite le redémarrage de Symphony.",
|
||||
"View": "Visualiser",
|
||||
"Window": "Fenêtre",
|
||||
"Would you like to restart and apply these new settings now?": "Would you like to restart and apply these new settings now?",
|
||||
"Your administrator has disabled": "Votre administrateur a désactivé",
|
||||
"Zoom": "Zoom",
|
||||
"Zoom In": "Zoom Avant",
|
||||
|
@ -55,6 +55,7 @@
|
||||
"Dev Tools disabled": "Outils de développement désactivés",
|
||||
"Dev Tools has been disabled! Please contact your system administrator to enable it!": "Dev Tools a été désactivé ! Veuillez contacter votre administrateur système pour l’activer !",
|
||||
"Disable Hamburger menu": "Désactiver le menu Hamburger",
|
||||
"Disable GPU": "Désactiver le GPU",
|
||||
"DownloadManager": {
|
||||
"downloaded": "téléchargé",
|
||||
"File not Found": "Fichier non trouvé",
|
||||
@ -65,6 +66,7 @@
|
||||
},
|
||||
"Edit": "Modifier",
|
||||
"Enable Hamburger menu": "Activer le menu Hamburger",
|
||||
"Enable GPU": "Activer le GPU",
|
||||
"Error loading configuration": "Erreur de chargement de la configuration",
|
||||
"Error loading URL": "Erreur de chargement de l'URL",
|
||||
"Error loading window": "Erreur de chargement de la fenêtre",
|
||||
@ -76,6 +78,7 @@
|
||||
"Hide Others": "Cacher les autres applications",
|
||||
"Hide Symphony": "Cacher Symphony",
|
||||
"Ignore": "Ignorer",
|
||||
"Later": "Plus tard",
|
||||
"Learn More": "En savoir plus sur Symphony",
|
||||
"Loading Error": "Erreur lors du chargement",
|
||||
"Minimize": "Minimiser",
|
||||
@ -126,6 +129,7 @@
|
||||
"Redo": "Répéter la dernière opération",
|
||||
"Refresh app when idle": "Rafraîchir Symphony pendant les périodes d'inactivité",
|
||||
"Relaunch": "Redémarrer",
|
||||
"Restart": "Redémarrer",
|
||||
"Relaunch Application": "Redémarrer l'application",
|
||||
"Reload": "Recharger",
|
||||
"Renderer Process Crashed": "Processus de rendu a eu un crash",
|
||||
@ -192,6 +196,7 @@
|
||||
"Updating Title bar style requires Symphony to relaunch.": "La mise à jour du style de la barre de titre nécessite le redémarrage de Symphony.",
|
||||
"View": "Visualiser",
|
||||
"Window": "Fenêtre",
|
||||
"Would you like to restart and apply these new settings now?": "Would you like to restart and apply these new settings now?",
|
||||
"Your administrator has disabled": "Votre administrateur a désactivé",
|
||||
"Zoom": "Zoom",
|
||||
"Zoom In": "Zoom Avant",
|
||||
|
@ -55,6 +55,7 @@
|
||||
"Dev Tools disabled": "開発ツールが無効",
|
||||
"Dev Tools has been disabled! Please contact your system administrator to enable it!": "開発ツールが無効になっています。システム管理者に連絡して、有効にしてください。",
|
||||
"Disable Hamburger menu": "ハンバーガーメニューを無効にする",
|
||||
"Disable GPU": "GPUを無効にする",
|
||||
"DownloadManager": {
|
||||
"downloaded": "ダウンロード済み",
|
||||
"File not Found": "ファイルが見つかりません",
|
||||
@ -65,6 +66,7 @@
|
||||
},
|
||||
"Edit": "編集",
|
||||
"Enable Hamburger menu": "ハンバーガーメニューを有効にする",
|
||||
"Enable GPU": "GPUを有効にする",
|
||||
"Error loading configuration": "構成の読み込みエラー",
|
||||
"Error loading URL": "URLの読み込みエラー",
|
||||
"Error loading window": "ウィンドウを読み込みエラー",
|
||||
@ -76,6 +78,7 @@
|
||||
"Hide Others": "他を隠す",
|
||||
"Hide Symphony": "Symphonyを隠す",
|
||||
"Ignore": "無視",
|
||||
"Later": "後で",
|
||||
"Learn More": "詳細",
|
||||
"Loading Error": "読み込みエラー",
|
||||
"Minimize": "最小化",
|
||||
@ -126,6 +129,7 @@
|
||||
"Redo": "やり直し",
|
||||
"Refresh app when idle": "アイドル時にアプリを再表示",
|
||||
"Relaunch": "「リスタート」",
|
||||
"Restart": "再起動する",
|
||||
"Relaunch Application": "アプリケーションの再起動",
|
||||
"Reload": "再読み込み",
|
||||
"Renderer Process Crashed": "レンダラープロセスがクラッシュしました",
|
||||
@ -192,6 +196,7 @@
|
||||
"Updating Title bar style requires Symphony to relaunch.": "タイトルバーのスタイルを更新するには、Symphonyが再起動する必要があります。",
|
||||
"View": "ビュー",
|
||||
"Window": "ウインドウ",
|
||||
"Would you like to restart and apply these new settings now?": "今すぐ再起動して、新しい設定を適用しますか?",
|
||||
"Your administrator has disabled": "管理者によて無効にされています",
|
||||
"Zoom": "ズーム",
|
||||
"Zoom In": "ズームイン",
|
||||
|
@ -55,6 +55,7 @@
|
||||
"Dev Tools disabled": "開発ツールが無効",
|
||||
"Dev Tools has been disabled! Please contact your system administrator to enable it!": "開発ツールが無効になっています。システム管理者に連絡して、有効にしてください。",
|
||||
"Disable Hamburger menu": "ハンバーガーメニューを無効にする",
|
||||
"Disable GPU": "GPUを無効にする",
|
||||
"DownloadManager": {
|
||||
"downloaded": "ダウンロード済み",
|
||||
"File not Found": "ファイルが見つかりません",
|
||||
@ -65,6 +66,7 @@
|
||||
},
|
||||
"Edit": "編集",
|
||||
"Enable Hamburger menu": "ハンバーガーメニューを有効にする",
|
||||
"Enable GPU": "GPUを有効にする",
|
||||
"Error loading configuration": "構成の読み込みエラー",
|
||||
"Error loading URL": "URLの読み込みエラー",
|
||||
"Error loading window": "ウィンドウを読み込みエラー",
|
||||
@ -76,6 +78,7 @@
|
||||
"Hide Others": "他を隠す",
|
||||
"Hide Symphony": "Symphonyを隠す",
|
||||
"Ignore": "無視",
|
||||
"Later": "後で",
|
||||
"Learn More": "詳細",
|
||||
"Loading Error": "読み込みエラー",
|
||||
"Minimize": "最小化",
|
||||
@ -126,6 +129,7 @@
|
||||
"Redo": "やり直し",
|
||||
"Refresh app when idle": "アイドル時にアプリを再表示",
|
||||
"Relaunch": "「リスタート」",
|
||||
"Restart": "再起動する",
|
||||
"Relaunch Application": "アプリケーションの再起動",
|
||||
"Reload": "再読み込み",
|
||||
"Renderer Process Crashed": "レンダラープロセスがクラッシュしました",
|
||||
@ -192,6 +196,7 @@
|
||||
"Updating Title bar style requires Symphony to relaunch.": "タイトルバーのスタイルを更新するには、Symphonyが再起動する必要があります。",
|
||||
"View": "ビュー",
|
||||
"Window": "ウインドウ",
|
||||
"Would you like to restart and apply these new settings now?": "今すぐ再起動して、新しい設定を適用しますか?",
|
||||
"Your administrator has disabled": "管理者によて無効にされています",
|
||||
"Zoom": "ズーム",
|
||||
"Zoom In": "ズームイン",
|
||||
|
@ -166,6 +166,9 @@ export class AppBridge {
|
||||
case apiCmds.registerRestartFloater:
|
||||
ssf.registerRestartFloater(this.callbackHandlers.restartFloater);
|
||||
break;
|
||||
case apiCmds.setCloudConfig:
|
||||
ssf.setCloudConfig(data as object);
|
||||
break;
|
||||
case apiCmds.swiftSearch:
|
||||
if (ssInstance) {
|
||||
ssInstance.handleMessageEvents(data);
|
||||
|
@ -66,10 +66,6 @@ export default class AboutApp extends React.Component<{}, IState> {
|
||||
public render(): JSX.Element {
|
||||
const { clientVersion, buildNumber, sfeVersion,
|
||||
sdaVersion, sdaBuildNumber,
|
||||
electronVersion, chromeVersion, v8Version,
|
||||
nodeVersion, openSslVersion, zlibVersion,
|
||||
uvVersion, aresVersion, httpParserVersion,
|
||||
swiftSearchVersion, swiftSearchSupportedVersion,
|
||||
} = this.state;
|
||||
|
||||
const appName = remote.app.getName() || 'Symphony';
|
||||
@ -91,39 +87,15 @@ export default class AboutApp extends React.Component<{}, IState> {
|
||||
<p className='AboutApp-copyrightText'>{copyright}</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div className='AboutApp-main-container'>
|
||||
<section>
|
||||
<h4>Symphony</h4>
|
||||
<ul className='AboutApp-symphony-section'>
|
||||
<li><b>SBE:</b> {podVersion}</li>
|
||||
<li><b>SFE:</b> {sfeVersion}</li>
|
||||
<li><b>SDA:</b> {sdaVersionBuild}</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<h4>Electron</h4>
|
||||
<ul className='AboutApp-electron-section'>
|
||||
<li><b>Electron:</b> {electronVersion}</li>
|
||||
<li><b>Chrome:</b> {chromeVersion}</li>
|
||||
<li><b>V8:</b> {v8Version}</li>
|
||||
<li><b>Node:</b> {nodeVersion}</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section>
|
||||
<h4>{i18n.t('Others', ABOUT_SYMPHONY_NAMESPACE)()}</h4>
|
||||
<ul className='AboutApp-others-section'>
|
||||
<li><b>openssl:</b> {openSslVersion}</li>
|
||||
<li><b>zlib:</b> {zlibVersion}</li>
|
||||
<li><b>uv:</b> {uvVersion}</li>
|
||||
<li><b>ares:</b> {aresVersion}</li>
|
||||
<li><b>http_parser:</b> {httpParserVersion}</li>
|
||||
<li><b>{i18n.t('Swift Search', ABOUT_SYMPHONY_NAMESPACE)()}:</b> {swiftSearchVersion}</li>
|
||||
<li><b>{i18n.t('Swift Search API', ABOUT_SYMPHONY_NAMESPACE)()}:</b> {swiftSearchSupportedVersion}</li>
|
||||
<li><b>SFE:</b> {sfeVersion}</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<button
|
||||
className='AboutApp-copy-button'
|
||||
|
@ -77,7 +77,7 @@ const monitorMemory = (time) => {
|
||||
};
|
||||
|
||||
// When the window is completely loaded
|
||||
ipcRenderer.on('page-load', (_event, { locale, resources, enableCustomTitleBar, isMainWindow }) => {
|
||||
ipcRenderer.on('page-load', (_event, { locale, resources, enableCustomTitleBar }) => {
|
||||
|
||||
i18n.setResource(locale, resources);
|
||||
|
||||
@ -113,10 +113,6 @@ ipcRenderer.on('page-load', (_event, { locale, resources, enableCustomTitleBar,
|
||||
// initialize red banner
|
||||
banner.initBanner();
|
||||
banner.showBanner(false, 'error');
|
||||
|
||||
if (isMainWindow) {
|
||||
monitorMemory(getRandomTime(minMemoryFetchInterval, maxMemoryFetchInterval));
|
||||
}
|
||||
});
|
||||
|
||||
// When the window fails to load
|
||||
@ -140,3 +136,7 @@ ipcRenderer.on('show-banner', (_event, { show, bannerType, url }) => {
|
||||
}
|
||||
banner.showBanner(show, bannerType, url);
|
||||
});
|
||||
|
||||
ipcRenderer.on('initialize-memory-refresh', () => {
|
||||
monitorMemory(getRandomTime(minMemoryFetchInterval, maxMemoryFetchInterval));
|
||||
});
|
||||
|
@ -93,6 +93,13 @@ const throttledSetIsInMeetingStatus = throttle((isInMeeting) => {
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
const throttledSetCloudConfig = throttle((data) => {
|
||||
ipcRenderer.send(apiName.symphonyApi, {
|
||||
cmd: apiCmds.setCloudConfig,
|
||||
cloudConfig: data,
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
let cryptoLib: ICryptoLib | null;
|
||||
try {
|
||||
cryptoLib = remote.require('../app/crypto-handler.js').cryptoLibrary;
|
||||
@ -470,6 +477,15 @@ export class SSFApi {
|
||||
local.restartFloater = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows JS to set the PMP & ACP cloud config
|
||||
*
|
||||
* @param data {ICloudConfig}
|
||||
*/
|
||||
public setCloudConfig(data: {}): void {
|
||||
throttledSetCloudConfig(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,27 +19,15 @@ body {
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.AboutApp-others-section {
|
||||
padding-left: 55px;
|
||||
}
|
||||
|
||||
.AboutApp-symphony-section {
|
||||
padding-left: 119px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.AboutApp:lang(fr-FR) {
|
||||
|
||||
.AboutApp-symphony-section {
|
||||
padding-left: 130px;
|
||||
}
|
||||
|
||||
.AboutApp-electron-section {
|
||||
padding-left: 103px;
|
||||
}
|
||||
|
||||
.AboutApp-others-section {
|
||||
padding-left: 0;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,11 +52,11 @@ body {
|
||||
}
|
||||
|
||||
&-main-container {
|
||||
padding: 0 20px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
&-name {
|
||||
font-size: 1.6em;
|
||||
font-size: 1.8em;
|
||||
padding-left: @text-padding;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
@ -86,15 +74,7 @@ body {
|
||||
}
|
||||
|
||||
&-symphony-section {
|
||||
padding-left: 115px;
|
||||
}
|
||||
|
||||
&-electron-section {
|
||||
padding-left: 88px;
|
||||
}
|
||||
|
||||
&-others-section {
|
||||
padding-left: 27px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
hr {
|
||||
@ -117,13 +97,13 @@ body {
|
||||
li {
|
||||
display: table-row;
|
||||
text-align: left;
|
||||
line-height: 26px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
b {
|
||||
display: table-cell;
|
||||
padding-right: 1em;
|
||||
text-align: right;
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user