diff --git a/electron-builder.yml b/electron-builder.yml
deleted file mode 100644
index 9669e2d8..00000000
--- a/electron-builder.yml
+++ /dev/null
@@ -1,52 +0,0 @@
-productName: "Symphony"
-appId: "com.symphony.electron-desktop"
-
-# Package electron code into a asar archive. Set to false to debug issues.
-asar: true
-
-# Unpack these files from asar to have them signed
-asarUnpack:
- - 'node_modules/@nornagon/cld/build/Release/cld.node'
- - 'node_modules/@nornagon/spellchecker/build/Release/spellchecker.node'
- - 'node_modules/keyboard-layout/build/Release/keyboard-layout-manager.node'
-
-# Don't package these files
-files:
- - '!coverage/*'
- - '!installer/*'
- - '!tests/*'
- - '!node_modules/@nornagon/cld/deps/cld${/*}'
- - '!node_modules/@nornagon/cld/build/deps${/*}'
- - '!node_modules/@nornagon/spellchecker/vendor${/*}'
-
-# Extra files to package
-extraFiles:
- - 'config/Symphony.config'
- - 'config/titleBarStyles.css'
- - 'dictionaries/**'
- - 'library/libsymphonysearch.dylib'
- - 'library/indexvalidator.exec'
- - 'library/cryptoLib.dylib'
- - 'library/dictionary'
- - 'library/lz4.exec'
-
-# Mac OS configuration
-mac:
- category: 'public.app-category.business'
- icon: 'images/icon.icns'
-
-# Windows configuration
-win:
- icon: 'images/icon.ico'
- target:
- - 'squirrel'
-
-# Linux configuration
-linux:
- category: 'Network;InstantMessaging;Chat'
- desktop:
- StartupWMClass: 'Symphony'
- target:
- - 'deb'
- - 'rpm'
- icon: 'images/linux'
diff --git a/gulpfile.js b/gulpfile.js
index 43bc0929..39e09422 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -2,11 +2,11 @@ const fs = require('fs');
const gulp = require('gulp');
const less = require('gulp-less');
const sourcemaps = require('gulp-sourcemaps');
-const tsc = require('gulp-tsc');
+const tsc = require('gulp-typescript');
const del = require('del');
const path = require('path');
-// TODO: Add gulp watch tasks
+const tsProject = tsc.createProject('./tsconfig.json');
gulp.task('clean', function() {
return del('lib');
@@ -17,8 +17,9 @@ gulp.task('clean', function() {
* and copy to the destination
*/
gulp.task('compile', function() {
- return gulp.src(['src/**/*.ts', 'src/**/*.tsx'])
- .pipe(tsc({ project: './tsconfig.json' }))
+ return tsProject.src()
+ .pipe(tsProject())
+ .on('error', (err) => console.log(err))
.pipe(gulp.dest('lib/'))
});
@@ -37,7 +38,8 @@ gulp.task('copy', function () {
return gulp.src([
'./src/renderer/assets/*',
'./src/renderer/*.html',
- './src/locale/*'
+ './src/locale/*',
+ './package.json'
], {
"base": "./src"
}).pipe(gulp.dest('lib/src'))
diff --git a/installer/win/Symphony-x64.aip b/installer/win/Symphony-x64.aip
index 29437e11..5eee64df 100644
--- a/installer/win/Symphony-x64.aip
+++ b/installer/win/Symphony-x64.aip
@@ -71,16 +71,11 @@
-
-
-
-
-
@@ -92,10 +87,8 @@
-
-
@@ -119,7 +112,6 @@
-
@@ -133,18 +125,17 @@
-
-
+
-
+
@@ -164,7 +155,6 @@
-
@@ -227,7 +217,6 @@
-
diff --git a/installer/win/Symphony-x86.aip b/installer/win/Symphony-x86.aip
index 07af6b12..606e282b 100644
--- a/installer/win/Symphony-x86.aip
+++ b/installer/win/Symphony-x86.aip
@@ -70,16 +70,11 @@
-
-
-
-
-
@@ -91,10 +86,8 @@
-
-
@@ -118,7 +111,6 @@
-
@@ -132,18 +124,17 @@
-
-
+
-
+
@@ -163,7 +154,6 @@
-
@@ -226,7 +216,6 @@
-
diff --git a/package.json b/package.json
index f81e64cb..d57d34c6 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "symphony",
"productName": "Symphony",
- "version": "5.0.0",
+ "version": "6.0.0",
"clientVersion": "2.0.1",
"buildNumber": "0",
"searchAPIVersion": "1.55.3",
@@ -16,15 +16,63 @@
"demo-win": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file:///src/demo/index.html",
"demo-mac": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file://$(pwd)/src/demo/index.html",
"lint": "tslint --project tsconfig.json",
- "packed-linux": "npm run prebuild && npm run test && build --linux",
+ "packed-linux": "npm run prebuild && npm run test && ./node_modules/.bin/electron-builder build --linux",
"packed-mac": "npm run unpacked-mac && packagesbuild -v installer/mac/symphony-mac-packager.pkgproj",
"prebuild": "npm run compile && npm run rebuild && npm run browserify-preload",
"rebuild": "electron-rebuild -f",
"start": "npm run compile && npm run browserify-preload && cross-env ELECTRON_DEV=true electron .",
"test": "npm run lint && cross-env ELECTRON_QA=true jest --config jest-config.json --runInBand --detectOpenHandles",
- "unpacked-mac": "npm run prebuild && npm run test && build --mac --dir",
- "unpacked-win": "npm run prebuild && npm run test && build --win --x64 --dir",
- "unpacked-win-x86": "npm run prebuild && npm run test && build --win --ia32 --dir"
+ "unpacked-mac": "npm run prebuild && npm run test && ./node_modules/.bin/electron-builder build --mac --dir",
+ "unpacked-win": "npm run prebuild && npm run test && node_modules\\.bin\\electron-builder build --win --x64 --dir",
+ "unpacked-win-x86": "npm run prebuild && npm run test && node_modules\\.bin\\electron-builder build --win --ia32 --dir"
+ },
+ "build": {
+ "appId": "com.symphony.electron-desktop",
+ "asar": true,
+ "asarUnpack": [
+ "node_modules/@nornagon/cld/build/Release/cld.node",
+ "node_modules/@nornagon/spellchecker/build/Release/spellchecker.node",
+ "node_modules/keyboard-layout/build/Release/keyboard-layout-manager.node"
+ ],
+ "files": [
+ "!coverage/*",
+ "!installer/*",
+ "!tests/*",
+ "!node_modules/@nornagon/cld/deps/cld${/*}",
+ "!node_modules/@nornagon/cld/build/deps${/*}",
+ "!node_modules/@nornagon/spellchecker/vendor${/*}"
+ ],
+ "extraFiles": [
+ "config/Symphony.config",
+ "config/titleBarStyles.css",
+ "dictionaries/**",
+ "library/libsymphonysearch.dylib",
+ "library/indexvalidator.exec",
+ "library/cryptoLib.dylib",
+ "library/dictionary",
+ "library/lz4.exec"
+ ],
+ "mac": {
+ "category": "public.app-category.business",
+ "icon": "images/icon.icns"
+ },
+ "win": {
+ "icon": "images/icon.ico",
+ "target": [
+ "squirrel"
+ ]
+ },
+ "linux": {
+ "category": "Network;InstantMessaging;Chat",
+ "desktop": {
+ "StartupWMClass": "Symphony"
+ },
+ "target": [
+ "deb",
+ "rpm"
+ ],
+ "icon": "images/linux"
+ }
},
"repository": {
"type": "git",
@@ -49,8 +97,8 @@
"browserify": "16.2.3",
"cross-env": "5.2.0",
"del": "3.0.0",
- "electron": "5.0.10",
- "electron-builder": "20.38.4",
+ "electron": "6.1.2",
+ "electron-builder": "21.2.0",
"electron-builder-squirrel-windows": "20.38.3",
"electron-icon-maker": "0.0.4",
"electron-rebuild": "1.8.2",
@@ -60,10 +108,11 @@
"gulp": "4.0.0",
"gulp-less": "4.0.1",
"gulp-sourcemaps": "2.6.4",
- "gulp-tsc": "1.3.2",
+ "gulp-typescript": "5.0.1",
"jest": "23.6.0",
"jest-html-reporter": "2.4.2",
"less": "3.8.1",
+ "node-abi": "^2.12.0",
"ts-jest": "23.10.5",
"tslint": "5.11.0",
"typescript": "3.1.1"
@@ -76,7 +125,7 @@
"electron-dl": "1.14.0",
"electron-fetch": "1.3.0",
"electron-log": "3.0.7",
- "electron-spellchecker": "git+https://github.com/symphonyoss/electron-spellchecker.git#v2.0.3",
+ "electron-spellchecker": "git+https://github.com/symphonyoss/electron-spellchecker.git#v2.3.0",
"ffi-napi": "2.4.5",
"filesize": "4.1.2",
"react": "16.9.0",
diff --git a/spec/__mocks__/electron.ts b/spec/__mocks__/electron.ts
index 70725903..c28d0034 100644
--- a/spec/__mocks__/electron.ts
+++ b/spec/__mocks__/electron.ts
@@ -21,6 +21,7 @@ interface IApp {
setPath(value: string, path: string): void;
setLoginItemSettings(settings: { openAtLogin: boolean, path: string }): void;
getLoginItemSettings(options?: { path: string, args: string[] }): ILoginItemSettings;
+ setAppLogsPath(): void;
}
interface ILoginItemSettings {
openAtLogin: boolean;
@@ -37,7 +38,7 @@ interface IIpcRenderer {
once(eventName: any, cb: any): void;
}
interface IPowerMonitor {
- querySystemIdleTime(): void;
+ getSystemIdleTime(): void;
}
const pathToConfigDir = (): string => {
@@ -77,6 +78,9 @@ export const app: IApp = {
getLoginItemSettings: (): ILoginItemSettings => {
return { openAtLogin: true };
},
+ setAppLogsPath: (): void => {
+ return;
+ },
};
// simple ipc mocks for render and main process ipc using
@@ -98,7 +102,7 @@ export const ipcMain: IIpcMain = {
};
export const powerMonitor: IPowerMonitor = {
- querySystemIdleTime: jest.fn().mockImplementation((cb) => cb(mockIdleTime)),
+ getSystemIdleTime: jest.fn().mockReturnValue(mockIdleTime),
};
export const ipcRenderer: IIpcRenderer = {
diff --git a/spec/dialogHandler.spec.ts b/spec/dialogHandler.spec.ts
index aede23f1..a325ea8d 100644
--- a/spec/dialogHandler.spec.ts
+++ b/spec/dialogHandler.spec.ts
@@ -44,18 +44,20 @@ describe('dialog handler', () => {
const errorMocked = 'check for server certificate revocation';
const certificate = null;
- it('should return false when buttonId is 1', () => {
- dialog.showMessageBox = jest.fn(() => 1);
- ipcRenderer.send('certificate-error', webContentsMocked, urlMocked, errorMocked, certificate, callbackMocked);
- expect(callbackMocked).toBeCalledWith(false);
+ it('should return false when buttonId is 1', async (done) => {
+ dialog.showMessageBox = jest.fn(() => {
+ return { response: 1 };
+ });
+ await ipcRenderer.send('certificate-error', webContentsMocked, urlMocked, errorMocked, certificate, callbackMocked);
+ done(expect(callbackMocked).toBeCalledWith(false));
});
- it('should return true when buttonId is not 1', () => {
+ it('should return true when buttonId is not 1', async (done) => {
dialog.showMessageBox = jest.fn(() => 2);
- ipcRenderer.send('certificate-error', webContentsMocked, urlMocked, errorMocked, certificate, callbackMocked);
- expect(callbackMocked).toBeCalledWith(true);
- ipcRenderer.send('certificate-error', webContentsMocked, urlMocked, errorMocked, certificate, callbackMocked);
+ await ipcRenderer.send('certificate-error', webContentsMocked, urlMocked, errorMocked, certificate, callbackMocked);
expect(callbackMocked).toBeCalledWith(true);
+ await ipcRenderer.send('certificate-error', webContentsMocked, urlMocked, errorMocked, certificate, callbackMocked);
+ done(expect(callbackMocked).toBeCalledWith(true));
});
});
});
@@ -78,7 +80,7 @@ describe('dialog handler', () => {
message: `Error loading URL:\n${urlMocked}\n\n${errorDescMocked}\n\nError Code: ${errorCodeMocked}`,
};
showLoadFailure(browserWindowMocked, urlMocked, errorDescMocked, errorCodeMocked, callbackMocked, showDialogMocked);
- expect(spy).toBeCalledWith({ id: 123 }, expectedValue, expect.any(Function));
+ expect(spy).toBeCalledWith({ id: 123 }, expectedValue);
});
it('should call `showNetworkConnectivityError` correctly', () => {
@@ -97,6 +99,6 @@ describe('dialog handler', () => {
message: `Error loading URL:\n${urlMocked}\n\n${errorDescMocked}`,
};
showNetworkConnectivityError(browserWindowMocked, urlMocked, callbackMocked);
- expect(spy).toBeCalledWith({ id: 123 }, expectedValue, expect.any(Function));
+ expect(spy).toBeCalledWith({ id: 123 }, expectedValue);
});
});
diff --git a/src/app/activity-detection.ts b/src/app/activity-detection.ts
index fbd3a70d..314d2447 100644
--- a/src/app/activity-detection.ts
+++ b/src/app/activity-detection.ts
@@ -38,7 +38,10 @@ class ActivityDetection {
private startActivityMonitor(): void {
if (app.isReady()) {
logger.info(`activity-detection: Starting activity monitor`);
- this.queryInterval = setInterval(() => (electron.powerMonitor as any).querySystemIdleTime(this.activity.bind(this)), this.idleThreshold);
+ this.queryInterval = setInterval(() => {
+ const idleTime = electron.powerMonitor.getSystemIdleTime();
+ this.activity(idleTime);
+ }, this.idleThreshold);
}
}
@@ -69,7 +72,8 @@ class ActivityDetection {
// when user goes inactive
this.timer = setInterval(() => {
if (app.isReady()) {
- (electron.powerMonitor as any).querySystemIdleTime(this.activity.bind(this));
+ const activeTime = electron.powerMonitor.getSystemIdleTime();
+ this.activity(activeTime);
}
}, 1000);
}
diff --git a/src/app/app-menu.ts b/src/app/app-menu.ts
index 3a1a8320..c2e4609a 100644
--- a/src/app/app-menu.ts
+++ b/src/app/app-menu.ts
@@ -188,7 +188,7 @@ export class AppMenu {
{ label: i18n.t('Services')(), role: 'services' },
this.buildSeparator(),
{ label: i18n.t('Hide Symphony')(), role: 'hide' },
- { label: i18n.t('Hide Others')(), role: 'hideothers' },
+ { label: i18n.t('Hide Others')(), role: 'hideOthers' },
{ label: i18n.t('Show All')(), role: 'unhide' },
this.buildSeparator(),
{ label: i18n.t('Quit Symphony')(), role: 'quit' },
@@ -211,9 +211,9 @@ export class AppMenu {
this.assignRoleOrLabel({ role: 'cut', label: i18n.t('Cut')() }),
this.assignRoleOrLabel({ role: 'copy', label: i18n.t('Copy')() }),
this.assignRoleOrLabel({ role: 'paste', label: i18n.t('Paste')() }),
- this.assignRoleOrLabel({ role: 'pasteandmatchstyle', label: i18n.t('Paste and Match Style')() }),
+ this.assignRoleOrLabel({ role: 'pasteAndMatchStyle', label: i18n.t('Paste and Match Style')() }),
this.assignRoleOrLabel({ role: 'delete', label: i18n.t('Delete')() }),
- this.assignRoleOrLabel({ role: 'selectall', label: i18n.t('Select All')() }),
+ this.assignRoleOrLabel({ role: 'selectAll', label: i18n.t('Select All')() }),
],
};
@@ -221,8 +221,8 @@ export class AppMenu {
menu.submenu.push(this.buildSeparator(), {
label: i18n.t('Speech')(),
submenu: [
- { label: i18n.t('Start Speaking')(), role: 'startspeaking' },
- { label: i18n.t('Stop Speaking')(), role: 'stopspeaking' },
+ { label: i18n.t('Start Speaking')(), role: 'startSpeaking' },
+ { label: i18n.t('Stop Speaking')(), role: 'stopSpeaking' },
],
});
}
@@ -242,9 +242,9 @@ export class AppMenu {
label: i18n.t('Reload')(),
},
this.buildSeparator(),
- this.assignRoleOrLabel({ role: 'resetzoom', label: i18n.t('Actual Size')() }),
- this.assignRoleOrLabel({ role: 'zoomin', label: i18n.t('Zoom In')() }),
- this.assignRoleOrLabel({ role: 'zoomout', label: i18n.t('Zoom Out')() }),
+ this.assignRoleOrLabel({ role: 'resetZoom', label: i18n.t('Actual Size')() }),
+ this.assignRoleOrLabel({ role: 'zoomIn', label: i18n.t('Zoom In')() }),
+ this.assignRoleOrLabel({ role: 'zoomOut', label: i18n.t('Zoom Out')() }),
this.buildSeparator(),
this.assignRoleOrLabel({ role: 'togglefullscreen', label: i18n.t('Toggle Full Screen')() }),
],
diff --git a/src/app/dialog-handler.ts b/src/app/dialog-handler.ts
index 20f35345..3537c9bf 100644
--- a/src/app/dialog-handler.ts
+++ b/src/app/dialog-handler.ts
@@ -53,7 +53,7 @@ let ignoreAllCertErrors = false;
* Note: the dialog is synchronous so further processing is blocked until
* user provides a response.
*/
-electron.app.on('certificate-error', (event, webContents, url, error, _certificate, callback) => {
+electron.app.on('certificate-error', async (event, webContents, url, error, _certificate, callback) => {
// TODO: Add logic verify custom certificate
if (ignoreAllCertErrors) {
@@ -65,7 +65,7 @@ electron.app.on('certificate-error', (event, webContents, url, error, _certifica
logger.warn(`Certificate error: ${error} for url: ${url}`);
const browserWin = electron.BrowserWindow.fromWebContents(webContents);
- const buttonId = electron.dialog.showMessageBox(browserWin, {
+ const { response } = await electron.dialog.showMessageBox(browserWin, {
type: 'warning',
buttons: [
i18n.t('Allow')(),
@@ -81,11 +81,11 @@ electron.app.on('certificate-error', (event, webContents, url, error, _certifica
event.preventDefault();
- if (buttonId === 2) {
+ if (response === 2) {
ignoreAllCertErrors = true;
}
- callback(buttonId !== 1);
+ callback(response !== 1);
});
/**
@@ -98,7 +98,7 @@ electron.app.on('certificate-error', (event, webContents, url, error, _certifica
* @param retryCallback {function} Callback when user clicks reload
* @param showDialog {Boolean} Indicates if a dialog need to be show to a user
*/
-export const showLoadFailure = (browserWindow: Electron.BrowserWindow, url: string, errorDesc: string, errorCode: number, retryCallback: () => void, showDialog: boolean): void => {
+export const showLoadFailure = async (browserWindow: Electron.BrowserWindow, url: string, errorDesc: string, errorCode: number, retryCallback: () => void, showDialog: boolean): Promise => {
let message = url ? `${i18n.t('Error loading URL')()}:\n${url}` : i18n.t('Error loading window')();
if (errorDesc) {
message += `\n\n${errorDesc}`;
@@ -107,16 +107,8 @@ export const showLoadFailure = (browserWindow: Electron.BrowserWindow, url: stri
message += `\n\nError Code: ${errorCode}`;
}
- // async handle of user input
- const response = (buttonId: number): void => {
- // retry if hitting button index 0 (i.e., reload)
- if (buttonId === 0 && typeof retryCallback === 'function') {
- retryCallback();
- }
- };
-
if (showDialog) {
- electron.dialog.showMessageBox(browserWindow, {
+ const { response } = await electron.dialog.showMessageBox(browserWindow, {
type: 'error',
buttons: [ i18n.t('Reload')(), i18n.t('Ignore')() ],
defaultId: 0,
@@ -124,7 +116,13 @@ export const showLoadFailure = (browserWindow: Electron.BrowserWindow, url: stri
noLink: true,
title: i18n.t('Loading Error')(),
message,
- }, response);
+ });
+
+ // async handle of user input
+ // retry if hitting button index 0 (i.e., reload)
+ if (response === 0 && typeof retryCallback === 'function') {
+ retryCallback();
+ }
}
logger.warn(`Load failure msg: ${errorDesc} errorCode: ${errorCode} for url: ${url}`);
@@ -148,7 +146,7 @@ export const showNetworkConnectivityError = (browserWindow: Electron.BrowserWind
*
* @param isNativeStyle {boolean}
*/
-export const titleBarChangeDialog = (isNativeStyle: boolean) => {
+export const titleBarChangeDialog = async (isNativeStyle: boolean) => {
const focusedWindow = electron.BrowserWindow.getFocusedWindow();
if (!focusedWindow || !windowExists(focusedWindow)) {
return;
@@ -161,11 +159,10 @@ export const titleBarChangeDialog = (isNativeStyle: boolean) => {
buttons: [ i18n.t('Relaunch')(), i18n.t('Cancel')() ],
cancelId: 1,
};
- electron.dialog.showMessageBox(focusedWindow, options, async (index) => {
- if (index === 0) {
- await config.updateUserConfig({ isCustomTitleBar: isNativeStyle });
- app.relaunch();
- app.exit();
- }
- });
+ const { response } = await electron.dialog.showMessageBox(focusedWindow, options);
+ if (response === 0) {
+ await config.updateUserConfig({ isCustomTitleBar: isNativeStyle });
+ app.relaunch();
+ app.exit();
+ }
};
diff --git a/src/app/main-api-handler.ts b/src/app/main-api-handler.ts
index 47c36a98..fd274b1e 100644
--- a/src/app/main-api-handler.ts
+++ b/src/app/main-api-handler.ts
@@ -26,7 +26,7 @@ import {
* Handle API related ipc messages from renderers. Only messages from windows
* we have created are allowed.
*/
-ipcMain.on(apiName.symphonyApi, (event: Electron.Event, arg: IApiArgs) => {
+ipcMain.on(apiName.symphonyApi, (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;
diff --git a/src/app/reports-handler.ts b/src/app/reports-handler.ts
index 56c756d9..9547deb0 100644
--- a/src/app/reports-handler.ts
+++ b/src/app/reports-handler.ts
@@ -67,7 +67,7 @@ export const exportLogs = (): void => {
const FILE_EXTENSIONS = [ '.log' ];
const MAC_LOGS_PATH = '/Library/Logs/Symphony/';
const LINUX_LOGS_PATH = '/.config/Symphony/';
- const WINDOWS_LOGS_PATH = '\\AppData\\Roaming\\Symphony\\logs';
+ const WINDOWS_LOGS_PATH = '\\AppData\\Local\\Symphony\\Symphony\\logs';
const logsPath = isMac ? MAC_LOGS_PATH : isLinux ? LINUX_LOGS_PATH : WINDOWS_LOGS_PATH;
const source = app.getPath('home') + logsPath;
diff --git a/src/app/window-handler.ts b/src/app/window-handler.ts
index 52595cb6..08123938 100644
--- a/src/app/window-handler.ts
+++ b/src/app/window-handler.ts
@@ -240,23 +240,22 @@ export class WindowHandler {
}
});
- this.mainWindow.webContents.on('crashed', (_event: Event, killed: boolean) => {
+ this.mainWindow.webContents.on('crashed', async (_event: Event, killed: boolean) => {
if (killed) {
logger.info(`window-handler: main window crashed (killed)!`);
return;
}
logger.info(`window-handler: main window crashed!`);
- electron.dialog.showMessageBox({
+ const { response } = await electron.dialog.showMessageBox({
type: 'error',
title: i18n.t('Renderer Process Crashed')(),
message: i18n.t('Oops! Looks like we have had a crash. Please reload or close this window.')(),
buttons: ['Reload', 'Close'],
- }, (index: number) => {
- if (!this.mainWindow || !windowExists(this.mainWindow)) {
- return;
- }
- index === 0 ? this.mainWindow.reload() : this.mainWindow.close();
});
+ if (!this.mainWindow || !windowExists(this.mainWindow)) {
+ return;
+ }
+ response === 0 ? this.mainWindow.reload() : this.mainWindow.close();
});
// Handle main window close
@@ -551,7 +550,7 @@ export class WindowHandler {
}
this.basicAuthWindow.webContents.send('basic-auth-data', {hostname, isValidCredentials: isMultipleTries});
});
- const closeBasicAuth = (shouldClearSettings = true) => {
+ const closeBasicAuth = (_event, shouldClearSettings = true) => {
if (shouldClearSettings) {
clearSettings();
}
@@ -564,7 +563,7 @@ export class WindowHandler {
const login = (_event, arg) => {
const {username, password} = arg;
callback(username, password);
- closeBasicAuth(false);
+ closeBasicAuth(null, false);
};
this.basicAuthWindow.once('close', () => {
@@ -826,7 +825,7 @@ export class WindowHandler {
* Check if build is expired and show an error message
* @param browserWindow Focused window instance
*/
- private checkExpiry(browserWindow: BrowserWindow) {
+ private async checkExpiry(browserWindow: BrowserWindow) {
logger.info(`window handler: calling ttl handler to check for build expiry!`);
const buildExpired = checkIfBuildExpired();
if (!buildExpired) {
@@ -834,21 +833,19 @@ export class WindowHandler {
return;
}
logger.info(`window handler: build expired, will inform the user and quit the app!`);
- const response = (resp: number) => {
- if (resp === 0) {
- electron.app.exit();
- }
- };
const options = {
type: 'error',
title: i18n.t('Build expired')(),
message: i18n.t('Sorry, this is a test build and it has expired. Please contact your administrator to get a production build.')(),
- buttons: [i18n.t('Quit')()],
+ buttons: [ i18n.t('Quit')() ],
cancelId: 0,
};
- electron.dialog.showMessageBox(browserWindow, options, response);
+ const { response } = await electron.dialog.showMessageBox(browserWindow, options);
+ if (response === 0) {
+ electron.app.exit();
+ }
}
/**
diff --git a/src/app/window-utils.ts b/src/app/window-utils.ts
index 76f550d8..ccba463c 100644
--- a/src/app/window-utils.ts
+++ b/src/app/window-utils.ts
@@ -71,7 +71,7 @@ export const preventWindowNavigation = (browserWindow: BrowserWindow, isPopOutWi
electron.dialog.showMessageBox(browserWindow, {
type: 'warning',
buttons: [ 'OK' ],
- title: i18n.t('Not Allowed'),
+ title: i18n.t('Not Allowed')(),
message: `${i18n.t(`Sorry, you are not allowed to access this website`)} (${winUrl}), ${i18n.t('please contact your administrator for more details')}`,
});
}
@@ -341,9 +341,9 @@ export const downloadManagerAction = (type, filePath): void => {
}
return;
}
-
- const showResponse = electron.shell.showItemInFolder(filePath);
- if (!showResponse) {
+ if (fs.existsSync(filePath)) {
+ electron.shell.showItemInFolder(filePath);
+ } else {
electron.dialog.showMessageBox(focusedWindow, {
message,
title,
diff --git a/src/common/logger.ts b/src/common/logger.ts
index bdacb185..4b789b4e 100644
--- a/src/common/logger.ts
+++ b/src/common/logger.ts
@@ -4,7 +4,7 @@ import * as fs from 'fs';
import * as path from 'path';
import * as util from 'util';
-import { isElectronQA, isLinux } from './env';
+import { isElectronQA, isLinux, isWindowsOS } from './env';
import { getCommandLineArgs } from './utils';
export interface ILogMsg {
@@ -22,6 +22,16 @@ interface IClientLogMsg {
const MAX_LOG_QUEUE_LENGTH = 100;
+// Force log path to local path in Windows rather than roaming
+if (isWindowsOS && process.env.LOCALAPPDATA) {
+ app.setPath('appData', process.env.LOCALAPPDATA);
+ app.setPath('userData', path.join(app.getPath('appData'), app.getName()));
+}
+
+// Electron wants this to be called initially before calling
+// app.getPath('logs')
+app.setAppLogsPath();
+
class Logger {
private readonly showInConsole: boolean = false;
private readonly desiredLogLevel?: LogLevel;
diff --git a/tsconfig.json b/tsconfig.json
index 6981c740..f488abc7 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,6 +6,7 @@
"resolveJsonModule": true,
"jsx": "react",
"outDir": "lib",
+ "rootDir": ".",
"lib": [
"es2016",
"dom"