Merge branch 'update-to-angular-v16' into 'master'

Update to Angular v16

See merge request openlp/web-remote!73
This commit is contained in:
Chris Witterholt 2024-02-08 19:37:40 +00:00
commit 96adf2c86f
24 changed files with 3294 additions and 2184 deletions

View File

@ -16,8 +16,8 @@
"createDefaultProgram": true "createDefaultProgram": true
}, },
"extends": [ "extends": [
"plugin:@angular-eslint/ng-cli-compat", "plugin:@typescript-eslint/recommended",
"plugin:@angular-eslint/ng-cli-compat--formatting-add-on", "plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates" "plugin:@angular-eslint/template/process-inline-templates"
], ],
"rules": { "rules": {
@ -56,6 +56,7 @@
"style": "camelCase" "style": "camelCase"
} }
], ],
"@angular-eslint/no-empty-lifecycle-method": "off",
"@typescript-eslint/naming-convention": [ "@typescript-eslint/naming-convention": [
"error", "error",
{ {
@ -64,6 +65,8 @@
"format": ["UPPER_CASE"] "format": ["UPPER_CASE"]
} }
], ],
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "off",
"jsdoc/no-types": [ "jsdoc/no-types": [
"off" "off"
], ],

View File

@ -23,33 +23,33 @@
"lint": "ng lint" "lint": "ng lint"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "^15.0.2", "@angular/animations": "^16.2.12",
"@angular/cdk": "^15.0.2", "@angular/cdk": "^16.2.12",
"@angular/common": "^15.0.2", "@angular/common": "^16.2.12",
"@angular/compiler": "^15.0.2", "@angular/compiler": "^16.2.12",
"@angular/core": "^15.0.2", "@angular/core": "^16.2.12",
"@angular/forms": "^15.0.2", "@angular/forms": "^16.2.12",
"@angular/material": "^15.0.2", "@angular/material": "^16.2.12",
"@angular/platform-browser": "^15.0.2", "@angular/platform-browser": "^16.2.12",
"@angular/platform-browser-dynamic": "^15.0.2", "@angular/platform-browser-dynamic": "^16.2.12",
"@angular/router": "^15.0.2", "@angular/router": "^16.2.12",
"@fontsource/roboto": "^4.5.8", "@fontsource/roboto": "^4.5.8",
"core-js": "^3.26.1", "core-js": "^3.26.1",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"material-icons": "^1.13.1", "material-icons": "^1.13.1",
"rxjs": "^7.6.0", "rxjs": "^7.6.0",
"zone.js": "^0.12.0" "zone.js": "^0.13.3"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^15.0.3", "@angular-devkit/build-angular": "^16.2.12",
"@angular-eslint/builder": "^15.0.3", "@angular-eslint/builder": "^16.2.12",
"@angular-eslint/eslint-plugin": "^15.1.0", "@angular-eslint/eslint-plugin": "^16.2.12",
"@angular-eslint/eslint-plugin-template": "^15.1.0", "@angular-eslint/eslint-plugin-template": "^16.2.12",
"@angular-eslint/schematics": "^15.1.0", "@angular-eslint/schematics": "^16.2.12",
"@angular-eslint/template-parser": "^15.1.0", "@angular-eslint/template-parser": "^16.2.12",
"@angular/cli": "~15.0.2", "@angular/cli": "~16.2.12",
"@angular/compiler-cli": "^15.0.2", "@angular/compiler-cli": "^16.2.12",
"@angular/language-service": "^15.0.2", "@angular/language-service": "^16.2.12",
"@types/jasmine": "~4.3.1", "@types/jasmine": "~4.3.1",
"@types/jasminewd2": "~2.0.10", "@types/jasminewd2": "~2.0.10",
"@types/node": "~18.11.13", "@types/node": "~18.11.13",
@ -67,7 +67,7 @@
"karma-jasmine": "~5.1.0", "karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "^2.0.0", "karma-jasmine-html-reporter": "^2.0.0",
"ts-node": "~10.9.1", "ts-node": "~10.9.1",
"typescript": "~4.8.2" "typescript": "~5.1.6"
}, },
"private": true "private": true
} }

View File

