From 6b16af4b7dbc494caefb3e09cc79f97a2cd04333 Mon Sep 17 00:00:00 2001 From: Michael Hollister Date: Thu, 12 Jun 2025 11:56:44 -0500 Subject: [PATCH] Receivers: Moved Store module to common components --- receivers/common/web/Store.ts | 72 ++++++++++++++++++++++++ receivers/electron/package-lock.json | 82 +++++----------------------- receivers/electron/package.json | 1 - receivers/electron/src/Main.ts | 6 ++ receivers/electron/src/Store.ts | 35 ------------ receivers/electron/src/Updater.ts | 36 +++++++----- 6 files changed, 112 insertions(+), 120 deletions(-) create mode 100644 receivers/common/web/Store.ts delete mode 100644 receivers/electron/src/Store.ts diff --git a/receivers/common/web/Store.ts b/receivers/common/web/Store.ts new file mode 100644 index 0000000..168fd5a --- /dev/null +++ b/receivers/common/web/Store.ts @@ -0,0 +1,72 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import * as fs from 'fs'; +import { Logger, LoggerType } from 'common/Logger'; +const logger = new Logger('Store', LoggerType.BACKEND); + +export interface NetworkSettings { + ignoreCertificateErrors: boolean, + deviceName: string, +} + +export interface UISettings { + mainWindowBackground: string, +} + +export interface UpdaterSettings { + channel: string, + checkForUpdatesOnStart: boolean, +} + +export interface Settings { + storeVersion: number, + network: NetworkSettings, + ui: UISettings, + updater: UpdaterSettings, +} + +export class Store { + private static instance: Store = null; + private static storeVersion = 1; + private static path?: string = null; + public static settings: Settings = null; + + constructor(path?: string) { + if (!Store.instance) { + // @ts-ignore + if (TARGET === 'electron') { + Store.path = path; + Store.settings = JSON.parse(fs.readFileSync(path, { encoding: 'utf8', flag: 'r' })) as Settings; + logger.info('Read settings file:', Store.settings); + + if (Store.settings === undefined) { + Store.settings.storeVersion = Store.storeVersion; + fs.writeFileSync(Store.path, JSON.stringify(Store.settings)); + } + + // @ts-ignore + } else if (TARGET === 'webOS') { + // todo + } else { + // @ts-ignore + logger.warn(`Attempting to initialize Store on unsupported target: ${TARGET}`); + } + + Store.instance = this; + } + } + + public static saveSettings() { + // @ts-ignore + if (TARGET === 'electron') { + logger.info('Saving settings file:', Store.settings); + fs.writeFileSync(Store.path, JSON.stringify(Store.settings)); + + // @ts-ignore + } else if (TARGET === 'webOS') { + // todo + } else { + // @ts-ignore + logger.warn(`Attempting to initialize Store on unsupported target: ${TARGET}`); + } + } +} diff --git a/receivers/electron/package-lock.json b/receivers/electron/package-lock.json index a063821..5901ebb 100644 --- a/receivers/electron/package-lock.json +++ b/receivers/electron/package-lock.json @@ -12,7 +12,6 @@ "@vscode/sudo-prompt": "^9.3.1", "bufferutil": "^4.0.8", "dashjs": "^4.7.4", - "electron-json-storage": "^4.6.0", "extract-zip": "^2.0.1", "follow-redirects": "^1.15.9", "hls.js": "^1.5.15", @@ -3639,6 +3638,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, "node_modules/base32-encode": { @@ -3755,6 +3755,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -4455,6 +4456,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, "license": "MIT" }, "node_modules/convert-source-map": { @@ -5358,29 +5360,6 @@ "node": ">=10" } }, - "node_modules/electron-json-storage": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/electron-json-storage/-/electron-json-storage-4.6.0.tgz", - "integrity": "sha512-gAgNsnA7tEtV9LzzOnZTyVIb3cQtCva+bEBVT5pbRGU8ZSZTVKPBrTxIAYjeVfdSjyNXgfb1mr/CZrOJgeHyqg==", - "license": "MIT", - "dependencies": { - "async": "^2.0.0", - "lockfile": "^1.0.4", - "lodash": "^4.0.1", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.1", - "write-file-atomic": "^2.4.2" - } - }, - "node_modules/electron-json-storage/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "license": "MIT", - "dependencies": { - "lodash": "^4.17.14" - } - }, "node_modules/electron-to-chromium": { "version": "1.5.137", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.137.tgz", @@ -6349,6 +6328,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -6553,6 +6533,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -6996,6 +6977,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -7023,6 +7005,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -7033,6 +7016,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, "license": "ISC" }, "node_modules/ini": { @@ -8424,19 +8408,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lockfile": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", - "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", - "license": "ISC", - "dependencies": { - "signal-exit": "^3.0.2" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, "license": "MIT" }, "node_modules/lodash.get": { @@ -8867,6 +8843,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -8879,6 +8856,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8995,18 +8973,6 @@ "dev": true, "license": "ISC" }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -9515,6 +9481,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10457,19 +10424,6 @@ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "license": "MIT" }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -10802,6 +10756,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, "license": "ISC" }, "node_modules/sisteransi": { @@ -12293,17 +12248,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, - "node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "license": "ISC", - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, "node_modules/ws": { "version": "8.18.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", diff --git a/receivers/electron/package.json b/receivers/electron/package.json index a299d57..61df1c6 100644 --- a/receivers/electron/package.json +++ b/receivers/electron/package.json @@ -49,7 +49,6 @@ "@vscode/sudo-prompt": "^9.3.1", "bufferutil": "^4.0.8", "dashjs": "^4.7.4", - "electron-json-storage": "^4.6.0", "extract-zip": "^2.0.1", "follow-redirects": "^1.15.9", "hls.js": "^1.5.15", diff --git a/receivers/electron/src/Main.ts b/receivers/electron/src/Main.ts index c3bf107..5718d6a 100644 --- a/receivers/electron/src/Main.ts +++ b/receivers/electron/src/Main.ts @@ -9,6 +9,7 @@ import { ConnectionMonitor } from 'common/ConnectionMonitor'; import { Logger, LoggerType } from 'common/Logger'; import { fetchJSON } from 'common/UtilityBackend'; import { MediaCache } from 'common/MediaCache'; +import { Store } from 'common/Store'; import { Updater } from './Updater'; import * as os from 'os'; import * as path from 'path'; @@ -475,6 +476,11 @@ export class Main { }) .parseSync(); + // Using singleton classes for better compatibility running on webOS + const jsonPath = path.join(app.getPath('userData'), 'UserSettings.json'); + new Store(jsonPath); + + new Updater(); const isUpdating = Updater.isUpdating(); const fileLogType = isUpdating ? 'fileSync' : 'file'; Logger.initialize({ diff --git a/receivers/electron/src/Store.ts b/receivers/electron/src/Store.ts deleted file mode 100644 index 1dc7f76..0000000 --- a/receivers/electron/src/Store.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import storage from 'electron-json-storage'; -import { app } from 'electron'; -import { Logger, LoggerType } from 'common/Logger'; -const logger = new Logger('Store', LoggerType.BACKEND); - -export class Store { - private static storeVersion = 1; - private static userSettings = 'UserSettings'; - private static settingsCache: any = null; - - static { - storage.setDataPath(app.getPath('userData')); - Store.settingsCache = storage.getSync(Store.userSettings); - - if (Store.get('storeVersion') === null) { - Store.set('storeVersion', Store.storeVersion); - } - } - - public static get(key: string): any { - return Store.settingsCache[key] ?? null; - } - - public static set(key: string, value: any) { - Store.settingsCache[key] = value; - - logger.info(`Writing settings file: key '${key}', value ${JSON.stringify(value)}`); - storage.set(Store.userSettings, Store.settingsCache, (err) => { - if (err) { - logger.error(`Error writing user settings: ${err}`); - } - }); - } -} diff --git a/receivers/electron/src/Updater.ts b/receivers/electron/src/Updater.ts index b635383..6223e45 100644 --- a/receivers/electron/src/Updater.ts +++ b/receivers/electron/src/Updater.ts @@ -2,8 +2,8 @@ import * as fs from 'fs'; import * as path from 'path'; import * as crypto from 'crypto'; import { app } from 'electron'; -import { Store } from './Store'; import sudo from 'sudo-prompt'; +import { Store } from 'common/Store'; import { Logger, LoggerType } from 'common/Logger'; import { fetchJSON, downloadFile } from 'common/UtilityBackend'; @@ -50,6 +50,7 @@ interface UpdateConditions { } export class Updater { + private static instance: Store = null; private static readonly supportedReleasesJsonVersion = '1'; private static appPath: string = app.getAppPath(); @@ -73,22 +74,27 @@ export class Updater { public static releaseChannel = 'stable'; public static updateChannel = 'stable'; - static { - Updater.localPackageJson = JSON.parse(fs.readFileSync(path.join(Updater.appPath, './package.json'), 'utf8')); + constructor() { + if (!Updater.instance) { + Updater.localPackageJson = JSON.parse(fs.readFileSync(path.join(Updater.appPath, './package.json'), 'utf8')); - let updaterSettings = Store.get('updater'); - if (updaterSettings !== null) { - Updater.updateChannel = updaterSettings.channel === undefined ? Updater.localPackageJson.channel : updaterSettings.channel; - Updater.checkForUpdatesOnStart = updaterSettings.checkForUpdatesOnStart === undefined ? true : updaterSettings.checkForUpdatesOnStart; + let updaterSettings = Store.settings.updater; + if (updaterSettings !== null) { + Updater.updateChannel = updaterSettings.channel === undefined ? Updater.localPackageJson.channel : updaterSettings.channel; + Updater.checkForUpdatesOnStart = updaterSettings.checkForUpdatesOnStart === undefined ? true : updaterSettings.checkForUpdatesOnStart; + } + + updaterSettings = { + 'channel': Updater.updateChannel, + 'checkForUpdatesOnStart': Updater.checkForUpdatesOnStart, + } + + Updater.releaseChannel = Updater.localPackageJson.channel; + Store.settings.updater = updaterSettings; + Store.saveSettings(); + + Updater.instance = this; } - - updaterSettings = { - 'channel': Updater.updateChannel, - 'checkForUpdatesOnStart': Updater.checkForUpdatesOnStart, - } - - Updater.releaseChannel = Updater.localPackageJson.channel; - Store.set('updater', updaterSettings); } private static async applyUpdate(src: string, dst: string) {