Skip to content
This repository has been archived by the owner on Nov 29, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' into feature/25-game-info
Browse files Browse the repository at this point in the history
  • Loading branch information
prefixaut committed Jul 18, 2019
2 parents 7774c48 + 6464a02 commit 832cd5c
Show file tree
Hide file tree
Showing 26 changed files with 148 additions and 377 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Expand Up @@ -14,5 +14,6 @@
],
"files.associations": {
"*.splits": "json"
}
},
"typescript.preferences.importModuleSpecifier": "relative"
}
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -36,7 +36,7 @@
},
"scripts": {
"serve": "vue-cli-service electron:serve",
"build": "vue-cli-service build:electron",
"build": "vue-cli-service electron:build",
"lint": "vue-cli-service lint ./src/**/*.vue ./src/**/*.ts",
"postinstall": "electron-builder install-app-deps",
"test:unit": "vue-cli-service test:unit",
Expand All @@ -48,7 +48,7 @@
"@fortawesome/vue-fontawesome": "^0.1.6",
"aevum": "^2.0.3",
"ajv": "^6.10.2",
"electron": "4.1.4",
"electron": "5.0.7",
"iso-639-1": "^2.0.5",
"keycode": "^2.2.0",
"lightweight-di": "^0.6.0",
Expand Down
19 changes: 12 additions & 7 deletions src/background.ts
@@ -1,11 +1,11 @@
'use strict';
import { app, BrowserWindow, ipcMain, protocol, WebContents } from 'electron';
import { app, BrowserWindow, ipcMain, WebContents } from 'electron';
import { merge } from 'lodash';
import { join } from 'path';
import * as pino from 'pino';
import { format as formatUrl } from 'url';
import Vue from 'vue';
import { createProtocol, installVueDevtools } from 'vue-cli-plugin-electron-builder/lib';
import { installVueDevtools, createProtocol } from 'vue-cli-plugin-electron-builder/lib';
import { OverlayHostPlugin } from 'vue-overlay-host';
import Vuex from 'vuex';

Expand All @@ -20,13 +20,18 @@ import { RootState } from './store/states/root.state';
import { Logger } from './utils/logger';
import { createInjector } from './utils/services';

process.on('uncaughtException', error => {
process.on('uncaughtException', (error: Error) => {
Logger.fatal({
msg: 'Uncaught Exception in background process!',
error: error,
});

Logger.trace({
error: error.stack
});

// exit the application safely
// FIXME: Does not actually quit app
app.exit(1);

// end the process
Expand All @@ -50,7 +55,7 @@ process.on('unhandledRejection', (reason, promise) => {
}

// Standard scheme must be registered before the app is ready
protocol.registerStandardSchemes(['app'], { secure: true });
// protocol.registerStandardSchemes(['app'], { secure: true });

/**
* global reference of the main window.
Expand Down Expand Up @@ -100,7 +105,7 @@ process.on('unhandledRejection', (reason, promise) => {
]
});

const appSettings = await io.loadApplicationSettingsFromFile(store);
const appSettings = await io.loadApplicationSettingsFromFile(store, process.argv[1]);
await io.loadSettingsFromFileToStore(store);

// Setup the Keybiding Functions
Expand Down Expand Up @@ -145,8 +150,8 @@ process.on('unhandledRejection', (reason, promise) => {
});

function createMainWindow() {
const loadedBrowserWindowOptions = appSettings.window;
const browserWindowOptions = merge({}, applicationSettingsDefaults.window, loadedBrowserWindowOptions);
const loadedBrowserWindowOptions = appSettings.windowOptions;
const browserWindowOptions = merge({}, applicationSettingsDefaults.windowOptions, loadedBrowserWindowOptions);

const window = new BrowserWindow(browserWindowOptions);

Expand Down
7 changes: 5 additions & 2 deletions src/common/application-settings-defaults.ts
@@ -1,7 +1,7 @@
import { ApplicationSettings } from './interfaces/application-settings';

export const applicationSettingsDefaults: ApplicationSettings = {
window: {
windowOptions: {
width: 800,
height: 600,
useContentSize: true,
Expand All @@ -11,6 +11,9 @@ export const applicationSettingsDefaults: ApplicationSettings = {
maximizable: false,
minWidth: 240,
minHeight: 60,
center: true
center: true,
webPreferences: {
nodeIntegration: true
}
}
};
2 changes: 1 addition & 1 deletion src/common/interfaces/application-settings.ts
Expand Up @@ -2,7 +2,7 @@ import { BrowserWindowConstructorOptions } from 'electron';
import { ActionKeybinding } from './keybindings';

export interface ApplicationSettings {
window: BrowserWindowConstructorOptions;
windowOptions: BrowserWindowConstructorOptions;
lastOpenedSplitsFile?: string;
keybindings?: ActionKeybinding[];
}
16 changes: 0 additions & 16 deletions src/common/interfaces/segment.ts
@@ -1,27 +1,11 @@
import * as SegmentSchema from '../../schemas/segment.schema.json';
import { createValidator, validate } from '../../utils/schemas';
import { asCleanNumber } from '../../utils/converters';

const validatorFunction = createValidator(SegmentSchema);

export function isSegment(data: any): data is Segment {
// Manual check until #37 is fixed
return data != null &&
typeof data === 'object' &&
typeof data.name === 'string' &&
typeof data.id === 'string' &&
/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/.test(data.id);
}

export function getFinalTime(time: DetailedTime): number {
return time == null ? 0 : Math.max(
Math.max(asCleanNumber(time.rawTime), 0) - Math.max(asCleanNumber(time.pauseTime), 0),
0);
}

export { SegmentSchema };
export { validatorFunction as SegmentValidator };

/**
* Defines a single Segment in a Split.
* Contains all basic information need to calculate
Expand Down
13 changes: 1 addition & 12 deletions src/common/interfaces/splits.ts
@@ -1,16 +1,5 @@
import * as SplitsSchema from '../../schemas/splits.schema.json';
import { GameInfoState } from '../../store/states/game-info.state.js';
import { createValidator, validate } from '../../utils/schemas';
import { Segment, TimingMethod } from './segment';

const validatorFunction = createValidator(SplitsSchema);

export function isSplits(data: any): data is Splits {
return validate(data, validatorFunction);
}

export { SplitsSchema };
export { validatorFunction as SplitsValidator };
import { GameInfoState } from '../../store/states/game-info.state';

export interface Splits {
segments: Segment[];
Expand Down
2 changes: 1 addition & 1 deletion src/schemas/detailed-time.schema.json
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://splitterino.prefix.moe/detailed-time.schema.json",
"$id": "detailed-time",
"title": "Detailed Time",
"description": "Format in which times can easily be represented and stored",
"type": "object",
Expand Down
8 changes: 3 additions & 5 deletions src/schemas/segment-time.schema.json
@@ -1,19 +1,17 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://splitterino.prefix.moe/segment-time.schema.json",
"$id": "segment-time",
"title": "Segment Time",
"description": "Format for detailed times with multiple timing methods",
"type": "object",
"properties": {
"igt": {
"description": "The detailed time of a Segment for IGT",
"type": "object",
"$ref": "http://splitterino.prefix.moe/detailed-time.schema.json"
"$ref": "detailed-time.schema.json"
},
"rta": {
"description": "The detailed time of a Segment for RTA",
"type": "object",
"$ref": "http://splitterino.prefix.moe/detailed-time.schema.json"
"$ref": "detailed-time.schema.json"
}
}
}
8 changes: 3 additions & 5 deletions src/schemas/segment.schema.json
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"id": "http://splitterino.prefix.moe/segment.schema.json",
"$id": "segment",
"title": "Segment",
"description": "Describes a single Segment",
"type": "object",
Expand All @@ -17,13 +17,11 @@
},
"personalBest": {
"description": "The time of the personal best in milliseconds",
"type": "object",
"$ref": "http://splitterino.prefix.moe/segment-time.schema.json"
"$ref": "segment-time.schema.json"
},
"overallBest": {
"description": "The time of the overall best in milliseconds",
"type": "object",
"$ref": "http://splitterino.prefix.moe/segment-time.schema.json"
"$ref": "segment-time.schema.json"
},
"passed": {
"description": "If the Segment has been passed successfully",
Expand Down
14 changes: 7 additions & 7 deletions src/schemas/splits.schema.json
@@ -1,32 +1,32 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://splitterino.prefix.moe/splits.schema.json",
"$id": "splits",
"title": "Splits",
"description": "Format in which splits are getting saved to file or should be transmitted",
"type": "object",
"required": ["game", "timing", "segments"],
"properties": {
"game": {
"description": "The Game Information about this run",
"$ref": "http://splitterino.prefix.moe/game-info.schema.json"
"$ref": "game-info.schema.json"
},
"startDelay": {
"description": "The delay of how much time the timer should wait when starting a new run in milliseconds",
"type": "integer",
"minimum": 0
},
"timing": {
"description": "The timing-method which is used for the splits",
"$ref": "http://splitterino.prefix.moe/timing-method.schema.json"
},
"segments": {
"description": "An array of segments which are associated to these splits",
"type": "array",
"minItems": 0,
"uniqueItems": true,
"items": {
"$ref": "http://splitterino.prefix.moe/segment.schema.json"
"$ref": "segment.schema.json"
}
},
"timing": {
"description": "The timing-method which is used for the splits",
"$ref": "timing-method.schema.json"
}
}
}
2 changes: 1 addition & 1 deletion src/schemas/timing-method.schema.json
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://splitterino.prefix.moe/timing-method.schema.json",
"$id": "timing-method",
"title": "Timing Method",
"description": "Timing methods which can be used for segment times",
"type": "string",
Expand Down
33 changes: 23 additions & 10 deletions src/services/io.service.ts
Expand Up @@ -7,7 +7,8 @@ import { Store } from 'vuex';

import { ApplicationSettings } from '../common/interfaces/application-settings';
import { ELECTRON_INTERFACE_TOKEN, ElectronInterface } from '../common/interfaces/electron';
import { isSplits, Splits } from '../common/interfaces/splits';
import { Splits } from '../common/interfaces/splits';
import { VALIDATOR_SERVICE_TOKEN, ValidatorService } from '../services/validator.service';
import {
ACTION_SET_CATEGORY,
ACTION_SET_GAME_NAME,
Expand All @@ -24,9 +25,15 @@ import { Logger } from '../utils/logger';

@Injectable
export class IOService {
constructor(@Inject(ELECTRON_INTERFACE_TOKEN) protected electron: ElectronInterface) { }
constructor(
@Inject(ELECTRON_INTERFACE_TOKEN) protected electron: ElectronInterface,
@Inject(VALIDATOR_SERVICE_TOKEN) protected validator: ValidatorService
) {
const isDevelopment = process.env.NODE_ENV !== 'production';
this.assetDir = join(this.electron.getAppPath(), isDevelopment ? 'ressources' : '..');
}

protected readonly assetDir = join(this.electron.getAppPath(), 'resources');
protected readonly assetDir;
protected readonly appSettingsFileName = 'application-settings.json';
protected readonly settingsFileName = 'settings.json';

Expand All @@ -46,8 +53,9 @@ export class IOService {
file: filePath,
});

let content: string = null;
try {
return readFileSync(filePath, { encoding: 'utf8' });
content = readFileSync(filePath, { encoding: 'utf8' });
} catch (e) {
Logger.error({
msg: 'Error loading file',
Expand All @@ -56,7 +64,7 @@ export class IOService {
});
}

return null;
return content;
}

public saveFile(path: string, data: string, basePath: string = this.assetDir): boolean {
Expand Down Expand Up @@ -152,7 +160,7 @@ export class IOService {
});
const loaded: { splits: Splits } = this.loadJSONFromFile(filePath, '');

if (loaded == null || typeof loaded !== 'object' || !isSplits(loaded.splits)) {
if (loaded == null || typeof loaded !== 'object' || !this.validator.isSplits(loaded.splits)) {
Logger.error({
msg: 'The loaded splits are not valid Splits!',
file: filePath,
Expand Down Expand Up @@ -288,16 +296,21 @@ export class IOService {
* Loads application settings object from file if it exists
* @param store Vuex store instance
*/
public async loadApplicationSettingsFromFile(store: Store<RootState>): Promise<ApplicationSettings> {
public async loadApplicationSettingsFromFile(
store: Store<RootState>,
splitsFile: string
): Promise<ApplicationSettings> {
const appSettings = this.loadJSONFromFile(this.appSettingsFileName) as ApplicationSettings;

if (appSettings != null && typeof appSettings === 'object') {
if (splitsFile != null && typeof splitsFile === 'string') {
await this.loadSplitsFromFileToStore(store, splitsFile);
} else if (appSettings != null && typeof appSettings === 'object') {
if (typeof appSettings.lastOpenedSplitsFile === 'string') {
await this.loadSplitsFromFileToStore(store, appSettings.lastOpenedSplitsFile);
}
}

return appSettings || { window: {} };
return appSettings || { windowOptions: {} };
}

/**
Expand All @@ -312,7 +325,7 @@ export class IOService {
const keybindings = store.state.splitterino.keybindings.bindings;

const newAppSettings: ApplicationSettings = {
window: {
windowOptions: {
width: windowSize[0],
height: windowSize[1],
x: windowPos[0],
Expand Down

0 comments on commit 832cd5c

Please sign in to comment.