@ -1,6 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
import { MatBottomSheet } from '@angular/material/bottom-sheet'; import { MatBottomSheet } from '@angular/material/bottom-sheet';
import { State, DisplayMode } from './responses'; import { State, DisplayMode } from './responses';
@ -54,38 +53,38 @@ export class AppComponent implements OnInit {
} }
addHotKeys(): void { addHotKeys(): void {
this.hotKeysService.addShortcut({ keys: 'ArrowUp' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 'ArrowUp' }).subscribe(() =>
this.previousSlide() this.previousSlide()
); );
this.hotKeysService.addShortcut({ keys: 'ArrowDown' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 'ArrowDown' }).subscribe(() =>
this.nextSlide() this.nextSlide()
); );
this.hotKeysService.addShortcut({ keys: 'PageUp' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 'PageUp' }).subscribe(() =>
this.previousSlide() this.previousSlide()
); );
this.hotKeysService.addShortcut({ keys: 'PageDown' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 'PageDown' }).subscribe(() =>
this.nextSlide() this.nextSlide()
); );
this.hotKeysService.addShortcut({ keys: 'ArrowLeft' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 'ArrowLeft' }).subscribe(() =>
this.previousItem() this.previousItem()
); );
this.hotKeysService.addShortcut({ keys: 'ArrowRight' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 'ArrowRight' }).subscribe(() =>
this.nextItem() this.nextItem()
); );
this.hotKeysService.addShortcut({ keys: 'Space' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 'Space' }).subscribe(() =>
{ {
if (this.state.displayMode !== DisplayMode.Presentation) { if (this.state.displayMode !== DisplayMode.Presentation) {
this.showDisplay(); this.showDisplay();
} }
} }
); );
this.hotKeysService.addShortcut({ keys: 't' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 't' }).subscribe(() =>
this.state.displayMode === DisplayMode.Theme ? this.showDisplay() : this.themeDisplay() this.state.displayMode === DisplayMode.Theme ? this.showDisplay() : this.themeDisplay()
); );
this.hotKeysService.addShortcut({ keys: 'code.Period' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 'code.Period' }).subscribe(() =>
this.state.displayMode === DisplayMode.Blank ? this.showDisplay() : this.blankDisplay() this.state.displayMode === DisplayMode.Blank ? this.showDisplay() : this.blankDisplay()
); );
this.hotKeysService.addShortcut({ keys: 'd' }).subscribe(_ => this.hotKeysService.addShortcut({ keys: 'd' }).subscribe(() =>
this.state.displayMode === DisplayMode.Desktop ? this.showDisplay() : this.desktopDisplay() this.state.displayMode === DisplayMode.Desktop ? this.showDisplay() : this.desktopDisplay()
); );
} }
@ -122,13 +121,13 @@ export class AppComponent implements OnInit {
} }
nextSlide() { nextSlide() {
this.openlpService.nextSlide().subscribe( _ => this.openlpService.nextSlide().subscribe(() =>
this.hotKeysService.scrollToCurrentItem('slide', 'start') this.hotKeysService.scrollToCurrentItem('slide', 'start')
); );
} }
previousSlide() { previousSlide() {
this.openlpService.previousSlide().subscribe(_ => this.openlpService.previousSlide().subscribe(() =>
this.hotKeysService.scrollToCurrentItem('slide', 'end') this.hotKeysService.scrollToCurrentItem('slide', 'end')
); );
} }

View File

@ -107,9 +107,6 @@ import { StageChordPreviewComponent } from './components/settings/stage-chord-pr
Title, Title,
WindowRef WindowRef
], ],
entryComponents: [
LoginComponent
],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { } export class AppModule { }

View File

@ -21,6 +21,6 @@ export class AlertComponent {
} }
onSubmit() { onSubmit() {
this.openlpService.showAlert(this.alert).subscribe(res => this.snackBar.open('Alert submitted', '', {duration: 2000})); this.openlpService.showAlert(this.alert).subscribe(() => this.snackBar.open('Alert submitted', '', {duration: 2000}));
} }
} }

View File

@ -1,4 +1,4 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, ViewEncapsulation } from '@angular/core';
import { Slide } from '../../responses'; import { Slide } from '../../responses';
import { StageViewComponent } from '../stage-view/stage-view.component'; import { StageViewComponent } from '../stage-view/stage-view.component';

View File

@ -10,7 +10,6 @@
* @licence Use this in any way you like, with no constraints. * @licence Use this in any way you like, with no constraints.
*/ */
import { Pipe, PipeTransform } from '@angular/core'; import { Pipe, PipeTransform } from '@angular/core';
import { MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY } from '@angular/material/autocomplete';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Pipe({ name: 'chordpro' }) @Pipe({ name: 'chordpro' })

View File

