refactor: general code improvements

This commit is contained in:
4gray authored and GitHub committed 2021-11-06 20:39:27 +00:00
1 parent e2f3098b7e
commit 8233328b9a
10 files changed
+522 -151

No files matched your search

+3 -3
View File
@@ -1,6 +1,6 @@
import { app, BrowserWindow, Menu, MenuItem, shell } from 'electron';
import * as path from 'path';
import { SHOW_WHATS_NEW } from './shared/ipc-commands';
import { SHOW_WHATS_NEW, VIEW_ADD_PLAYLIST, VIEW_SETTINGS } from './shared/ipc-commands';
const openAboutWindow = require('about-window').default;
export class AppMenu {
@@ -48,14 +48,14 @@ export class AppMenu {
{
label: 'Add playlist',
click: () =>
this.window.webContents.send('add-playlist-view'),
this.window.webContents.send(VIEW_ADD_PLAYLIST),
},
{
type: 'separator',
},
{
label: 'Settings',
click: () => this.window.webContents.send('settings-view'),
click: () => this.window.webContents.send(VIEW_SETTINGS),
},
{
type: 'separator',
+239 -10
View File
@@ -1,12 +1,30 @@
import { NgxWhatsNewModule } from 'ngx-whats-new';
import { TestBed, waitForAsync } from '@angular/core/testing';
import {
ComponentFixture,
inject,
TestBed,
waitForAsync,
} from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
import { TranslateModule, TranslatePipe } from '@ngx-translate/core';
import {
TranslateModule,
TranslatePipe,
TranslateService,
} from '@ngx-translate/core';
import { ElectronService } from './services/electron.service';
import { ElectronServiceStub } from './services/electron.service.stub';
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
import { MockModule, MockPipe } from 'ng-mocks';
import { of } from 'rxjs';
import { WhatsNewService } from './services/whats-new.service';
import { Theme } from './settings/theme.enum';
import { SettingsService } from './services/settings.service';
import { Router } from '@angular/router';
import { ChannelStore } from './state';
import { STORE_KEY } from './shared/enums/store-keys.enum';
import { WhatsNewServiceStub } from './services/whats-new.service.stub';
import { IpcCommand } from '../../shared/ipc-command.class';
jest.mock('custom-electron-titlebar', () => {
return {
@@ -24,6 +42,14 @@ class MatSnackBarStub {
}
describe('AppComponent', () => {
let component: AppComponent;
let electronService: ElectronService;
let fixture: ComponentFixture<AppComponent>;
let settingsService: SettingsService;
let translateService: TranslateService;
let whatsNewService: WhatsNewService;
const defaultLanguage = 'en';
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
@@ -31,6 +57,9 @@ describe('AppComponent', () => {
providers: [
{ provide: ElectronService, useClass: ElectronServiceStub },
{ provide: MatSnackBar, useClass: MatSnackBarStub },
{ provide: WhatsNewService, useClass: WhatsNewServiceStub },
TranslateService,
SettingsService, // TODO: stub
],
imports: [
MockModule(MatSnackBarModule),
@@ -42,12 +71,212 @@ describe('AppComponent', () => {
})
);
it(
'should create the app',
waitForAsync(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
})
);
beforeEach(() => {
electronService = TestBed.inject(ElectronService);
fixture = TestBed.createComponent(AppComponent);
settingsService = TestBed.inject(SettingsService);
translateService = TestBed.inject(TranslateService);
whatsNewService = TestBed.inject(WhatsNewService);
component = fixture.componentInstance;
component.modals = [];
fixture.detectChanges();
});
it('should create the component and set default language', () => {
spyOn(translateService, 'setDefaultLang');
spyOn(component, 'setRendererListeners');
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
expect(component.commandsList.length).toEqual(5);
expect(IpcCommand).toHaveBeenCalledTimes(5);
});
it('should init component', () => {
spyOn(translateService, 'setDefaultLang');
spyOn(component, 'setRendererListeners');
spyOn(component, 'initSettings');
spyOn(component, 'handleWhatsNewDialog');
component.ngOnInit();
expect(translateService.setDefaultLang).toHaveBeenCalledWith(
defaultLanguage
);
expect(component.setRendererListeners).toHaveBeenCalledTimes(1);
expect(component.initSettings).toHaveBeenCalledTimes(1);
expect(component.handleWhatsNewDialog).toHaveBeenCalledTimes(1);
});
describe('Test ipc listeners and commands', () => {
it('should set IPC listeners', () => {
spyOn(electronService.ipcRenderer, 'on');
component.setRendererListeners();
expect(electronService.ipcRenderer.on).toHaveBeenCalledTimes(5);
});
it('should remove all ipc listeners on destroy', () => {
spyOn(electronService.ipcRenderer, 'removeAllListeners');
component.ngOnDestroy();
expect(
electronService.ipcRenderer.removeAllListeners
).toHaveBeenCalledTimes(4);
});
it('should navigate to the provided route', inject(
[Router],
(router: Router) => {
const route = '/add-playlists';
spyOn(router, 'navigateByUrl');
component.navigateToRoute(route);
expect(router.navigateByUrl).toHaveBeenCalledTimes(1);
expect(router.navigateByUrl).toHaveBeenCalledWith(
route,
expect.anything()
);
}
));
it('should show a notification on epg error', inject(
[MatSnackBar],
(snackbar: MatSnackBar) => {
spyOn(snackbar, 'open');
component.onEpgError();
expect(snackbar.open).toHaveBeenCalledTimes(1);
}
));
it('should handle epg download success', inject(
[MatSnackBar, ChannelStore],
(snackbar: MatSnackBar, channelStore: ChannelStore) => {
spyOn(snackbar, 'open');
spyOn(channelStore, 'setEpgAvailableFlag');
component.onEpgFetchDone();
expect(snackbar.open).toHaveBeenCalledTimes(1);
expect(channelStore.setEpgAvailableFlag).toHaveBeenCalledWith(
true
);
}
));
it('show show whats new dialog', () => {
spyOn(whatsNewService, 'getModalsByVersion');
spyOn(component, 'setDialogVisibility');
component.showWhatsNewDialog();
expect(whatsNewService.getModalsByVersion).toHaveBeenCalledTimes(1);
expect(component.setDialogVisibility).toHaveBeenCalledWith(true);
});
});
describe('Test version handling', () => {
it('should get actual app version which is outdated and show updates dialog', () => {
const currentAppVersion = '0.0.1';
const spyOnSettingsGet = spyOn(
settingsService,
'getValueFromLocalStorage'
).and.returnValue(of(currentAppVersion));
spyOn(whatsNewService, 'getModalsByVersion').and.returnValue([{}]);
spyOn(whatsNewService, 'changeDialogVisibleState');
component.handleWhatsNewDialog();
expect(spyOnSettingsGet).toHaveBeenCalled();
expect(whatsNewService.getModalsByVersion).toHaveBeenCalled();
expect(
whatsNewService.changeDialogVisibleState
).toHaveBeenCalledWith(true);
});
it('should get actual app version which is not outdated and do not shop updates dialog', () => {
const currentAppVersion = '1.0.0';
const spyOnSettingsGet = spyOn(
settingsService,
'getValueFromLocalStorage'
).and.returnValue(of(currentAppVersion));
spyOn(whatsNewService, 'getModalsByVersion').and.returnValue([{}]);
spyOn(whatsNewService, 'changeDialogVisibleState');
component.handleWhatsNewDialog();
expect(spyOnSettingsGet).toHaveBeenCalled();
expect(whatsNewService.getModalsByVersion).toHaveBeenCalledTimes(0);
expect(
whatsNewService.changeDialogVisibleState
).toHaveBeenCalledTimes(0);
});
it('should change the visibility of the whats new dialog', () => {
spyOn(whatsNewService, 'changeDialogVisibleState');
component.modals = [{}, {}];
const visibilityFlag = true;
component.setDialogVisibility(true);
expect(
whatsNewService.changeDialogVisibleState
).toHaveBeenCalledWith(visibilityFlag);
expect(
whatsNewService.changeDialogVisibleState
).toHaveBeenCalledTimes(1);
});
it('should not change the visibility of the whats new dialog', () => {
spyOn(whatsNewService, 'changeDialogVisibleState');
component.modals = [];
component.setDialogVisibility(true);
expect(
whatsNewService.changeDialogVisibleState
).toHaveBeenCalledTimes(0);
});
});
describe('Set initial settings', () => {
const theme = Theme.DarkTheme;
const language = 'es';
const epgUrl = 'http://localhost/epg.xml';
beforeEach(() => {
spyOn(electronService.ipcRenderer, 'send');
spyOn(settingsService, 'changeTheme');
spyOn(component, 'handleWhatsNewDialog');
spyOn(translateService, 'use');
});
it('should get and init settings (all settings are defined)', () => {
const spyOnSettingsGet = spyOn(
settingsService,
'getValueFromLocalStorage'
).and.returnValue(of({ theme, epgUrl, language }));
component.initSettings();
expect(spyOnSettingsGet).toHaveBeenCalledWith(STORE_KEY.Settings);
expect(settingsService.changeTheme).toHaveBeenCalledWith(theme);
expect(electronService.ipcRenderer.send).toHaveBeenCalledTimes(1);
expect(translateService.use).toHaveBeenCalledWith(language);
});
it('should get and init settings (nothing is defined)', () => {
const spyOnSettingsGet = spyOn(
settingsService,
'getValueFromLocalStorage'
).and.returnValue(of());
component.initSettings();
expect(spyOnSettingsGet).toHaveBeenCalledWith(STORE_KEY.Settings);
expect(settingsService.changeTheme).toHaveBeenCalledTimes(0);
expect(electronService.ipcRenderer.send).toHaveBeenCalledTimes(0);
expect(translateService.use).toHaveBeenCalledTimes(0);
});
it('should get and init settings (only theme is defined)', () => {
const spyOnSettingsGet = spyOn(
settingsService,
'getValueFromLocalStorage'
).and.returnValue(of({ theme }));
component.initSettings();
expect(spyOnSettingsGet).toHaveBeenCalledWith(STORE_KEY.Settings);
expect(settingsService.changeTheme).toHaveBeenCalledWith(theme);
expect(electronService.ipcRenderer.send).toHaveBeenCalledTimes(0);
expect(translateService.use).toHaveBeenCalledWith(defaultLanguage);
});
});
});
+130 -89
View File
@@ -3,7 +3,7 @@ import { TranslateService } from '@ngx-translate/core';
import { Titlebar, Color } from 'custom-electron-titlebar';
import { ElectronService } from './services/electron.service';
import { Router } from '@angular/router';
import { MatSnackBar } from '@angular/material/snack-bar';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
import { ChannelStore } from './state';
import { StorageMap } from '@ngx-pwa/local-storage';
import { Settings } from './settings/settings.interface';
@@ -12,11 +12,15 @@ import {
EPG_FETCH,
EPG_FETCH_DONE,
SHOW_WHATS_NEW,
VIEW_ADD_PLAYLIST,
VIEW_SETTINGS,
} from '../../shared/ipc-commands';
import { IpcCommand } from '../../shared/ipc-command.class';
import { SettingsService } from './services/settings.service';
import { WhatsNewService } from './services/whats-new.service';
import * as semver from 'semver';
import { ModalWindow } from 'ngx-whats-new/lib/modal-window.interface';
import { STORE_KEY } from './shared/enums/store-keys.enum';
// create custom title bar
new Titlebar({
@@ -25,6 +29,9 @@ new Titlebar({
enableMnemonics: true,
});
/**
* AppComponent
*/
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
@@ -32,10 +39,30 @@ new Titlebar({
export class AppComponent {
/** Visibility flag of the "what is new" modal dialog */
isDialogVisible$ = this.whatsNewService.dialogState$;
/** Dialog options */
options = this.whatsNewService.options;
/** Modals to show for the updated version of the application */
modals: ModalWindow[];
modals: ModalWindow[] = [];
/** Default options for epg snackbar notifications */
epgSnackBarOptions: MatSnackBarConfig = {
verticalPosition: 'bottom',
horizontalPosition: 'right',
};
/** List of ipc commands with function mapping */
commandsList = [
new IpcCommand(VIEW_ADD_PLAYLIST, () => this.navigateToRoute('/')),
new IpcCommand(VIEW_SETTINGS, () => this.navigateToRoute('/settings')),
new IpcCommand(EPG_FETCH_DONE, () => this.onEpgFetchDone),
new IpcCommand(EPG_ERROR, () => this.onEpgError),
new IpcCommand(SHOW_WHATS_NEW, () => this.showWhatsNewDialog),
];
/** Default language as fallback */
DEFAULT_LANG = 'en';
/**
* Creates an instance of AppComponent
@@ -51,10 +78,6 @@ export class AppComponent {
private storage: StorageMap,
private whatsNewService: WhatsNewService
) {
this.translate.setDefaultLang('en');
this.setRendererListeners();
if (
(this.electronService.remote.process.platform === 'linux' ||
this.electronService.remote.process.platform === 'win32') &&
@@ -76,76 +99,53 @@ export class AppComponent {
}
/**
* Initializes all necessary listeners for the events from the renderer process
* Starts all the functions to initialize the component
*/
setRendererListeners(): void {
this.electronService.ipcRenderer.on('add-playlist-view', () => {
this.ngZone.run(() => {
this.router.navigateByUrl('/', { skipLocationChange: true });
});
});
ngOnInit(): void {
this.translate.setDefaultLang(this.DEFAULT_LANG);
this.electronService.ipcRenderer.on('settings-view', () => {
this.ngZone.run(() => {
this.router.navigateByUrl('/settings', {
skipLocationChange: true,
});
});
});
this.electronService.ipcRenderer.on(EPG_FETCH_DONE, () => {
this.ngZone.run(() => {
this.channelStore.setEpgAvailableFlag(true);
this.snackBar.open('EPG was successfully downloaded!', null, {
duration: 2000,
verticalPosition: 'bottom',
horizontalPosition: 'right',
});
});
});
this.electronService.ipcRenderer.on(EPG_ERROR, () => {
this.snackBar.open('EPG Error: something went wrong...', null, {
duration: 2000,
verticalPosition: 'bottom',
horizontalPosition: 'right',
});
});
this.electronService.ipcRenderer.on(SHOW_WHATS_NEW, () => {
this.ngZone.run(() => {
this.modals = this.whatsNewService.getModalsByVersion(
this.electronService.getAppVersion()
);
this.setDialogVisibility(true);
});
});
this.setRendererListeners();
this.initSettings();
this.handleWhatsNewDialog();
}
/**
* Subscribes for app settings on component init
* Initializes all necessary listeners for the events from the renderer process
*/
ngOnInit(): void {
this.storage.get('settings').subscribe((settings: Settings) => {
if (settings && Object.keys(settings).length > 0) {
this.translate.use(settings.language ?? 'en');
if (settings.epgUrl) {
this.electronService.ipcRenderer.send(EPG_FETCH, {
url: settings.epgUrl,
});
this.snackBar.open('Fetch EPG data...', 'Close', {
verticalPosition: 'bottom',
horizontalPosition: 'right',
});
}
setRendererListeners(): void {
this.commandsList.forEach((command) =>
this.electronService.ipcRenderer.on(command.id, () =>
this.ngZone.run(() => command.callback())
)
);
}
if (settings.theme) {
this.settingsService.changeTheme(settings.theme);
}
}
});
/**
* Reads the settings object from local storage and initializes the
* application based on them
*/
initSettings(): void {
this.settingsService
.getValueFromLocalStorage(STORE_KEY.Settings)
.subscribe((settings: Settings) => {
if (settings && Object.keys(settings).length > 0) {
this.translate.use(settings.language ?? this.DEFAULT_LANG);
if (settings.epgUrl) {
this.electronService.ipcRenderer.send(EPG_FETCH, {
url: settings.epgUrl,
});
this.snackBar.open(
this.translate.instant('FETCH_EPG'),
this.translate.instant('CLOSE'),
this.epgSnackBarOptions
);
}
this.handleWhatsNewDialog();
if (settings.theme) {
this.settingsService.changeTheme(settings.theme);
}
}
});
}
/**
@@ -153,23 +153,23 @@ export class AppComponent {
*/
handleWhatsNewDialog(): void {
const actualVersion = this.electronService.getAppVersion();
this.storage.get('version').subscribe((version) => {
const isNewVersion = semver.gt(actualVersion, version || '0.0.0');
if (!version || isNewVersion) {
this.modals =
this.whatsNewService.getModalsByVersion(actualVersion);
this.setDialogVisibility(true);
}
this.setVersion(actualVersion);
});
}
/**
* Updates the version of the application in localstorage
* @param version actual version of the application
*/
setVersion(version: string): void {
this.storage.set('version', version).subscribe(() => {});
this.settingsService
.getValueFromLocalStorage(STORE_KEY.Version)
.subscribe((version) => {
const isNewVersion = semver.gt(
actualVersion,
version || '0.0.0'
);
if (!version || isNewVersion) {
this.modals =
this.whatsNewService.getModalsByVersion(actualVersion);
this.setDialogVisibility(true);
}
this.settingsService.setValueToLocalStorage(
STORE_KEY.Version,
actualVersion
);
});
}
/**
@@ -182,15 +182,56 @@ export class AppComponent {
}
}
/**
* Navigate to the specified route
* @param route route to navigate to
*/
navigateToRoute(route: string) {
this.router.navigateByUrl(route, { skipLocationChange: true });
}
/**
* Handles the event when the EPG fetching is done
*/
onEpgFetchDone(): void {
this.channelStore.setEpgAvailableFlag(true);
this.snackBar.open(
this.translate.instant('EPG.DOWNLOAD_SUCCESS'),
null,
{
...this.epgSnackBarOptions,
duration: 2000,
}
);
}
/**
* Handles epg error
*/
onEpgError(): void {
this.snackBar.open(this.translate.instant('EPG.ERROR'), null, {
...this.epgSnackBarOptions,
duration: 2000,
});
}
/**
* Shows the "what is new" dialog
*/
showWhatsNewDialog(): void {
this.modals = this.whatsNewService.getModalsByVersion(
this.electronService.getAppVersion()
);
this.setDialogVisibility(true);
}
/**
* Removes all ipc command listeners on component destroy
*/
ngOnDestroy(): void {
this.electronService.ipcRenderer.removeAllListeners(EPG_FETCH_DONE);
this.electronService.ipcRenderer.removeAllListeners(EPG_ERROR);
this.electronService.ipcRenderer.removeAllListeners(
'add-playlist-view'
);
this.electronService.ipcRenderer.removeAllListeners('settings-view');
this.electronService.ipcRenderer.removeAllListeners(VIEW_ADD_PLAYLIST);
this.electronService.ipcRenderer.removeAllListeners(VIEW_SETTINGS);
}
}
@@ -5,8 +5,9 @@ import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { MatSidenav } from '@angular/material/sidenav';
import { StorageMap } from '@ngx-pwa/local-storage';
import { Settings, SETTINGS_STORE_KEY, VideoPlayer } from '../../../settings/settings.interface';
import { Settings, VideoPlayer } from '../../../settings/settings.interface';
import { MatSnackBar } from '@angular/material/snack-bar';
import { STORE_KEY } from '../../../shared/enums/store-keys.enum';
@Component({
selector: 'app-video-player',
@@ -74,7 +75,7 @@ export class VideoPlayerComponent implements OnInit {
* Reads the app configuration from the browsers storage and applies the settings in the current component
*/
applySettings(): void {
this.storage.get(SETTINGS_STORE_KEY).subscribe((settings: Settings) => {
this.storage.get(STORE_KEY.Settings).subscribe((settings: Settings) => {
if (settings && Object.keys(settings).length > 0) {
this.playerSettings = {
player: settings.player,
+2 -2
View File
@@ -10,12 +10,12 @@ export class ElectronServiceStub {
argv: [0, 1],
},
app: {
getVersion: jest.fn(),
getVersion: jest.fn(() => '1.0.0'),
}
};
getAppVersion() {
this.remote.app.getVersion();
return this.remote.app.getVersion();
}
sendIpcEvent() {
+73
View File
@@ -0,0 +1,73 @@
import { TestBed, inject } from '@angular/core/testing';
import { StorageMap } from '@ngx-pwa/local-storage';
import { of } from 'rxjs';
import { Theme } from '../settings/theme.enum';
import { STORE_KEY } from '../shared/enums/store-keys.enum';
import { SettingsService } from './settings.service';
describe('Service: Settings', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [SettingsService],
});
});
it('should create a service instance', inject(
[SettingsService],
(service: SettingsService) => {
expect(service).toBeTruthy();
}
));
it('should set key/value pair', inject(
[SettingsService, StorageMap],
(service: SettingsService, storage: StorageMap) => {
const version = '2.1.0';
spyOn(storage, 'set').and.returnValue(of([]));
service.setValueToLocalStorage(STORE_KEY.Version, version);
expect(storage.set).toHaveBeenCalledWith(
STORE_KEY.Version,
version
);
}
));
it('should get value from the local storage', inject(
[SettingsService, StorageMap],
(service: SettingsService, storage: StorageMap) => {
const version = '2.1.0';
service.setValueToLocalStorage(STORE_KEY.Version, version);
service
.getValueFromLocalStorage(STORE_KEY.Version)
.subscribe((value) => {
expect(value).toBe(version);
});
}
));
describe('Test theme switch', () => {
let spyOnAdd, spyOnRemove;
beforeEach(() => {
spyOnAdd = spyOn(document.body.classList, 'add');
spyOnRemove = spyOn(document.body.classList, 'remove');
});
it('should switch to the dark theme', inject(
[SettingsService],
(service: SettingsService) => {
service.changeTheme(Theme.DarkTheme);
expect(spyOnRemove).toHaveBeenCalledTimes(0);
expect(spyOnAdd).toHaveBeenCalledTimes(1);
}
));
it('should switch to the light theme', inject(
[SettingsService],
(service: SettingsService) => {
service.changeTheme(Theme.LightTheme);
expect(spyOnRemove).toHaveBeenCalledTimes(1);
expect(spyOnAdd).toHaveBeenCalledTimes(0);
}
));
});
});
+23
View File
@@ -1,10 +1,15 @@
import { Theme } from './../settings/theme.enum';
import { Injectable } from '@angular/core';
import { StorageMap } from '@ngx-pwa/local-storage';
import { STORE_KEY } from '../shared/enums/store-keys.enum';
@Injectable({
providedIn: 'root',
})
export class SettingsService {
/** Creates an instance of SettingsService */
constructor(private storage: StorageMap) {}
/**
* Changes the visual theme of the application
* @param selectedTheme theme to set
@@ -16,4 +21,22 @@ export class SettingsService {
document.body.classList.add('dark-theme');
}
}
/**
* Returns the value of the given key from the local storage
* @param key key to get
* @returns returns the value of the given key
*/
getValueFromLocalStorage(key: STORE_KEY) {
return this.storage.get(key);
}
/**
* Sets the given key/value pair in the local storage
* @param key key to set
* @param value value to set
*/
setValueToLocalStorage(key: STORE_KEY, value: string) {
this.storage.set(key, value).subscribe(() => {});
}
}
@@ -0,0 +1,6 @@
export class WhatsNewServiceStub {
changeDialogVisibleState(): void {}
getModalsByVersion(): any {
return [];
}
}
+42 -42
View File
@@ -5,7 +5,8 @@ import { StorageMap } from '@ngx-pwa/local-storage';
import { Router } from '@angular/router';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Observable, Subscription } from 'rxjs';
import { Settings, SETTINGS_STORE_KEY, VideoPlayer } from './settings.interface';
import { STORE_KEY } from '../shared/enums/store-keys.enum';
import { Settings, VideoPlayer } from './settings.interface';
import { HttpClient } from '@angular/common/http';
import * as semver from 'semver';
import { ElectronService } from '../services/electron.service';
@@ -59,7 +60,7 @@ export class SettingsComponent implements OnInit {
themeEnum = Theme;
/**
* Creates an instance of SettingsComponent and injects
* Creates an instance of SettingsComponent and injects
* required dependencies into the component
* @param channelQuery
* @param electronService
@@ -94,50 +95,54 @@ export class SettingsComponent implements OnInit {
}
/**
* Reads the config object from the browsers
* Reads the config object from the browsers
* storage (indexed db)
*/
ngOnInit(): void {
this.storage.get(SETTINGS_STORE_KEY).subscribe((settings: Settings) => {
if (settings) {
this.settingsForm.setValue({
player: settings.player
? settings.player
: VideoPlayer.VideoJs,
epgUrl: settings.epgUrl ? settings.epgUrl : '',
language: settings.language
? settings.language
: Language.ENGLISH,
showCaptions: settings.showCaptions
? settings.showCaptions
: false,
theme: settings.theme
? settings.theme
: Theme.LightTheme,
});
}
});
this.settingsService
.getValueFromLocalStorage(STORE_KEY.Settings)
.subscribe((settings: Settings) => {
if (settings) {
this.settingsForm.setValue({
player: settings.player
? settings.player
: VideoPlayer.VideoJs,
epgUrl: settings.epgUrl ? settings.epgUrl : '',
language: settings.language
? settings.language
: Language.ENGLISH,
showCaptions: settings.showCaptions
? settings.showCaptions
: false,
theme: settings.theme
? settings.theme
: Theme.LightTheme,
});
}
});
}
/**
* Checks whether the latest version of the application
* Checks whether the latest version of the application
* is used and updates the version message in the
* settings UI
*/
checkAppVersion(): void {
this.http
.get(PACKAGE_JSON_URL)
.pipe(catchError(err => {
console.error(err);
throw new Error(err);
}))
.subscribe((response: { version: string }) => {
this.showVersionInformation(response.version);
});
.get(PACKAGE_JSON_URL)
.pipe(
catchError((err) => {
console.error(err);
throw new Error(err);
})
)
.subscribe((response: { version: string }) => {
this.showVersionInformation(response.version);
});
}
/**
* Updates the message in settings UI about the used
* Updates the message in settings UI about the used
* version of the app
* @param currentVersion current version of the application
*/
@@ -158,17 +163,14 @@ export class SettingsComponent implements OnInit {
}
/**
* Compares actual with latest version of the
* application
* Compares actual with latest version of the
* application
* @param latestVersion latest version
* @returns returns true if an update is available
*/
isCurrentVersionOutdated(latestVersion: string): boolean {
this.version = this.electronService.getAppVersion();
return semver.lt(
this.version,
latestVersion
);
return semver.lt(this.version, latestVersion);
}
/**
@@ -177,7 +179,7 @@ export class SettingsComponent implements OnInit {
*/
onSubmit(): void {
this.storage
.set(SETTINGS_STORE_KEY, this.settingsForm.value)
.set(STORE_KEY.Settings, this.settingsForm.value)
.subscribe(() => {
this.settingsForm.markAsPristine();
// check whether the epg url was changed or not
@@ -185,9 +187,7 @@ export class SettingsComponent implements OnInit {
this.fetchEpg();
}
this.translate.use(this.settingsForm.value.language);
this.settingsService.changeTheme(
this.settingsForm.value.theme
);
this.settingsService.changeTheme(this.settingsForm.value.theme);
this.snackBar.open(
this.translate.instant('SETTINGS.SETTINGS_SAVED'),
null,
+1 -3
View File
@@ -1,11 +1,9 @@
import { Language } from './language.enum';
import { Theme } from './theme.enum';
/** Settings key in storage */
export const SETTINGS_STORE_KEY = 'settings';
/**
* Contains all types of supported video players
* TODO: extract to separate file
*/
export enum VideoPlayer {
VideoJs = 'videojs',