mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
Typescript - Refactor code base
This commit is contained in:
parent
3177e54b6e
commit
9c138ddf25
@ -6,8 +6,8 @@
|
|||||||
"buildNumber": "0",
|
"buildNumber": "0",
|
||||||
"description": "Symphony desktop app (Foundation ODP)",
|
"description": "Symphony desktop app (Foundation ODP)",
|
||||||
"author": "Symphony",
|
"author": "Symphony",
|
||||||
"main": "lib/src/browser/main.js",
|
"main": "lib/src/app/main.js",
|
||||||
"types": "lib/src/browser/main.d.ts",
|
"types": "lib/src/app/main.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile": "npm run lint && gulp build",
|
"compile": "npm run lint && gulp build",
|
||||||
"lint": "tslint --project tsconfig.json",
|
"lint": "tslint --project tsconfig.json",
|
||||||
|
@ -5,7 +5,7 @@ import { i18n, LocaleType } from '../common/i18n';
|
|||||||
import { logger } from '../common/logger';
|
import { logger } from '../common/logger';
|
||||||
import { autoLaunchInstance as autoLaunch } from './auto-launch-controller';
|
import { autoLaunchInstance as autoLaunch } from './auto-launch-controller';
|
||||||
import { config, IConfig } from './config-handler';
|
import { config, IConfig } from './config-handler';
|
||||||
import { exportCrashDumps, exportLogs } from './reports';
|
import { exportCrashDumps, exportLogs } from './reports-handler';
|
||||||
import { updateAlwaysOnTop } from './window-actions';
|
import { updateAlwaysOnTop } from './window-actions';
|
||||||
import { windowHandler } from './window-handler';
|
import { windowHandler } from './window-handler';
|
||||||
|
|
@ -46,7 +46,7 @@ const library = new Library((cryptoLibPath), {
|
|||||||
getVersion: [types.CString, []],
|
getVersion: [types.CString, []],
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface ICryptoLib {
|
interface ICryptoLib {
|
||||||
AESGCMEncrypt: (name: string, base64IV: string, base64AAD: string, base64Key: string, base64In: string) => string | null;
|
AESGCMEncrypt: (name: string, base64IV: string, base64AAD: string, base64Key: string, base64In: string) => string | null;
|
||||||
AESGCMDecrypt: (base64IV: string, base64AAD: string, base64Key: string, base64In: string) => string | null;
|
AESGCMDecrypt: (base64IV: string, base64AAD: string, base64Key: string, base64In: string) => string | null;
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ import { setChromeFlags } from './chrome-flags';
|
|||||||
import { config } from './config-handler';
|
import { config } from './config-handler';
|
||||||
import './dialog-handler';
|
import './dialog-handler';
|
||||||
import './main-api-handler';
|
import './main-api-handler';
|
||||||
import { SpellChecker } from './spell-checker-handler';
|
import { SpellChecker } from './spell-check-handler';
|
||||||
import { ICustomBrowserWindow, windowHandler } from './window-handler';
|
import { ICustomBrowserWindow, windowHandler } from './window-handler';
|
||||||
|
|
||||||
const allowMultiInstance: string | boolean = getCommandLineArgs(process.argv, '--multiInstance', true) || isDevEnv;
|
const allowMultiInstance: string | boolean = getCommandLineArgs(process.argv, '--multiInstance', true) || isDevEnv;
|
@ -1,11 +1,64 @@
|
|||||||
|
import * as archiver from 'archiver';
|
||||||
import { app, BrowserWindow, dialog, shell } from 'electron';
|
import { app, BrowserWindow, dialog, shell } from 'electron';
|
||||||
import * as fs from 'fs';
|
|
||||||
|
|
||||||
import * as electron from 'electron';
|
import * as electron from 'electron';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
import { isMac } from '../common/env';
|
import { isMac } from '../common/env';
|
||||||
import { i18n } from '../common/i18n';
|
import { i18n } from '../common/i18n';
|
||||||
import { generateArchiveForDirectory } from '../common/utils';
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Archives files in the source directory
|
||||||
|
* that matches the given file extension
|
||||||
|
*
|
||||||
|
* @param source {String} source path
|
||||||
|
* @param destination {String} destination path
|
||||||
|
* @param fileExtensions {Array} array of file ext
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
const generateArchiveForDirectory = (source: string, destination: string, fileExtensions: string[]): Promise<void> => {
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const output = fs.createWriteStream(destination);
|
||||||
|
const archive = archiver('zip', { zlib: { level: 9 } });
|
||||||
|
|
||||||
|
output.on('close', () => {
|
||||||
|
return resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
archive.on('error', (err) => {
|
||||||
|
return reject(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
archive.pipe(output);
|
||||||
|
|
||||||
|
const files = fs.readdirSync(source);
|
||||||
|
files
|
||||||
|
.filter((file) => fileExtensions.indexOf(path.extname(file)) !== -1)
|
||||||
|
.forEach((file) => {
|
||||||
|
switch (path.extname(file)) {
|
||||||
|
case '.log':
|
||||||
|
archive.file(source + '/' + file, { name: 'logs/' + file });
|
||||||
|
break;
|
||||||
|
case '.dmp':
|
||||||
|
case '.txt': // on Windows .txt files will be created as part of crash dump
|
||||||
|
archive.file(source + '/' + file, { name: 'crashes/' + file });
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
archive.finalize();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compress and export logs stored under system log directory
|
||||||
|
*
|
||||||
|
* MacOS - /Library/Logs/Symphony/
|
||||||
|
* Windows - AppData\Roaming\Symphony\logs
|
||||||
|
*/
|
||||||
export const exportLogs = (): void => {
|
export const exportLogs = (): void => {
|
||||||
const FILE_EXTENSIONS = [ '.log' ];
|
const FILE_EXTENSIONS = [ '.log' ];
|
||||||
const MAC_LOGS_PATH = '/Library/Logs/Symphony/';
|
const MAC_LOGS_PATH = '/Library/Logs/Symphony/';
|
||||||
@ -42,6 +95,9 @@ export const exportLogs = (): void => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compress and export crash dump stored under system crashes directory
|
||||||
|
*/
|
||||||
export const exportCrashDumps = (): void => {
|
export const exportCrashDumps = (): void => {
|
||||||
const FILE_EXTENSIONS = isMac ? [ '.dmp' ] : [ '.dmp', '.txt' ];
|
const FILE_EXTENSIONS = isMac ? [ '.dmp' ] : [ '.dmp', '.txt' ];
|
||||||
const crashesDirectory = (electron.crashReporter as any).getCrashesDirectory();
|
const crashesDirectory = (electron.crashReporter as any).getCrashesDirectory();
|
@ -2,7 +2,7 @@ import { BrowserWindow } from 'electron';
|
|||||||
|
|
||||||
import { apiName, IBoundsChange, KeyCodes } from '../common/api-interface';
|
import { apiName, IBoundsChange, KeyCodes } from '../common/api-interface';
|
||||||
import { isWindowsOS } from '../common/env';
|
import { isWindowsOS } from '../common/env';
|
||||||
import { throttle } from '../common/throttle';
|
import { throttle } from '../common/utils';
|
||||||
import { config } from './config-handler';
|
import { config } from './config-handler';
|
||||||
import { ICustomBrowserWindow, windowHandler } from './window-handler';
|
import { ICustomBrowserWindow, windowHandler } from './window-handler';
|
||||||
import { showPopupMenu } from './window-utils';
|
import { showPopupMenu } from './window-utils';
|
@ -10,9 +10,9 @@ import { isMac, isWindowsOS } from '../common/env';
|
|||||||
import { i18n } from '../common/i18n';
|
import { i18n } from '../common/i18n';
|
||||||
import { getCommandLineArgs, getGuid } from '../common/utils';
|
import { getCommandLineArgs, getGuid } from '../common/utils';
|
||||||
import { AppMenu } from './app-menu';
|
import { AppMenu } from './app-menu';
|
||||||
|
import { handleChildWindow } from './child-window-handler';
|
||||||
import { config, IConfig } from './config-handler';
|
import { config, IConfig } from './config-handler';
|
||||||
import { showNetworkConnectivityError } from './dialog-handler';
|
import { showNetworkConnectivityError } from './dialog-handler';
|
||||||
import { handleChildWindow } from './pop-out-window-handler';
|
|
||||||
import { monitorWindowActions } from './window-actions';
|
import { monitorWindowActions } from './window-actions';
|
||||||
import { createComponentWindow, getBounds, handleDownloadManager, injectStyles } from './window-utils';
|
import { createComponentWindow, getBounds, handleDownloadManager, injectStyles } from './window-utils';
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
/**
|
|
||||||
* Formats a string with dynamic values
|
|
||||||
* @param str {String} String to be formatted
|
|
||||||
* @param data {Object} - Data to be added
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* StringFormat(this will log {time}`, { time: '1234' })
|
|
||||||
*
|
|
||||||
* result:
|
|
||||||
* this will log 1234
|
|
||||||
*
|
|
||||||
* @return {*}
|
|
||||||
*/
|
|
||||||
export const formatString = (str: string, data?: object): string => {
|
|
||||||
|
|
||||||
if (!str || !data) return str;
|
|
||||||
|
|
||||||
for (const key in data) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
||||||
return str.replace(/({([^}]+)})/g, (i) => {
|
|
||||||
const replacedKey = i.replace(/{/, '').replace(/}/, '');
|
|
||||||
if (!data[key] || !data[key][replacedKey]) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return data[key][replacedKey];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
};
|
|
@ -1,4 +1,4 @@
|
|||||||
import { formatString } from './format-string';
|
import { formatString } from './utils';
|
||||||
|
|
||||||
const localeCodeRegex = /^([a-z]{2})-([A-Z]{2})$/;
|
const localeCodeRegex = /^([a-z]{2})-([A-Z]{2})$/;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
import { formatString } from './format-string';
|
import { formatString } from './utils';
|
||||||
|
|
||||||
const localeCodeRegex = /^([a-z]{2})-([A-Z]{2})$/;
|
const localeCodeRegex = /^([a-z]{2})-([A-Z]{2})$/;
|
||||||
|
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
/**
|
|
||||||
* Limits your function to be called at most every milliseconds
|
|
||||||
*
|
|
||||||
* @param func
|
|
||||||
* @param wait
|
|
||||||
* @example const throttled = throttle(anyFunc, 500);
|
|
||||||
*/
|
|
||||||
export const throttle = (func: (...args) => void, wait: number): (...args) => void => {
|
|
||||||
if (wait <= 0) {
|
|
||||||
throw Error('throttle: invalid throttleTime arg, must be a number: ' + wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
let isCalled: boolean = false;
|
|
||||||
|
|
||||||
return (...args) => {
|
|
||||||
if (!isCalled) {
|
|
||||||
func(...args);
|
|
||||||
isCalled = true;
|
|
||||||
setTimeout(() => isCalled = false, wait);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,7 +1,3 @@
|
|||||||
import * as archiver from 'archiver';
|
|
||||||
import * as fs from 'fs';
|
|
||||||
import * as path from 'path';
|
|
||||||
|
|
||||||
// regex match the semver (semantic version) this checks for the pattern X.Y.Z
|
// regex match the semver (semantic version) this checks for the pattern X.Y.Z
|
||||||
// ex-valid v1.2.0, 1.2.0, 2.3.4-r51
|
// ex-valid v1.2.0, 1.2.0, 2.3.4-r51
|
||||||
const semver = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(?:-[\da-z-]+(?:\.[\da-z-]+)*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?)?)?$/i;
|
const semver = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(?:-[\da-z-]+(?:\.[\da-z-]+)*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?)?)?$/i;
|
||||||
@ -52,7 +48,7 @@ const validate = (version: string): number => {
|
|||||||
* @param v2
|
* @param v2
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
const compareVersions = (v1: string, v2: string): number => {
|
export const compareVersions = (v1: string, v2: string): number => {
|
||||||
if (validate(v1) === -1 || validate(v2) === -1) {
|
if (validate(v1) === -1 || validate(v2) === -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -96,7 +92,7 @@ const compareVersions = (v1: string, v2: string): number => {
|
|||||||
* try finding arg that starts with argName.
|
* try finding arg that starts with argName.
|
||||||
* @return {String} If found, returns the arg, otherwise null.
|
* @return {String} If found, returns the arg, otherwise null.
|
||||||
*/
|
*/
|
||||||
const getCommandLineArgs = (argv: string[], argName: string, exactMatch: boolean): string | null => {
|
export const getCommandLineArgs = (argv: string[], argName: string, exactMatch: boolean): string | null => {
|
||||||
if (!Array.isArray(argv)) {
|
if (!Array.isArray(argv)) {
|
||||||
throw new Error(`get-command-line-args: TypeError invalid func arg, must be an array: ${argv}`);
|
throw new Error(`get-command-line-args: TypeError invalid func arg, must be an array: ${argv}`);
|
||||||
}
|
}
|
||||||
@ -120,7 +116,7 @@ const getCommandLineArgs = (argv: string[], argName: string, exactMatch: boolean
|
|||||||
*
|
*
|
||||||
* @return {String} guid value in string
|
* @return {String} guid value in string
|
||||||
*/
|
*/
|
||||||
const getGuid = (): string => {
|
export const getGuid = (): string => {
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
|
||||||
(c) => {
|
(c) => {
|
||||||
const r = Math.random() * 16 | 0; // tslint:disable-line:no-bitwise
|
const r = Math.random() * 16 | 0; // tslint:disable-line:no-bitwise
|
||||||
@ -135,7 +131,7 @@ const getGuid = (): string => {
|
|||||||
* @param object Object to be filtered
|
* @param object Object to be filtered
|
||||||
* @param fields Fields to be picked
|
* @param fields Fields to be picked
|
||||||
*/
|
*/
|
||||||
const pick = (object: object, fields: string[]) => {
|
export const pick = (object: object, fields: string[]) => {
|
||||||
const obj = {};
|
const obj = {};
|
||||||
for (const field of fields) {
|
for (const field of fields) {
|
||||||
if (object[field]) {
|
if (object[field]) {
|
||||||
@ -146,49 +142,55 @@ const pick = (object: object, fields: string[]) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Archives files in the source directory
|
* Limits your function to be called at most every milliseconds
|
||||||
* that matches the given file extension
|
|
||||||
*
|
*
|
||||||
* @param source {String} source path
|
* @param func
|
||||||
* @param destination {String} destination path
|
* @param wait
|
||||||
* @param fileExtensions {Array} array of file ext
|
* @example const throttled = throttle(anyFunc, 500);
|
||||||
* @return {Promise<void>}
|
|
||||||
*/
|
*/
|
||||||
const generateArchiveForDirectory = (source: string, destination: string, fileExtensions: string[]): Promise<void> => {
|
export const throttle = (func: (...args) => void, wait: number): (...args) => void => {
|
||||||
|
if (wait <= 0) {
|
||||||
|
throw Error('throttle: invalid throttleTime arg, must be a number: ' + wait);
|
||||||
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
let isCalled: boolean = false;
|
||||||
const output = fs.createWriteStream(destination);
|
|
||||||
const archive = archiver('zip', { zlib: { level: 9 } });
|
|
||||||
|
|
||||||
output.on('close', () => {
|
return (...args) => {
|
||||||
return resolve();
|
if (!isCalled) {
|
||||||
});
|
func(...args);
|
||||||
|
isCalled = true;
|
||||||
archive.on('error', (err) => {
|
setTimeout(() => isCalled = false, wait);
|
||||||
return reject(err);
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
archive.pipe(output);
|
|
||||||
|
|
||||||
const files = fs.readdirSync(source);
|
|
||||||
files
|
|
||||||
.filter((file) => fileExtensions.indexOf(path.extname(file)) !== -1)
|
|
||||||
.forEach((file) => {
|
|
||||||
switch (path.extname(file)) {
|
|
||||||
case '.log':
|
|
||||||
archive.file(source + '/' + file, { name: 'logs/' + file });
|
|
||||||
break;
|
|
||||||
case '.dmp':
|
|
||||||
case '.txt': // on Windows .txt files will be created as part of crash dump
|
|
||||||
archive.file(source + '/' + file, { name: 'crashes/' + file });
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
archive.finalize();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export { compareVersions, getCommandLineArgs, getGuid, pick, generateArchiveForDirectory };
|
/**
|
||||||
|
* Formats a string with dynamic values
|
||||||
|
* @param str {String} String to be formatted
|
||||||
|
* @param data {Object} - Data to be added
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* StringFormat(this will log {time}`, { time: '1234' })
|
||||||
|
*
|
||||||
|
* result:
|
||||||
|
* this will log 1234
|
||||||
|
*
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
export const formatString = (str: string, data?: object): string => {
|
||||||
|
|
||||||
|
if (!str || !data) return str;
|
||||||
|
|
||||||
|
for (const key in data) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
||||||
|
return str.replace(/({([^}]+)})/g, (i) => {
|
||||||
|
const replacedKey = i.replace(/{/, '').replace(/}/, '');
|
||||||
|
if (!data[key] || !data[key][replacedKey]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return data[key][replacedKey];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
};
|
@ -1,6 +1,5 @@
|
|||||||
import { ipcRenderer, remote } from 'electron';
|
import { ipcRenderer, remote } from 'electron';
|
||||||
|
|
||||||
import { ICryptoLib } from '../browser/crypto-library-handler';
|
|
||||||
import {
|
import {
|
||||||
apiCmds,
|
apiCmds,
|
||||||
apiName,
|
apiName,
|
||||||
@ -10,13 +9,18 @@ import {
|
|||||||
IScreenSnippet, KeyCodes,
|
IScreenSnippet, KeyCodes,
|
||||||
} from '../common/api-interface';
|
} from '../common/api-interface';
|
||||||
import { i18n, LocaleType } from '../common/i18n-preload';
|
import { i18n, LocaleType } from '../common/i18n-preload';
|
||||||
import { throttle } from '../common/throttle';
|
import { throttle } from '../common/utils';
|
||||||
import { getSource } from './desktop-capturer';
|
import { getSource } from './desktop-capturer';
|
||||||
|
|
||||||
let isAltKey: boolean = false;
|
let isAltKey: boolean = false;
|
||||||
let isMenuOpen: boolean = false;
|
let isMenuOpen: boolean = false;
|
||||||
let nextId = 0;
|
let nextId = 0;
|
||||||
|
|
||||||
|
interface ICryptoLib {
|
||||||
|
AESGCMEncrypt: (name: string, base64IV: string, base64AAD: string, base64Key: string, base64In: string) => string | null;
|
||||||
|
AESGCMDecrypt: (base64IV: string, base64AAD: string, base64Key: string, base64In: string) => string | null;
|
||||||
|
}
|
||||||
|
|
||||||
interface ILocalObject {
|
interface ILocalObject {
|
||||||
ipcRenderer;
|
ipcRenderer;
|
||||||
activityDetectionCallback?: (arg: IActivityDetection) => void;
|
activityDetectionCallback?: (arg: IActivityDetection) => void;
|
||||||
@ -46,7 +50,7 @@ const throttledSetLocale = throttle((locale) => {
|
|||||||
|
|
||||||
let cryptoLib: ICryptoLib | null;
|
let cryptoLib: ICryptoLib | null;
|
||||||
try {
|
try {
|
||||||
cryptoLib = remote.require('../browser/crypto-library-handler.js').cryptoLibrary;
|
cryptoLib = remote.require('../app/crypto-handler.js').cryptoLibrary;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
cryptoLib = null;
|
cryptoLib = null;
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
|
Loading…
Reference in New Issue
Block a user