Merge branch 'use-new-service-item-api-transpose-endpoint' into 'master'

Using the new response_format=service_item on Transpose API Endpoint while preserving old behavior

See merge request openlp/web-remote!53
This commit is contained in:
Raoul Snyman 2023-02-09 17:08:26 +00:00
commit 460df54a7d
4 changed files with 85 additions and 16 deletions

View File

@ -16,14 +16,53 @@ export class ChordViewComponent extends StageViewComponent {
songTransposeMap = new Map(); songTransposeMap = new Map();
// current songs transpose level // current songs transpose level
transposeLevel = 0; transposeLevel = 0;
currentSlide = 0;
useNewTransposeEndpoint = this.openlpService.assertApiVersionMinimum(2, 2);
updateCurrentSlides(serviceItemId: string, currentSlide: number): void {
this.currentSlide = currentSlide;
this.useNewTransposeEndpoint = this.openlpService.assertApiVersionMinimum(2, 2);
this.serviceItemSubscription$?.unsubscribe();
const newServiceItemTransposeLevel = this.songTransposeMap.get(serviceItemId);
setNewSlides(slides: Slide[]): void { if (this.useNewTransposeEndpoint && newServiceItemTransposeLevel && (newServiceItemTransposeLevel !== 0)) {
super.setNewSlides(slides); this.serviceItemSubscription$ = this.openlpService
.transposeSong(newServiceItemTransposeLevel, 'service_item')
.subscribe(serviceItem => {
this.serviceItem = serviceItem;
if (serviceItem instanceof Array) {
this.setNewSlides(serviceItem, currentSlide);
}
else {
this.setNewSlides(serviceItem.slides, currentSlide);
this.setNotes(serviceItem.notes);
}
});
} else {
if (this.useNewTransposeEndpoint) {
this.songTransposeMap.set(serviceItemId, 0);
this.transposeLevel = 0;
}
super.updateCurrentSlides(serviceItemId, currentSlide);
}
}
setNewSlides(slides: Slide[], currentSlide: number): void {
if (this.openlpService.assertApiVersionExact(2, 2)) {
// API Version 2.2 released on OpenLP 3.0.2 contains a bug on which 'selected' is not set correctly
// on Transponse Service Item response.
if (slides[currentSlide]) {
slides[currentSlide].selected = true;
}
}
super.setNewSlides(slides, currentSlide);
// if this song is already known // if this song is already known
if (this.songTransposeMap.has(this.serviceItem.id)) { if (this.songTransposeMap.has(this.serviceItem.id)) {
if (this.songTransposeMap.get(this.serviceItem.id) !== 0) { const transposeLevel = this.songTransposeMap.get(this.serviceItem.id);
this.transposeChords(); if (transposeLevel) {
if (!this.useNewTransposeEndpoint) {
this.transposeChords();
}
} else { } else {
this.transposeLevel = this.songTransposeMap.get(this.serviceItem.id); this.transposeLevel = this.songTransposeMap.get(this.serviceItem.id);
} }
@ -57,7 +96,15 @@ export class ChordViewComponent extends StageViewComponent {
transposeChords(): void { transposeChords(): void {
const tmpTranspose = this.songTransposeMap.get(this.serviceItem.id); const tmpTranspose = this.songTransposeMap.get(this.serviceItem.id);
this.transposeLevel = tmpTranspose; this.transposeLevel = tmpTranspose;
this.openlpService.transposeSong(tmpTranspose).subscribe(transposedLyrics => { if (this.useNewTransposeEndpoint) {
this.updateCurrentSlides(this.serviceItem.id, this.currentSlide);
} else {
this.transposeChordsLegacy(tmpTranspose);
}
}
transposeChordsLegacy(transposeLevel): void {
this.openlpService.transposeSong(transposeLevel).subscribe(transposedLyrics => {
// Replace the chords in the currentSlides with the returned transposed chords // Replace the chords in the currentSlides with the returned transposed chords
if (transposedLyrics instanceof Array) { if (transposedLyrics instanceof Array) {
for (let i = 0; i < transposedLyrics.length; ++i) { for (let i = 0; i < transposedLyrics.length; ++i) {

View File

@ -1,4 +1,5 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Subscription } from 'rxjs';
import { OpenLPService } from '../../openlp.service'; import { OpenLPService } from '../../openlp.service';
import { ServiceItem, Slide } from '../../responses'; import { ServiceItem, Slide } from '../../responses';
@ -21,24 +22,26 @@ export class StageViewComponent implements OnInit {
tags: Tag[] = []; tags: Tag[] = [];
time = new Date(); time = new Date();
showNotes = true; showNotes = true;
serviceItemSubscription$: Subscription = null;
constructor(public openlpService: OpenLPService) { constructor(public openlpService: OpenLPService) {
setInterval(() => this.time = new Date(), 1000); setInterval(() => this.time = new Date(), 1000);
} }
ngOnInit() { ngOnInit() {
this.updateCurrentSlides(); this.updateCurrentSlides(null, null);
this.openlpService.stateChanged$.subscribe(item => this.updateCurrentSlides()); this.openlpService.stateChanged$.subscribe(item => this.updateCurrentSlides(item.item, item.slide));
} }
updateCurrentSlides(): void { updateCurrentSlides(serviceItemId: string, currentSlide: number): void {
this.openlpService.getServiceItem().subscribe(serviceItem => { this.serviceItemSubscription$?.unsubscribe();
this.serviceItemSubscription$ = this.openlpService.getServiceItem().subscribe(serviceItem => {
this.serviceItem = serviceItem; this.serviceItem = serviceItem;
if (serviceItem instanceof Array) { if (serviceItem instanceof Array) {
this.setNewSlides(serviceItem); this.setNewSlides(serviceItem, currentSlide);
} }
else { else {
this.setNewSlides(serviceItem.slides); this.setNewSlides(serviceItem.slides, currentSlide);
this.setNotes(serviceItem.notes); this.setNotes(serviceItem.notes);
} }
}); });
@ -48,7 +51,7 @@ export class StageViewComponent implements OnInit {
return this.currentSlides.slice(this.activeSlide + 1); return this.currentSlides.slice(this.activeSlide + 1);
} }
setNewSlides(slides: Slide[]): void { setNewSlides(slides: Slide[], currentSlide: number): void {
if (slides.length === 0) { if (slides.length === 0) {
return; return;
} }

View File

@ -1,7 +1,7 @@
import { Injectable, EventEmitter } from '@angular/core'; import { Injectable, EventEmitter } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { finalize, shareReplay } from 'rxjs/operators'; import { finalize, shareReplay, tap } from 'rxjs/operators';
import { import {
PluginDescription, PluginDescription,
@ -44,6 +44,8 @@ export enum WebSocketStatus {
@Injectable() @Injectable()
export class OpenLPService { export class OpenLPService {
private apiURL: string; private apiURL: string;
public apiVersion: number | null;
public apiRevision: number | null;
private host: string; private host: string;
public stateChanged$: EventEmitter<State>; public stateChanged$: EventEmitter<State>;
public webSocketStateChanged$: EventEmitter<WebSocketStatus>; public webSocketStateChanged$: EventEmitter<WebSocketStatus>;
@ -69,6 +71,14 @@ export class OpenLPService {
this.createWebSocket(); this.createWebSocket();
} }
assertApiVersionExact(version: number, revision: number) {
return version === this.apiVersion && revision === this.apiRevision;
}
assertApiVersionMinimum(version: number, revision: number) {
return this.apiVersion >= version && this.apiRevision >= revision;
}
setAuthToken(token: string): void { setAuthToken(token: string): void {
httpOptions.headers = httpOptions.headers.set('Authorization', token); httpOptions.headers = httpOptions.headers.set('Authorization', token);
} }
@ -78,7 +88,13 @@ export class OpenLPService {
} }
retrieveSystemInformation(): Observable<SystemInformation> { retrieveSystemInformation(): Observable<SystemInformation> {
return this.doGet<SystemInformation>(`${this.apiURL}/core/system`); return this.doGet<SystemInformation>(`${this.apiURL}/core/system`)
.pipe(tap(systemInfo => {
if (systemInfo.api_version) {
this.apiVersion = systemInfo.api_version;
this.apiRevision = systemInfo.api_revision;
}
}));
} }
getMainImage(): Observable<MainView> { getMainImage(): Observable<MainView> {
@ -185,8 +201,8 @@ export class OpenLPService {
return this.doPost(`${this.apiURL}/plugins/${plugin}/add`, {id}); return this.doPost(`${this.apiURL}/plugins/${plugin}/add`, {id});
} }
transposeSong(transpose_value): Observable<any> { transposeSong(transpose_value, return_format = 'default'): Observable<any> {
return this.doGet(`${this.apiURL}/plugins/songs/transpose-live-item/${transpose_value}`); return this.doGet(`${this.apiURL}/plugins/songs/transpose-live-item/${transpose_value}?response_format=${return_format}`);
} }
login(credentials: Credentials): Observable<AuthToken> { login(credentials: Credentials): Observable<AuthToken> {

View File

@ -12,6 +12,7 @@ export class State {
blank: boolean; blank: boolean;
twelve: boolean; twelve: boolean;
theme: boolean; theme: boolean;
item: string;
live = () => !(this.blank || this.display || this.theme); live = () => !(this.blank || this.display || this.theme);
@ -68,6 +69,8 @@ export interface MainView {
export interface SystemInformation { export interface SystemInformation {
websocket_port: number; websocket_port: number;
login_required: boolean; login_required: boolean;
api_version?: number;
api_revision?: number;
} }
export interface Credentials { export interface Credentials {