Custom colors!
This commit is contained in:
parent
ce573865f6
commit
68bda87253
9 changed files with 269 additions and 136 deletions
36
package-lock.json
generated
36
package-lock.json
generated
|
@ -14,9 +14,11 @@
|
|||
"electron-squirrel-startup": "^1.0.0",
|
||||
"elite-matrix": "^1.0.0",
|
||||
"glob": "^10.2.2",
|
||||
"ini": "^4.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"reverse-line-reader": "^0.2.6",
|
||||
"tail": "^2.2.6"
|
||||
"tail": "^2.2.6",
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "^6.1.1",
|
||||
|
@ -3796,6 +3798,12 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/global-prefix/node_modules/ini": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/global-prefix/node_modules/which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
|
@ -4075,10 +4083,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||
"dev": true
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-4.1.0.tgz",
|
||||
"integrity": "sha512-HLR38RSF2iulAzc3I/sma4CoYxQP844rPYCNfzGDOHqa/YqVlwuuZgBx6M50/X8dKgzk0cm1qRg3+47mK2N+cQ==",
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/interpret": {
|
||||
"version": "3.1.1",
|
||||
|
@ -5982,6 +5992,11 @@
|
|||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz",
|
||||
|
@ -6951,6 +6966,17 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml-js": {
|
||||
"version": "1.6.11",
|
||||
"resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
|
||||
"integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
|
||||
"dependencies": {
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"bin": {
|
||||
"xml-js": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "15.1.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
|
||||
|
|
|
@ -45,8 +45,10 @@
|
|||
"electron-squirrel-startup": "^1.0.0",
|
||||
"elite-matrix": "^1.0.0",
|
||||
"glob": "^10.2.2",
|
||||
"ini": "^4.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"reverse-line-reader": "^0.2.6",
|
||||
"tail": "^2.2.6"
|
||||
"tail": "^2.2.6",
|
||||
"xml-js": "^1.6.11"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,9 +45,9 @@
|
|||
</div>
|
||||
|
||||
<div class="row ms-1 me-1">
|
||||
<div class="col col-form-label system charted">
|
||||
<label class="col col-form-label system charted">
|
||||
Where to get RGB matrix:
|
||||
</div>
|
||||
</label>
|
||||
<div class="col-2 system charted p-0 text-center">
|
||||
<button type="button" class="btn" id="matrixBtn">Select File</button>
|
||||
<input type="hidden" id="matrixFile" name="matrixFile">
|
||||
|
|
|
@ -98,7 +98,7 @@ div.charted b.inactive {
|
|||
}
|
||||
|
||||
.highlighted {
|
||||
color: var(--secondary-dark);
|
||||
color: var(--background);
|
||||
background: var(--main);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
import type { Tail as TailType } from 'tail'
|
||||
import type { autoScan, completeFsdJump, detailedScan, journalEntry, navRoute, planetScan } from "../@types/journalLines"
|
||||
import type { Tail as TailType } from 'tail';
|
||||
import type { autoScan, completeFsdJump, detailedScan, journalEntry, navRoute, planetScan } from "../@types/journalLines";
|
||||
|
||||
const EventEmitter = require('node:events')
|
||||
import * as _ from 'lodash-es'
|
||||
const path = require('node:path')
|
||||
const { readFile } = require('node:fs/promises')
|
||||
const reverseLineReader = require('reverse-line-reader')
|
||||
const Tail = require('tail').Tail
|
||||
const EventEmitter = require('node:events');
|
||||
import * as _ from 'lodash-es';
|
||||
const path = require('node:path');
|
||||
const { readFile } = require('node:fs/promises');
|
||||
const reverseLineReader = require('reverse-line-reader');
|
||||
const Tail = require('tail').Tail;
|
||||
|
||||
import { System } from "./System"
|
||||
import { Log } from "./Log"
|
||||
import { Body } from "./Body"
|
||||
import { System } from "./System";
|
||||
import { Log } from "./Log";
|
||||
import { Body } from "./Body";
|
||||
|
||||
|
||||
export class Journal extends EventEmitter {
|
||||
#path: string
|
||||
testing: string
|
||||
location: System
|
||||
navRoute: System[]
|
||||
#path: string;
|
||||
testing: string;
|
||||
location: System;
|
||||
navRoute: System[];
|
||||
|
||||
constructor(journalPath: string) {
|
||||
super()
|
||||
super();
|
||||
|
||||
this.#path = journalPath
|
||||
this.location = new System()
|
||||
this.navRoute = []
|
||||
this.#path = journalPath;
|
||||
this.location = new System();
|
||||
this.navRoute = [];
|
||||
|
||||
// Start ReverseLineReader chain here.
|
||||
Log.write(`Journal initialized. Attempting to find current location.`)
|
||||
this.#getLastFsdJump()
|
||||
Log.write(`Journal initialized. Attempting to find current location.`);
|
||||
this.#getLastFsdJump();
|
||||
// -> IF no FSD Jump: this.#getLastLocation()
|
||||
// --> this.#getScannedBodies()
|
||||
|
||||
this.testing = this.#path
|
||||
this.testing = this.#path;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- #getLastFsdJump ---- */
|
||||
|
@ -42,22 +42,23 @@ export class Journal extends EventEmitter {
|
|||
#getLastFsdJump(): void {
|
||||
reverseLineReader.eachLine(this.#path, (raw: string) => {
|
||||
if (raw) { //skip blank line at end of file
|
||||
const line: journalEntry = JSON.parse(raw)
|
||||
const line: journalEntry = JSON.parse(raw);
|
||||
|
||||
if (line.event === 'FSDJump') {
|
||||
this.location = new System((line as completeFsdJump))
|
||||
Log.write(`Current location set to ${this.location.name}.`)
|
||||
this.emit('ENTERED_NEW_SYSTEM')
|
||||
return false
|
||||
this.location = new System((line as completeFsdJump));
|
||||
Log.write(`Current location set to ${this.location.name}.`);
|
||||
this.emit('ENTERED_NEW_SYSTEM');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
if (this.location.name === 'Unknown') {
|
||||
Log.write('Unable to find last hyperspace jump. Searching for last known location.')
|
||||
this.#getLastLocation()
|
||||
Log
|
||||
.write('Unable to find last hyperspace jump. Searching for last known location.');
|
||||
this.#getLastLocation();
|
||||
} else {
|
||||
Log.write('Attempting to find scanned bodies in current system.')
|
||||
this.#getScannedBodies()
|
||||
Log.write('Attempting to find scanned bodies in current system.');
|
||||
this.#getScannedBodies();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -69,27 +70,27 @@ export class Journal extends EventEmitter {
|
|||
reverseLineReader.eachLine(this.#path, (raw: string, last: boolean) => {
|
||||
// Extra check just to be sure.
|
||||
if (this.location.name !== 'Unknown') {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
if (raw) {
|
||||
const line: journalEntry = JSON.parse(raw)
|
||||
const line: journalEntry = JSON.parse(raw);
|
||||
|
||||
if (line.event === 'Location') {
|
||||
this.location = new System((line as completeFsdJump))
|
||||
Log.write(`Current location set to ${this.location.name}.`)
|
||||
this.emit('ENTERED_NEW_SYSTEM')
|
||||
return false
|
||||
this.location = new System((line as completeFsdJump));
|
||||
Log.write(`Current location set to ${this.location.name}.`);
|
||||
this.emit('ENTERED_NEW_SYSTEM');
|
||||
return false;
|
||||
|
||||
} else if (last) {
|
||||
Log.write('WARNING: Unable to find last known location.')
|
||||
return false
|
||||
Log.write('WARNING: Unable to find last known location.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
if (this.location.name !== 'Unknown') {
|
||||
Log.write('Attempting to find scanned bodies in current system.')
|
||||
this.#getScannedBodies()
|
||||
Log.write('Attempting to find scanned bodies in current system.');
|
||||
this.#getScannedBodies();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -102,38 +103,38 @@ export class Journal extends EventEmitter {
|
|||
|
||||
reverseLineReader.eachLine(this.#path, (raw: string) => {
|
||||
if (raw) {
|
||||
const line: journalEntry = JSON.parse(raw)
|
||||
const line: journalEntry = JSON.parse(raw);
|
||||
|
||||
// Check if previous line was ScanType = Detailed, and handle that.
|
||||
if (dssLine) {
|
||||
if (line.event === 'SAAScanComplete') {
|
||||
// This was a DSS, so add to list with DSS flag set to true.
|
||||
this.location.bodies.push(new Body(dssLine, true))
|
||||
this.location.bodies.push(new Body(dssLine, true));
|
||||
} else {
|
||||
// Else, check that the body hasn't already been added (by a DSS scan line).
|
||||
const dupChecker = {'BodyName': dssLine.BodyName, 'BodyID': dssLine.BodyID}
|
||||
const r = _.find(this.location.bodies, dupChecker)
|
||||
const dupChecker = {'BodyName': dssLine.BodyName, 'BodyID': dssLine.BodyID};
|
||||
const r = _.find(this.location.bodies, dupChecker);
|
||||
|
||||
if (r === undefined) {
|
||||
// Body was not already logged, so add to list.
|
||||
this.location.bodies.push(new Body(dssLine))
|
||||
this.location.bodies.push(new Body(dssLine));
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, clear the variable.
|
||||
dssLine = null
|
||||
dssLine = null;
|
||||
}
|
||||
|
||||
// Now move on to evaluating the current line.
|
||||
if (line.event === 'Scan' && 'ScanType' in line) {
|
||||
// If ScanType = Detailed and body is not a star, save the line so we can check
|
||||
// the one immediately above for event = SAAScanComplete, which indicates this
|
||||
// If ScanType = Detailed and body is not a star, save the line so we can check
|
||||
// the one immediately above for event = SAAScanComplete, which indicates this
|
||||
// was a DSS.
|
||||
if (line.ScanType === 'Detailed' && !('StarType' in line)) {
|
||||
dssLine = (line as detailedScan)
|
||||
dssLine = (line as detailedScan);
|
||||
|
||||
} else if ('StarType' in line) { // Save stars to bodies list.
|
||||
this.location.bodies.push(new Body((line as autoScan|detailedScan)))
|
||||
this.location.bodies.push(new Body((line as autoScan|detailedScan)));
|
||||
|
||||
} else if (line.ScanType === 'AutoScan') { // Save auto/discovery scan bodies.
|
||||
// Check if planet, and then do the duplicate check (otherwise it's an
|
||||
|
@ -142,33 +143,33 @@ export class Journal extends EventEmitter {
|
|||
const dupChecker = {
|
||||
'BodyName': (line as planetScan<'AutoScan'>).BodyName,
|
||||
'BodyID': (line as planetScan<'AutoScan'>).BodyID,
|
||||
}
|
||||
const r = _.find(this.location.bodies, dupChecker)
|
||||
};
|
||||
const r = _.find(this.location.bodies, dupChecker);
|
||||
|
||||
if (r === undefined) {
|
||||
this.location.bodies.push(new Body((line as autoScan)))
|
||||
this.location.bodies.push(new Body((line as autoScan)));
|
||||
}
|
||||
|
||||
} else { // Asteroids.
|
||||
this.location.bodies.push(new Body((line as autoScan)))
|
||||
this.location.bodies.push(new Body((line as autoScan)));
|
||||
}
|
||||
}
|
||||
|
||||
} else if (line.event === 'FSDJump') {
|
||||
// Stop evaluating once we reach the beginning of current system entries.
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
if (this.location.bodies.length > 0) {
|
||||
Log.write('No scanned bodies found in current system.')
|
||||
this.emit('BUILD_BODY_LIST')
|
||||
Log.write('No scanned bodies found in current system.');
|
||||
this.emit('BUILD_BODY_LIST');
|
||||
} else {
|
||||
Log.write('Scanned bodies found.')
|
||||
Log.write('Scanned bodies found.');
|
||||
}
|
||||
|
||||
Log.write('Checking for nav route.')
|
||||
this.#getNavRoute()
|
||||
Log.write('Checking for nav route.');
|
||||
this.#getNavRoute();
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -176,40 +177,40 @@ export class Journal extends EventEmitter {
|
|||
|
||||
async #getNavRoute(): Promise<void> {
|
||||
this.navRoute = [] // Clear previous route, to catch overwritten routes.
|
||||
let routeFile: string|null = null
|
||||
let routeFile: string|null = null;
|
||||
|
||||
try {
|
||||
const filePath: string = path.dirname(this.#path) + '/NavRoute.json'
|
||||
routeFile = await readFile(filePath, {encoding: 'utf8'})
|
||||
const filePath: string = path.dirname(this.#path) + '/NavRoute.json';
|
||||
routeFile = await readFile(filePath, {encoding: 'utf8'});
|
||||
} catch (err) {
|
||||
Log.write(`Error reading nav route file: ${err.message}.`)
|
||||
Log.write(`Error reading nav route file: ${err.message}.`);
|
||||
}
|
||||
|
||||
if (routeFile) {
|
||||
const route: navRoute = JSON.parse(routeFile)
|
||||
const route: navRoute = JSON.parse(routeFile);
|
||||
|
||||
// system -> skip
|
||||
// CURRENT -> push = true; skip
|
||||
// system -> push
|
||||
let push: boolean = false
|
||||
let push: boolean = false;
|
||||
route.Route.forEach((system) => {
|
||||
if (!push && system.SystemAddress === this.location.SystemAddress) {
|
||||
push = true
|
||||
push = true;
|
||||
}
|
||||
|
||||
if (push && system.SystemAddress !== this.location.SystemAddress) {
|
||||
this.navRoute.push(new System(system))
|
||||
this.navRoute.push(new System(system));
|
||||
}
|
||||
})
|
||||
|
||||
if (this.navRoute.length > 0) {
|
||||
Log.write('Nav route set.')
|
||||
Log.write('Nav route set.');
|
||||
} else {
|
||||
Log.write('No nav route found.')
|
||||
Log.write('No nav route found.');
|
||||
}
|
||||
|
||||
// Call this no matter what, so that cleared routes are properly dealt with.
|
||||
this.emit('SET_NAV_ROUTE')
|
||||
this.emit('SET_NAV_ROUTE');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,63 +218,63 @@ export class Journal extends EventEmitter {
|
|||
|
||||
// Watch the journal for changes.
|
||||
watch(): void {
|
||||
const tail: TailType = new Tail(this.#path, {useWatchFile: true})
|
||||
const tail: TailType = new Tail(this.#path, {useWatchFile: true});
|
||||
|
||||
Log.write(`Watching ${path.basename(this.#path)}...`)
|
||||
Log.write(`Watching ${path.basename(this.#path)}...`);
|
||||
|
||||
tail.on('line', (data) => data ? this.#parseLine(data) : undefined)
|
||||
tail.on('error', (err) => Log.write(`Tail error in Journal.watch(): ${err}`))
|
||||
tail.on('line', (data) => data ? this.#parseLine(data) : undefined);
|
||||
tail.on('error', (err) => Log.write(`Tail error in Journal.watch(): ${err}`));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ #parseLine() ---- */
|
||||
|
||||
// Parse and handle journal lines.
|
||||
#parseLine(raw: string) {
|
||||
const line: journalEntry = JSON.parse(raw)
|
||||
let dssFlag: boolean = false
|
||||
const line: journalEntry = JSON.parse(raw);
|
||||
let dssFlag: boolean = false;
|
||||
|
||||
switch (line.event) {
|
||||
// Hyperspace jump started (3.. 2.. 1..)
|
||||
case 'StartJump': {
|
||||
if ('JumpType' in line && line.JumpType === 'Hyperspace') {
|
||||
this.emit('ENTERING_WITCH_SPACE')
|
||||
this.emit('ENTERING_WITCH_SPACE');
|
||||
}
|
||||
break
|
||||
break;
|
||||
}
|
||||
|
||||
// CMDR jumped to new system, so update current location.
|
||||
case 'FSDJump': {
|
||||
this.#handleFsdJump((line as completeFsdJump))
|
||||
break
|
||||
this.#handleFsdJump((line as completeFsdJump));
|
||||
break;
|
||||
}
|
||||
|
||||
// CMDR completed DSS scan, so set flag for when next line processes and we want to
|
||||
// figure out what kind of scan occurred.
|
||||
case 'SAAScanComplete': {
|
||||
dssFlag = true
|
||||
break
|
||||
dssFlag = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// A scan occurred, so let's hand that info off to the appropriate function and then
|
||||
// reset the DSS flag.
|
||||
case 'Scan': {
|
||||
this.#handleScanLine((line as autoScan|detailedScan), dssFlag)
|
||||
dssFlag = false
|
||||
break
|
||||
this.#handleScanLine((line as autoScan|detailedScan), dssFlag);
|
||||
dssFlag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// CMDR set a new nav route.
|
||||
case 'NavRoute': {
|
||||
this.#getNavRoute()
|
||||
break
|
||||
this.#getNavRoute();
|
||||
break;
|
||||
}
|
||||
|
||||
// CMDR cleared the nav route.
|
||||
case 'NavRouteClear': {
|
||||
this.navRoute = []
|
||||
Log.write('Nav route cleared.')
|
||||
this.emit('SET_NAV_ROUTE')
|
||||
break
|
||||
this.navRoute = [];
|
||||
Log.write('Nav route cleared.');
|
||||
this.emit('SET_NAV_ROUTE');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,49 +282,49 @@ export class Journal extends EventEmitter {
|
|||
/* ---------------------------------------------------------------------- #handleFsdJump ---- */
|
||||
|
||||
#handleFsdJump(line: completeFsdJump): void {
|
||||
this.location = new System(line)
|
||||
Log.write(`FSD Jump detected, current location updated to ${this.location.name}.`)
|
||||
this.location = new System(line);
|
||||
Log.write(`FSD Jump detected, current location updated to ${this.location.name}.`);
|
||||
|
||||
if (this.navRoute.length > 0) {
|
||||
_.remove(this.navRoute, (system) => {
|
||||
return system.SystemAddress === this.location.SystemAddress
|
||||
return system.SystemAddress === this.location.SystemAddress;
|
||||
})
|
||||
}
|
||||
|
||||
this.emit('ENTERED_NEW_SYSTEM')
|
||||
this.emit('ENTERED_NEW_SYSTEM');
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- #handleScanLine ---- */
|
||||
|
||||
#handleScanLine(line: autoScan|detailedScan, DSS: boolean = false) {
|
||||
const dupChecker = {'BodyName': line.BodyName, 'BodyID': line.BodyID}
|
||||
let body: Body|null = null
|
||||
const dupChecker = {'BodyName': line.BodyName, 'BodyID': line.BodyID};
|
||||
let body: Body|null = null;
|
||||
|
||||
// If it's a DSS scan, then we should have already added the body to the list. But we'll
|
||||
// check to make sure.
|
||||
if (DSS) {
|
||||
// Using findIndex() rather than find() so we can edit the body if found.
|
||||
const bodyIndex: number = _.findIndex(this.location.bodies, dupChecker)
|
||||
const bodyIndex: number = _.findIndex(this.location.bodies, dupChecker);
|
||||
|
||||
if (bodyIndex > -1) { // Body was found in list, so simply toggle the DSS flag.
|
||||
this.location.bodies[bodyIndex].DSSDone = true
|
||||
this.location.bodies[bodyIndex].DSSDone = true;
|
||||
|
||||
} else { // Body was missed on initial journal scan, so add it to the list.
|
||||
body = new Body(line, true)
|
||||
this.location.bodies.push(body)
|
||||
body = new Body(line, true);
|
||||
this.location.bodies.push(body);
|
||||
}
|
||||
|
||||
} else { // Otherwise it's an FSS or auto scan, and needs to be added to the list.
|
||||
// Probably overkill, but do a duplicate check just in case.
|
||||
const r = _.find(this.location.bodies, dupChecker)
|
||||
const r = _.find(this.location.bodies, dupChecker);
|
||||
|
||||
if (r === undefined) {
|
||||
body = new Body(line)
|
||||
this.location.bodies.push(body)
|
||||
body = new Body(line);
|
||||
this.location.bodies.push(body);
|
||||
}
|
||||
}
|
||||
|
||||
Log.write(`Scan detected. Body: ${line.BodyName}.`)
|
||||
this.emit('BODY_SCANNED', body, DSS)
|
||||
Log.write(`Scan detected. Body: ${line.BodyName}.`);
|
||||
this.emit('BODY_SCANNED', body, DSS);
|
||||
}
|
||||
}
|
|
@ -1,17 +1,22 @@
|
|||
import { EliteMatrix } from "elite-matrix";
|
||||
const EventEmitter = require('node:events');
|
||||
const fs = require('node:fs/promises');
|
||||
const { statSync, writeFileSync, readFileSync } = require('node:fs');
|
||||
const ini = require('ini');
|
||||
const os = require('node:os');
|
||||
const path = require('node:path');
|
||||
const { setTimeout } = require('node:timers/promises');
|
||||
const xmlJS = require('xml-js');
|
||||
|
||||
import { EliteMatrix } from "elite-matrix";
|
||||
import { Log } from "./Log";
|
||||
|
||||
interface settingsFile {
|
||||
minValue: number,
|
||||
maxDistance: number,
|
||||
matrixFile: string,
|
||||
}
|
||||
|
||||
export class Settings {
|
||||
export class Settings extends EventEmitter {
|
||||
static #instance: Settings;
|
||||
|
||||
#file: string;
|
||||
|
@ -20,10 +25,12 @@ export class Settings {
|
|||
minValue: number;
|
||||
maxDistance: number;
|
||||
|
||||
#matrixFile?: string;
|
||||
#matrixFile: null|string;
|
||||
matrix?: EliteMatrix;
|
||||
|
||||
private constructor(isPackaged: boolean) {
|
||||
super();
|
||||
|
||||
if (!isPackaged && os.platform() === 'linux') {
|
||||
this.#file = '/mnt/c/Users/marle/ed-safari-settings.json';
|
||||
} else {
|
||||
|
@ -39,6 +46,7 @@ export class Settings {
|
|||
const contents: string = JSON.stringify({
|
||||
minValue: 500000,
|
||||
maxDistance: 10000,
|
||||
matrixFile: '',
|
||||
});
|
||||
|
||||
writeFileSync(this.#file, contents);
|
||||
|
@ -49,8 +57,12 @@ export class Settings {
|
|||
const contents: settingsFile = JSON.parse(readFileSync(this.#file, { encoding: 'utf8' }));
|
||||
this.minValue = contents.minValue;
|
||||
this.maxDistance = contents.maxDistance;
|
||||
|
||||
this.#matrixFile = contents.matrixFile;
|
||||
this.#writing = false;
|
||||
|
||||
if (this.#matrixFile) {
|
||||
this.#setMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
static get(isPackaged: boolean = false): Settings {
|
||||
|
@ -74,6 +86,10 @@ export class Settings {
|
|||
this.#writing = false;
|
||||
|
||||
Log.write('Settings saved!');
|
||||
|
||||
// Update Settings props.
|
||||
await this.#read();
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
Log.write(err);
|
||||
|
@ -83,4 +99,73 @@ export class Settings {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- #read ---- */
|
||||
|
||||
async #read(): Promise<boolean> {
|
||||
try {
|
||||
const file: string = await fs.readFile(this.#file, { encoding: 'utf8' });
|
||||
const contents: settingsFile = JSON.parse(file);
|
||||
|
||||
this.minValue = contents.minValue;
|
||||
this.maxDistance = contents.maxDistance;
|
||||
this.#matrixFile = contents.matrixFile;
|
||||
|
||||
if (this.#matrixFile) {
|
||||
await this.#setMatrix();
|
||||
Log.write('Custom colors set!');
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
Log.write(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- #setMatrix ---- */
|
||||
|
||||
async #setMatrix(): Promise<void> {
|
||||
const file: string = await fs.readFile(this.#matrixFile, { encoding: 'utf8' });
|
||||
|
||||
let matrixRed: [number, number, number];
|
||||
let matrixGreen: [number, number, number];
|
||||
let matrixBlue: [number, number, number];
|
||||
|
||||
if (path.basename(this.#matrixFile) === 'GraphicsConfiguration.xml') {
|
||||
const options = {
|
||||
trim: true,
|
||||
ignoreDeclaration: true,
|
||||
ignoreAttributes: true,
|
||||
compact: true,
|
||||
textKey: '$'
|
||||
};
|
||||
const contents = xmlJS.xml2js(file, options);
|
||||
|
||||
let matrix = [
|
||||
contents.GraphicsConfig.GUIColour.Default.MatrixRed.$,
|
||||
contents.GraphicsConfig.GUIColour.Default.MatrixGreen.$,
|
||||
contents.GraphicsConfig.GUIColour.Default.MatrixBlue.$,
|
||||
];
|
||||
|
||||
matrix = matrix.map(v => v.replace(/\s/g, '').split(','));
|
||||
|
||||
matrixRed = matrix[0].length === 3 ? matrix[0] : [1,0,0];
|
||||
matrixGreen = matrix[1].length === 3 ? matrix[1] : [0,1,0];
|
||||
matrixBlue = matrix[2].length === 3 ? matrix[2] : [0,0,1];
|
||||
|
||||
this.matrix = new EliteMatrix(matrixRed, matrixGreen, matrixBlue);
|
||||
|
||||
} else if (path.basename(this.#matrixFile) === 'XML-Profile.ini') {
|
||||
const contents = (ini.parse(file)).constants;
|
||||
|
||||
matrixRed = [contents.x150, contents.y150, contents.z150];
|
||||
matrixGreen = [contents.x151, contents.y151, contents.z151];
|
||||
matrixBlue = [contents.x152, contents.y152, contents.z152];
|
||||
|
||||
this.matrix = new EliteMatrix(matrixRed, matrixGreen, matrixBlue);
|
||||
}
|
||||
|
||||
this.emit('CUSTOM_COLORS_SET');
|
||||
}
|
||||
}
|
|
@ -9,6 +9,17 @@ export class UI {
|
|||
return Intl.NumberFormat().format(Math.round(number));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------- setColors ---- */
|
||||
|
||||
static setColors(matrix) {
|
||||
const body = $('body');
|
||||
body.css('--main', matrix.filterColor('#F5A804'));
|
||||
body.css('--accent-dark', matrix.filterColor('#000e5f'));
|
||||
body.css('--accent-light', matrix.filterColor('#17cbd4'));
|
||||
body.css('--secondary-light', matrix.filterColor('#EAA529'));
|
||||
body.css('--secondary-dark', matrix.filterColor('#370C03'));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- enterWitchSpace ---- */
|
||||
|
||||
static enterWitchSpace() {
|
||||
|
|
|
@ -35,6 +35,12 @@ if (!journal) {
|
|||
safari.watchJournalDir();
|
||||
journal.watch();
|
||||
|
||||
/* ------------------------------------------------------------------------------ set colors ---- */
|
||||
|
||||
settings.on('CUSTOM_COLORS_SET', () => {
|
||||
UI.setColors(settings.matrix);
|
||||
});
|
||||
|
||||
/* -------------------------------------------------------------------- close window handler ---- */
|
||||
|
||||
$('#closeBtn').on('click', () => {
|
||||
|
@ -129,18 +135,4 @@ edsm.on('SYSTEM_APPRAISED', (system) => {
|
|||
if (systemRow.length > 0) {
|
||||
UI.setValue(systemRow, system.estimatedValueMapped);
|
||||
}
|
||||
});
|
||||
|
||||
// const matrixRed = [1.2, 0.05, 0.07];
|
||||
// const matrixGreen = [0.13, 1, 1.18];
|
||||
// const matrixBlue = [0.4, 1.29, 2];
|
||||
|
||||
// const matrix = new EliteMatrix(matrixRed, matrixGreen, matrixBlue);
|
||||
// const hex = matrix.filterColor('#f5a804');
|
||||
// const rgb = matrix.filterColor([245, 168, 4]);
|
||||
// console.log(`rgb(${rgb})`)
|
||||
// $('body').css('--main', `rgb(${rgb})`);
|
||||
// $('body').css('--accent-dark', matrix.filterColor('#000e5f'));
|
||||
// $('body').css('--accent-light', matrix.filterColor('#17cbd4'));
|
||||
// $('body').css('--secondary-light', matrix.filterColor('#EAA529'));
|
||||
// $('body').css('--secondary-dark', matrix.filterColor('#370C03'));
|
||||
});
|
|
@ -5,12 +5,23 @@ import './assets/ldom.min';
|
|||
|
||||
const { ipcRenderer } = require('electron');
|
||||
const { setTimeout } = require('node:timers/promises');
|
||||
const { basename } = require('node:path');
|
||||
|
||||
import { Settings } from './models/Settings';
|
||||
import { UI } from './models/UI';
|
||||
|
||||
const settings = Settings.get();
|
||||
|
||||
if (settings.matrix) {
|
||||
UI.setColors(settings.matrix);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------ set colors ---- */
|
||||
|
||||
settings.on('CUSTOM_COLORS_SET', () => {
|
||||
UI.setColors(settings.matrix);
|
||||
});
|
||||
|
||||
/* -------------------------------------------------------------------- close window handler ---- */
|
||||
|
||||
$('#closeBtn').on('click', () => {
|
||||
|
@ -61,6 +72,11 @@ $('form').on('submit', async function (event) {
|
|||
errors = true;
|
||||
}
|
||||
|
||||
const fileName = basename(data.matrixFile);
|
||||
if (fileName !== 'XML-Profile.ini' || fileName !== 'GraphicsConfiguration.xml') {
|
||||
UI.addFormError('#matrixFile', 'Invalid file.');
|
||||
}
|
||||
|
||||
// TODO re-enable submit button if errors.
|
||||
|
||||
// If no errors, save.
|
||||
|
|
Loading…
Reference in a new issue