mirror of
https://gitlab.com/futo-org/fcast.git
synced 2025-06-24 21:25:23 +00:00
Receivers: Renamed store module and added Electron option to ignore certificate errors
This commit is contained in:
parent
6b16af4b7d
commit
fa246a3f08
6 changed files with 136 additions and 85 deletions
98
receivers/common/web/Settings.ts
Normal file
98
receivers/common/web/Settings.ts
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import { Logger, LoggerType } from 'common/Logger';
|
||||||
|
const logger = new Logger('Settings', LoggerType.BACKEND);
|
||||||
|
|
||||||
|
export interface LoggerSettings {
|
||||||
|
level: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NetworkSettings {
|
||||||
|
ignoreCertificateErrors: boolean,
|
||||||
|
deviceName: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UISettings {
|
||||||
|
noMainWindow: boolean,
|
||||||
|
fullscreen: boolean,
|
||||||
|
mainWindowBackground: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdaterSettings {
|
||||||
|
channel: string,
|
||||||
|
checkForUpdatesOnStart: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Settings {
|
||||||
|
storeVersion: number,
|
||||||
|
log: LoggerSettings,
|
||||||
|
network: NetworkSettings,
|
||||||
|
ui: UISettings,
|
||||||
|
updater: UpdaterSettings,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Settings {
|
||||||
|
private static instance: Settings = null;
|
||||||
|
private static readonly version = 1;
|
||||||
|
private static path?: string = null;
|
||||||
|
public static json: Settings;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(path?: string) {
|
||||||
|
if (!Settings.instance) {
|
||||||
|
// @ts-ignore
|
||||||
|
if (TARGET === 'electron') {
|
||||||
|
Settings.path = path;
|
||||||
|
Settings.json = JSON.parse(fs.readFileSync(path, { encoding: 'utf8', flag: 'r' })) as Settings;
|
||||||
|
logger.info('Read settings file:', Settings.json);
|
||||||
|
Settings.setDefault();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
} else if (TARGET === 'webOS') {
|
||||||
|
// todo
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
logger.warn(`Attempting to initialize Settings on unsupported target: ${TARGET}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings.instance = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static setDefault() {
|
||||||
|
Settings.json.storeVersion = Settings.json.storeVersion === undefined ? Settings.version : Settings.json.storeVersion;
|
||||||
|
Settings.json.log = Settings.json.log === undefined ? {} as LoggerSettings : Settings.json.log;
|
||||||
|
Settings.json.network = Settings.json.network === undefined ? {} as NetworkSettings : Settings.json.network;
|
||||||
|
Settings.json.ui = Settings.json.ui === undefined ? {} as UISettings : Settings.json.ui;
|
||||||
|
Settings.json.updater = Settings.json.updater === undefined ? {} as UpdaterSettings : Settings.json.updater;
|
||||||
|
|
||||||
|
Settings.json.log.level = Settings.json.log.level === undefined ? 'INFO' : Settings.json.log.level;
|
||||||
|
|
||||||
|
Settings.json.network.deviceName = Settings.json.network.deviceName === undefined ? '' : Settings.json.network.deviceName;
|
||||||
|
Settings.json.network.ignoreCertificateErrors = Settings.json.network.ignoreCertificateErrors === undefined ? false : Settings.json.network.ignoreCertificateErrors;
|
||||||
|
|
||||||
|
Settings.json.ui.noMainWindow = Settings.json.ui.noMainWindow === undefined ? false : Settings.json.ui.noMainWindow;
|
||||||
|
Settings.json.ui.fullscreen = Settings.json.ui.fullscreen === undefined ? false : Settings.json.ui.fullscreen;
|
||||||
|
Settings.json.ui.mainWindowBackground = Settings.json.ui.mainWindowBackground === undefined ? '' : Settings.json.ui.mainWindowBackground;
|
||||||
|
|
||||||
|
Settings.json.updater.channel = Settings.json.updater.channel === undefined ? '' : Settings.json.updater.channel;
|
||||||
|
Settings.json.updater.checkForUpdatesOnStart = Settings.json.updater.checkForUpdatesOnStart === undefined ? true : Settings.json.updater.checkForUpdatesOnStart;
|
||||||
|
|
||||||
|
Settings.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static save() {
|
||||||
|
// @ts-ignore
|
||||||
|
if (TARGET === 'electron') {
|
||||||
|
logger.info('Saving settings file:', Settings.json);
|
||||||
|
fs.writeFileSync(Settings.path, JSON.stringify(Settings.json, null, 4));
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
} else if (TARGET === 'webOS') {
|
||||||
|
// todo
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
logger.warn(`Attempting to initialize Settings on unsupported target: ${TARGET}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,72 +0,0 @@
|
||||||
/* 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}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import { toast, ToastIcon } from 'common/components/Toast';
|
||||||
import { Logger, LoggerType } from 'common/Logger';
|
import { Logger, LoggerType } from 'common/Logger';
|
||||||
import { EventMessage } from 'common/Packets';
|
import { EventMessage } from 'common/Packets';
|
||||||
const logger = new Logger('MainWindow', LoggerType.FRONTEND);
|
const logger = new Logger('MainWindow', LoggerType.FRONTEND);
|
||||||
|
@ -34,14 +35,18 @@ if (TARGET === 'electron') {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const electronAPI = __non_webpack_require__('electron');
|
const electronAPI = __non_webpack_require__('electron');
|
||||||
|
|
||||||
electronAPI.ipcRenderer.on("device-info", (_event, value: any) => {
|
electronAPI.ipcRenderer.on('device-info', (_event, value: any) => {
|
||||||
preloadData.deviceInfo = value;
|
preloadData.deviceInfo = value;
|
||||||
})
|
})
|
||||||
electronAPI.ipcRenderer.on("event-subscribed-keys-update", (_event, value: { keyDown: Set<string>, keyUp: Set<string> }) => {
|
electronAPI.ipcRenderer.on('event-subscribed-keys-update', (_event, value: { keyDown: Set<string>, keyUp: Set<string> }) => {
|
||||||
preloadData.subscribedKeys.keyDown = value.keyDown;
|
preloadData.subscribedKeys.keyDown = value.keyDown;
|
||||||
preloadData.subscribedKeys.keyUp = value.keyUp;
|
preloadData.subscribedKeys.keyUp = value.keyUp;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
electronAPI.ipcRenderer.on('toast', (_event, message: string, icon: ToastIcon = ToastIcon.INFO, duration: number = 5000) => {
|
||||||
|
toast(message, icon, duration);
|
||||||
|
})
|
||||||
|
|
||||||
electronAPI.contextBridge.exposeInMainWorld('targetAPI', {
|
electronAPI.contextBridge.exposeInMainWorld('targetAPI', {
|
||||||
onDeviceInfo: (callback: any) => electronAPI.ipcRenderer.on('device-info', callback),
|
onDeviceInfo: (callback: any) => electronAPI.ipcRenderer.on('device-info', callback),
|
||||||
getDeviceInfo: () => preloadData.deviceInfo,
|
getDeviceInfo: () => preloadData.deviceInfo,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { PlaybackErrorMessage, PlaybackUpdateMessage, VolumeUpdateMessage, EventMessage, PlayMessage } from 'common/Packets';
|
import { PlaybackErrorMessage, PlaybackUpdateMessage, VolumeUpdateMessage, EventMessage, PlayMessage } from 'common/Packets';
|
||||||
import { Logger, LoggerType } from 'common/Logger';
|
import { Logger, LoggerType } from 'common/Logger';
|
||||||
|
import { toast, ToastIcon } from 'common/components/Toast';
|
||||||
const logger = new Logger('PlayerWindow', LoggerType.FRONTEND);
|
const logger = new Logger('PlayerWindow', LoggerType.FRONTEND);
|
||||||
|
|
||||||
// Cannot directly pass the object to the renderer for some reason...
|
// Cannot directly pass the object to the renderer for some reason...
|
||||||
|
@ -35,11 +36,15 @@ if (TARGET === 'electron') {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const electronAPI = __non_webpack_require__('electron');
|
const electronAPI = __non_webpack_require__('electron');
|
||||||
|
|
||||||
electronAPI.ipcRenderer.on("event-subscribed-keys-update", (_event, value: { keyDown: Set<string>, keyUp: Set<string> }) => {
|
electronAPI.ipcRenderer.on('event-subscribed-keys-update', (_event, value: { keyDown: Set<string>, keyUp: Set<string> }) => {
|
||||||
preloadData.subscribedKeys.keyDown = value.keyDown;
|
preloadData.subscribedKeys.keyDown = value.keyDown;
|
||||||
preloadData.subscribedKeys.keyUp = value.keyUp;
|
preloadData.subscribedKeys.keyUp = value.keyUp;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
electronAPI.ipcRenderer.on('toast', (_event, message: string, icon: ToastIcon = ToastIcon.INFO, duration: number = 5000) => {
|
||||||
|
toast(message, icon, duration);
|
||||||
|
})
|
||||||
|
|
||||||
electronAPI.contextBridge.exposeInMainWorld('targetAPI', {
|
electronAPI.contextBridge.exposeInMainWorld('targetAPI', {
|
||||||
sendPlaybackUpdate: (update: PlaybackUpdateMessage) => electronAPI.ipcRenderer.send('send-playback-update', update),
|
sendPlaybackUpdate: (update: PlaybackUpdateMessage) => electronAPI.ipcRenderer.send('send-playback-update', update),
|
||||||
sendVolumeUpdate: (update: VolumeUpdateMessage) => electronAPI.ipcRenderer.send('send-volume-update', update),
|
sendVolumeUpdate: (update: VolumeUpdateMessage) => electronAPI.ipcRenderer.send('send-volume-update', update),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { BrowserWindow, ipcMain, IpcMainEvent, nativeImage, Tray, Menu, dialog, shell } from 'electron';
|
import { BrowserWindow, ipcMain, IpcMainEvent, nativeImage, Tray, Menu, dialog, shell } from 'electron';
|
||||||
|
import { ToastIcon } from 'common/components/Toast';
|
||||||
import { Opcode, PlaybackErrorMessage, PlaybackUpdateMessage, VolumeUpdateMessage, PlayMessage, PlayUpdateMessage, EventMessage, EventType, ContentObject, ContentType, PlaylistContent, SeekMessage, SetVolumeMessage, SetSpeedMessage, SetPlaylistItemMessage } from 'common/Packets';
|
import { Opcode, PlaybackErrorMessage, PlaybackUpdateMessage, VolumeUpdateMessage, PlayMessage, PlayUpdateMessage, EventMessage, EventType, ContentObject, ContentType, PlaylistContent, SeekMessage, SetVolumeMessage, SetSpeedMessage, SetPlaylistItemMessage } from 'common/Packets';
|
||||||
import { supportedPlayerTypes } from 'common/MimeTypes';
|
import { supportedPlayerTypes } from 'common/MimeTypes';
|
||||||
import { DiscoveryService } from 'common/DiscoveryService';
|
import { DiscoveryService } from 'common/DiscoveryService';
|
||||||
|
@ -9,7 +10,7 @@ import { ConnectionMonitor } from 'common/ConnectionMonitor';
|
||||||
import { Logger, LoggerType } from 'common/Logger';
|
import { Logger, LoggerType } from 'common/Logger';
|
||||||
import { fetchJSON } from 'common/UtilityBackend';
|
import { fetchJSON } from 'common/UtilityBackend';
|
||||||
import { MediaCache } from 'common/MediaCache';
|
import { MediaCache } from 'common/MediaCache';
|
||||||
import { Store } from 'common/Store';
|
import { Settings } from 'common/Settings';
|
||||||
import { Updater } from './Updater';
|
import { Updater } from './Updater';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
@ -464,6 +465,14 @@ export class Main {
|
||||||
Main.cache.appName = app.name;
|
Main.cache.appName = app.name;
|
||||||
Main.cache.appVersion = app.getVersion();
|
Main.cache.appVersion = app.getVersion();
|
||||||
|
|
||||||
|
// Using singleton classes for better compatibility running on webOS
|
||||||
|
const jsonPath = path.join(app.getPath('userData'), 'UserSettings.json');
|
||||||
|
new Settings(jsonPath);
|
||||||
|
|
||||||
|
if (Settings.json.network.ignoreCertificateErrors) {
|
||||||
|
app.commandLine.appendSwitch('ignore-certificate-errors');
|
||||||
|
}
|
||||||
|
|
||||||
const argv = yargs(hideBin(process.argv))
|
const argv = yargs(hideBin(process.argv))
|
||||||
.version(app.getVersion())
|
.version(app.getVersion())
|
||||||
.parserConfiguration({
|
.parserConfiguration({
|
||||||
|
@ -476,10 +485,6 @@ export class Main {
|
||||||
})
|
})
|
||||||
.parseSync();
|
.parseSync();
|
||||||
|
|
||||||
// Using singleton classes for better compatibility running on webOS
|
|
||||||
const jsonPath = path.join(app.getPath('userData'), 'UserSettings.json');
|
|
||||||
new Store(jsonPath);
|
|
||||||
|
|
||||||
new Updater();
|
new Updater();
|
||||||
const isUpdating = Updater.isUpdating();
|
const isUpdating = Updater.isUpdating();
|
||||||
const fileLogType = isUpdating ? 'fileSync' : 'file';
|
const fileLogType = isUpdating ? 'fileSync' : 'file';
|
||||||
|
@ -524,6 +529,11 @@ export class Main {
|
||||||
Main.openMainWindow();
|
Main.openMainWindow();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Main.application.on('certificate-error', (_event, _webContents, url, error, certificate) => {
|
||||||
|
toast('Could not playback media (certificate error)', ToastIcon.ERROR);
|
||||||
|
logger.error('Could not playback media (certificate error):', { url: url, error: error, certificate: certificate });
|
||||||
|
});
|
||||||
Main.application.on('ready', Main.onReady);
|
Main.application.on('ready', Main.onReady);
|
||||||
Main.application.on('window-all-closed', () => { });
|
Main.application.on('window-all-closed', () => { });
|
||||||
}
|
}
|
||||||
|
@ -534,6 +544,11 @@ export class Main {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toast(message: string, icon: ToastIcon = ToastIcon.INFO, duration: number = 5000) {
|
||||||
|
Main.mainWindow?.webContents?.send('toast', message, icon, duration);
|
||||||
|
Main.playerWindow?.webContents?.send('toast', message, icon, duration);
|
||||||
|
}
|
||||||
|
|
||||||
export function getComputerName() {
|
export function getComputerName() {
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case "win32":
|
case "win32":
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as path from 'path';
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
import { app } from 'electron';
|
import { app } from 'electron';
|
||||||
import sudo from 'sudo-prompt';
|
import sudo from 'sudo-prompt';
|
||||||
import { Store } from 'common/Store';
|
import { Settings } from 'common/Settings';
|
||||||
import { Logger, LoggerType } from 'common/Logger';
|
import { Logger, LoggerType } from 'common/Logger';
|
||||||
import { fetchJSON, downloadFile } from 'common/UtilityBackend';
|
import { fetchJSON, downloadFile } from 'common/UtilityBackend';
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ interface UpdateConditions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Updater {
|
export class Updater {
|
||||||
private static instance: Store = null;
|
private static instance: Updater = null;
|
||||||
private static readonly supportedReleasesJsonVersion = '1';
|
private static readonly supportedReleasesJsonVersion = '1';
|
||||||
|
|
||||||
private static appPath: string = app.getAppPath();
|
private static appPath: string = app.getAppPath();
|
||||||
|
@ -78,7 +78,7 @@ export class Updater {
|
||||||
if (!Updater.instance) {
|
if (!Updater.instance) {
|
||||||
Updater.localPackageJson = JSON.parse(fs.readFileSync(path.join(Updater.appPath, './package.json'), 'utf8'));
|
Updater.localPackageJson = JSON.parse(fs.readFileSync(path.join(Updater.appPath, './package.json'), 'utf8'));
|
||||||
|
|
||||||
let updaterSettings = Store.settings.updater;
|
let updaterSettings = Settings.json.updater;
|
||||||
if (updaterSettings !== null) {
|
if (updaterSettings !== null) {
|
||||||
Updater.updateChannel = updaterSettings.channel === undefined ? Updater.localPackageJson.channel : updaterSettings.channel;
|
Updater.updateChannel = updaterSettings.channel === undefined ? Updater.localPackageJson.channel : updaterSettings.channel;
|
||||||
Updater.checkForUpdatesOnStart = updaterSettings.checkForUpdatesOnStart === undefined ? true : updaterSettings.checkForUpdatesOnStart;
|
Updater.checkForUpdatesOnStart = updaterSettings.checkForUpdatesOnStart === undefined ? true : updaterSettings.checkForUpdatesOnStart;
|
||||||
|
@ -90,8 +90,8 @@ export class Updater {
|
||||||
}
|
}
|
||||||
|
|
||||||
Updater.releaseChannel = Updater.localPackageJson.channel;
|
Updater.releaseChannel = Updater.localPackageJson.channel;
|
||||||
Store.settings.updater = updaterSettings;
|
Settings.json.updater = updaterSettings;
|
||||||
Store.saveSettings();
|
Settings.save();
|
||||||
|
|
||||||
Updater.instance = this;
|
Updater.instance = this;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue