Files
SymphonyElectron/src/browser/config-handler.ts
2019-04-02 10:56:36 +05:30

210 lines
5.9 KiB
TypeScript

import { app } from 'electron';
import * as fs from 'fs';
import * as path from 'path';
import { omit } from 'lodash';
import compareSemVersions from '../common/compare-sem-versions';
import { logger } from '../common/logger';
import { isDevEnv, isMac } from '../common/mics';
import pick from '../common/pick';
const ignoreSettings = [
'minimizeOnClose',
'launchOnStartup',
'alwaysOnTop',
'url',
'memoryRefresh',
'bringToFront',
'isCustomTitleBar',
];
export interface IConfig {
url: string;
minimizeOnClose: boolean;
launchOnStartup: boolean;
alwaysOnTop: boolean;
bringToFront: boolean;
whitelistUrl: string;
isCustomTitleBar: boolean;
memoryRefresh: boolean;
devToolsEnabled: boolean;
ctWhitelist: string[];
configVersion: string;
autoLaunchPath: string;
notificationSettings: INotificationSetting;
permissions: IPermission;
customFlags: ICustomFlag;
crashReporter: ICrashReporter;
}
export interface IPermission {
media: boolean;
geolocation: boolean;
notifications: boolean;
midiSysex: boolean;
pointerLock: boolean;
fullscreen: boolean;
openExternal: boolean;
}
export interface ICustomFlag {
authServerWhitelist: string;
authNegotiateDelegateWhitelist: string;
disableGpu: boolean;
}
export interface ICrashReporter {
submitURL: string;
companyName: string;
uploadToServer: boolean;
}
export interface INotificationSetting {
position: string;
display: string;
}
class Config {
private userConfig: IConfig | {};
private globalConfig: IConfig | {};
private isFirstTime: boolean = true;
private readonly configFileName: string;
private readonly userConfigPath: string;
private readonly appPath: string;
private readonly globalConfigPath: string;
constructor() {
this.configFileName = 'Symphony.config';
this.userConfigPath = path.join(app.getPath('userData'), this.configFileName);
this.appPath = isDevEnv ? app.getAppPath() : path.dirname(app.getPath('exe'));
this.globalConfigPath = isDevEnv
? path.join(this.appPath, path.join('config', this.configFileName))
: path.join(this.appPath, isMac ? '..' : '', 'config', this.configFileName);
this.globalConfig = {};
this.userConfig = {};
this.readUserConfig();
this.readGlobalConfig();
this.checkFirstTimeLaunch();
}
/**
* Returns the specified fields from both user and global config file
* and keep values from user config as priority
*
* @param fields
*/
public getConfigFields(fields: string[]): IConfig {
return { ...this.getGlobalConfigFields(fields), ...this.getUserConfigFields(fields) } as IConfig;
}
/**
* Returns the specified fields from user config file
*
* @param fields {Array}
*/
public getUserConfigFields(fields: string[]): IConfig {
return pick(this.userConfig, fields) as IConfig;
}
/**
* Returns the specified fields from global config file
*
* @param fields {Array}
*/
public getGlobalConfigFields(fields: string[]): IConfig {
return pick(this.globalConfig, fields) as IConfig;
}
/**
* updates new data to the user config
*
* @param data {IConfig}
*/
public updateUserConfig(data: IConfig): void {
this.userConfig = { ...data, ...this.userConfig };
fs.writeFileSync(this.userConfigPath, JSON.stringify(this.userConfig), { encoding: 'utf8' });
}
public isFirstTimeLaunch(): boolean {
return this.isFirstTime;
}
/**
* Method that updates user config file
* by modifying the old config file
*/
public async setUpFirstTimeLaunch(): Promise<void> {
const filteredFields: IConfig = omit(this.userConfig, ignoreSettings) as IConfig;
await this.updateUserConfig(filteredFields);
}
/**
* Parses the config data string
*
* @param data
*/
private parseConfigData(data: string): object {
let parsedData;
if (!data) {
throw new Error('unable to read user config file');
}
try {
parsedData = JSON.parse(data);
} catch (e) {
throw new Error(e);
}
return parsedData;
}
/**
* Reads a stores the user config file
*
* If user config doesn't exits?
* this creates a new one with { configVersion: current_app_version }
*/
private readUserConfig() {
if (!fs.existsSync(this.userConfigPath)) {
this.updateUserConfig({ configVersion: app.getVersion().toString() } as IConfig);
}
this.userConfig = this.parseConfigData(fs.readFileSync(this.userConfigPath, 'utf8'));
}
/**
* Reads a stores the global config file
*/
private readGlobalConfig() {
this.globalConfig = this.parseConfigData(fs.readFileSync(this.globalConfigPath, 'utf8'));
}
/**
* Verifies if the application is launched for the first time
*/
private checkFirstTimeLaunch() {
logger.info('checking first launch');
const appVersionString = app.getVersion().toString();
const execPath = path.dirname(this.appPath);
const shouldUpdateUserConfig = execPath.indexOf('AppData\\Local\\Programs') !== -1 || isMac;
const userConfigVersion = this.userConfig && (this.userConfig as IConfig).configVersion || null;
if (!userConfigVersion) {
this.isFirstTime = true;
return;
}
if (!(userConfigVersion
&& typeof userConfigVersion === 'string'
&& (compareSemVersions(appVersionString, userConfigVersion) !== 1)) && shouldUpdateUserConfig) {
this.isFirstTime = true;
return;
}
this.isFirstTime = false;
}
}
const config = new Config();
export {
config,
};