@ -1,5 +1,4 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Credentials } from '../../responses';
import { MatDialogRef } from '@angular/material/dialog'; import { MatDialogRef } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { OpenLPService } from '../../openlp.service'; import { OpenLPService } from '../../openlp.service';
@ -16,6 +15,7 @@ export class LoginComponent implements OnInit {
private snackBar: MatSnackBar) { } private snackBar: MatSnackBar) { }
ngOnInit() { ngOnInit() {
// Do nothing
} }
performLogin() { performLogin() {
@ -24,7 +24,7 @@ export class LoginComponent implements OnInit {
this.snackBar.open('Successfully logged in', '', {duration: 2000}); this.snackBar.open('Successfully logged in', '', {duration: 2000});
this.dialogRef.close(result); this.dialogRef.close(result);
}, },
err => this.snackBar.open('Login failed', '', {duration: 2000}) () => this.snackBar.open('Login failed', '', {duration: 2000})
); );
} }
} }

View File

@ -1,7 +1,7 @@
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { SettingsProperties, SettingsService } from 'src/app/settings.service'; import { SettingsService } from 'src/app/settings.service';
import { OpenLPService } from '../../openlp.service'; import { OpenLPService } from '../../openlp.service';
import { ServiceItem, Slide } from '../../responses'; import { ServiceItem, Slide } from '../../responses';
@ -34,27 +34,27 @@ export class LowerThirdComponent implements OnInit, OnDestroy {
} }
ngOnInit() { ngOnInit() {
this.updateCurrentSlides(null, null); this.updateCurrentSlides();
this.openlpService.stateChanged$.subscribe(item => this.updateCurrentSlides(item.item, item.slide)); this.openlpService.stateChanged$.subscribe(() => this.updateCurrentSlides());
} }
ngOnDestroy(): void { ngOnDestroy(): void {
} }
updateCurrentSlides(serviceItemId: string, currentSlide: number): void { updateCurrentSlides(): void {
this.serviceItemSubscription$?.unsubscribe(); this.serviceItemSubscription$?.unsubscribe();
this.serviceItemSubscription$ = this.openlpService.getServiceItem().subscribe(serviceItem => { this.serviceItemSubscription$ = this.openlpService.getServiceItem().subscribe(serviceItem => {
this.serviceItem = serviceItem; this.serviceItem = serviceItem;
if (serviceItem instanceof Array) { if (serviceItem instanceof Array) {
this.setNewSlides(serviceItem, currentSlide); this.setNewSlides(serviceItem);
} }
else { else {
this.setNewSlides(serviceItem.slides, currentSlide); this.setNewSlides(serviceItem.slides);
} }
}); });
} }
setNewSlides(slides: Slide[], currentSlide: number): void { setNewSlides(slides: Slide[]): void {
if (slides.length === 0) { if (slides.length === 0) {
return; return;
} }

View File

@ -12,7 +12,7 @@ export class MainViewComponent implements OnInit {
ngOnInit() { ngOnInit() {
this.updateImage(); this.updateImage();
this.openlpService.stateChanged$.subscribe(item => this.updateImage()); this.openlpService.stateChanged$.subscribe(() => this.updateImage());
} }
updateImage(): void { updateImage(): void {

View File

@ -40,7 +40,7 @@ export class SearchOptionsComponent {
} }
setSearchOption(target) { setSearchOption(target) {
this.openlpService.setSearchOption(this.selectedPlugin, 'primary bible', target.value).subscribe(res => {}); this.openlpService.setSearchOption(this.selectedPlugin, 'primary bible', target.value).subscribe(() => {});
this.selectedSearchOption = target.value; this.selectedSearchOption = target.value;
} }
} }

View File

@ -45,11 +45,11 @@ export class SearchComponent implements OnInit, AfterViewInit {
} }
sendLive(id) { sendLive(id) {
this.openlpService.sendItemLive(this.currentPlugin, id).subscribe(res => {}); this.openlpService.sendItemLive(this.currentPlugin, id).subscribe(() => {});
} }
addToService(id) { addToService(id) {
this.openlpService.addItemToService(this.currentPlugin, id).subscribe(res => {}); this.openlpService.addItemToService(this.currentPlugin, id).subscribe(() => {});
} }
ngOnInit() { ngOnInit() {

View File

@ -34,7 +34,7 @@ export class ServiceListComponent implements OnInit, OnDestroy {
} }
constructor(private openlpService: OpenLPService) { constructor(private openlpService: OpenLPService) {
this._subscription = openlpService.stateChanged$.subscribe(state => { this._subscription = openlpService.stateChanged$.subscribe(() => {
this.fetchServiceItems(); this.fetchServiceItems();
}); });
} }

View File

@ -1,4 +1,4 @@
import { Component, OnDestroy, ViewChild } from '@angular/core'; import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { OpenLPService } from '../../openlp.service'; import { OpenLPService } from '../../openlp.service';
import { PageTitleService } from '../../page-title.service'; import { PageTitleService } from '../../page-title.service';

View File

@ -20,7 +20,7 @@ export class SlideListComponent implements OnInit, OnDestroy {
isServiceItemChanged: boolean; isServiceItemChanged: boolean;
constructor(private openlpService: OpenLPService, private hotKeysService: HotKeysService) { constructor(private openlpService: OpenLPService, private hotKeysService: HotKeysService) {
this._subscription = openlpService.stateChanged$.subscribe(_ => this._subscription = openlpService.stateChanged$.subscribe(() =>
this.fetchSlides() this.fetchSlides()
); );
} }

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { Slide } from '../../../responses'; import { Slide } from '../../../responses';
@Component({ @Component({

View File

@ -84,7 +84,7 @@ export class StageViewComponent implements OnInit, OnDestroy {
this.nextServiceItemTitle = ''; this.nextServiceItemTitle = '';
let doStoreServiceItemTitle = false; let doStoreServiceItemTitle = false;
this.openlpService.getServiceItems().subscribe(serviceItems => { this.openlpService.getServiceItems().subscribe(serviceItems => {
serviceItems.forEach((serviceItem, _index) => { serviceItems.forEach((serviceItem) => {
if (doStoreServiceItemTitle) { if (doStoreServiceItemTitle) {
this.nextServiceItemTitle = serviceItem.title; this.nextServiceItemTitle = serviceItem.title;
doStoreServiceItemTitle = false; doStoreServiceItemTitle = false;
@ -96,7 +96,7 @@ export class StageViewComponent implements OnInit, OnDestroy {
}); });
} }
setNewSlides(slides: Slide[], _currentSlide: number): void { setNewSlides(slides: Slide[], _currentSlide: number): void { /* eslint-disable-line @typescript-eslint/no-unused-vars */
if (slides.length === 0) { if (slides.length === 0) {
return; return;
} }

View File

@ -6,7 +6,7 @@ import { Observable } from 'rxjs';
interface Options { interface Options {
element: any; element: any;
keys: string; keys: string;
}; }
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class HotKeysService { export class HotKeysService {

View File

@ -1,5 +1,3 @@
import { Type } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
export function createWebSocket<T>( export function createWebSocket<T>(

View File

@ -246,7 +246,7 @@ export class OpenLPService {
this.createMessageWebsocketConnection(info.websocket_port); this.createMessageWebsocketConnection(info.websocket_port);
} }
}, },
error: _ => this.reconnectWebSocket() error: () => this.reconnectWebSocket()
}); });
} }
@ -269,7 +269,7 @@ export class OpenLPService {
} }
this.handleStateChange(state); this.handleStateChange(state);
}, },
error: (e) => { error: () => {
this.webSocketStateChanged$.emit(WebSocketStatus.Closed); this.webSocketStateChanged$.emit(WebSocketStatus.Closed);
this.reconnectWebSocket(); this.reconnectWebSocket();
}, },
@ -292,7 +292,7 @@ export class OpenLPService {
'messages', 'messages',
).subscribe({ ).subscribe({
next: (message) => this.handleMessage(message), next: (message) => this.handleMessage(message),
error: (e) => this.reconnectWebSocket(), error: () => this.reconnectWebSocket(),
complete: () => this.reconnectWebSocket() complete: () => this.reconnectWebSocket()
}); });
} }

View File

@ -5,7 +5,7 @@ export class SettingsProperties {
fastSwitching = false; fastSwitching = false;
stageFontScale = 100; stageFontScale = 100;
chordsFontScale = 100; chordsFontScale = 100;
}; }
export interface SettingsPropertiesItem<SP extends keyof SettingsProperties, SV = SettingsProperties[SP]> { export interface SettingsPropertiesItem<SP extends keyof SettingsProperties, SV = SettingsProperties[SP]> {
property: SP; property: SP;

View File

@ -9,4 +9,4 @@ export function deserialize<T>(json: any, cls: Type<T>): T {
inst[p] = json[p]; inst[p] = json[p];
} }
return inst; return inst;
}; }

View File

@ -9,5 +9,9 @@
"exclude": [ "exclude": [
"src/test.ts", "src/test.ts",
"**/*.spec.ts" "**/*.spec.ts"
],
"files": [
"main.ts",
"polyfills.ts"
] ]
} }

5340
yarn.lock

File diff suppressed because it is too large Load Diff