From a9348b39286249d4271842c440aae3bc1b8fa17a Mon Sep 17 00:00:00 2001
From: jojohoch <joachim.hoch@iqb.hu-berlin.de>
Date: Thu, 3 Mar 2022 08:49:24 +0100
Subject: [PATCH] [player] Refactor MediaPlayerService

Replace the direct method calls in media player components with events.
For this purpose, expand the inputs of the media player components that
are defined in the ElementMediaPlayerGroupComponent.
---
 ...edia-player-element-component.directive.ts | 29 +++++++++++++++----
 .../element-media-player-group.component.html |  4 +++
 .../element-media-player-group.component.ts   |  2 --
 .../src/app/services/media-player.service.ts  | 26 +++++------------
 4 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/projects/common/directives/media-player-element-component.directive.ts b/projects/common/directives/media-player-element-component.directive.ts
index ada517cc5..051ed225e 100644
--- a/projects/common/directives/media-player-element-component.directive.ts
+++ b/projects/common/directives/media-player-element-component.directive.ts
@@ -1,24 +1,41 @@
 import {
-  Directive, EventEmitter, Input, Output
+  Directive, EventEmitter, Input, OnInit, Output
 } from '@angular/core';
+import { Subject } from 'rxjs';
 import { ElementComponent } from './element-component.directive';
-import { ValueChangeElement } from '../interfaces/elements';
+import { AudioElement, ValueChangeElement, VideoElement } from '../interfaces/elements';
 
 @Directive()
-export abstract class MediaPlayerElementComponent extends ElementComponent {
+export abstract class MediaPlayerElementComponent extends ElementComponent implements OnInit {
   @Input() savedPlaybackTime!: number;
+  @Input() actualPlayingId!: Subject<string | null>;
+  @Input() mediaStatusChanged!: Subject<string>;
   @Output() elementValueChanged = new EventEmitter<ValueChangeElement>();
   @Output() onMediaPlayStatusChanged = new EventEmitter<string | null>();
   @Output() onMediaValidStatusChanged = new EventEmitter<string>();
 
+  abstract elementModel: AudioElement | VideoElement;
   active: boolean = true;
   dependencyDissolved!: boolean;
 
-  setActualPlayingMediaId(id: string | null): void {
+  ngOnInit(): void {
+    if (this.actualPlayingId) {
+      this.actualPlayingId
+        .subscribe((actualID: string | null): void => this.setActualPlayingMediaId(actualID));
+    }
+    if (this.mediaStatusChanged) {
+      this.mediaStatusChanged
+        .subscribe((id: string): void => this.setActivatedAfterID(id));
+    }
+  }
+
+  private setActualPlayingMediaId(id: string | null): void {
     this.active = !id || id === this.elementModel.id;
   }
 
-  setActivatedAfterID(): void {
-    this.dependencyDissolved = true;
+  private setActivatedAfterID(id: string): void {
+    if (!this.dependencyDissolved) {
+      this.dependencyDissolved = id === (this.elementModel).playerProps.activeAfterID;
+    }
   }
 }
diff --git a/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.html b/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.html
index 7c5982780..916f6f14d 100644
--- a/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.html
+++ b/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.html
@@ -3,6 +3,8 @@
     #elementComponent
     [elementModel]="elementModel | cast: AudioElement"
     [savedPlaybackTime]="initialValue"
+    [actualPlayingId]="mediaPlayerService.actualPlayingId"
+    [mediaStatusChanged]="mediaPlayerService.mediaStatusChanged"
     (onMediaValidStatusChanged)="mediaPlayerService.setValidStatusChanged($event)"
     (onMediaPlayStatusChanged)="mediaPlayerService.setActualPlayingMediaId($event)"
     (elementValueChanged)="unitStateService.changeElementValue($event)">
@@ -12,6 +14,8 @@
     *ngIf="elementModel.type === 'video'"
     #elementComponent
     [elementModel]="elementModel | cast: VideoElement"
+    [actualPlayingId]="mediaPlayerService.actualPlayingId"
+    [mediaStatusChanged]="mediaPlayerService.mediaStatusChanged"
     [savedPlaybackTime]="initialValue"
     (onMediaValidStatusChanged)="mediaPlayerService.setValidStatusChanged($event)"
     (onMediaPlayStatusChanged)="mediaPlayerService.setActualPlayingMediaId($event)"
diff --git a/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.ts b/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.ts
index d4e2fadb4..beb92a0dd 100644
--- a/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.ts
+++ b/projects/player/src/app/components/element-media-player-group/element-media-player-group.component.ts
@@ -38,8 +38,6 @@ export class ElementMediaPlayerGroupComponent extends ElementGroupDirective impl
 
     this.mediaPlayerService.registerMediaElement(
       this.elementModel.id,
-      this.elementComponent,
-      this.elementModel.playerProps?.activeAfterID as string,
       this.elementModel.playerProps?.minRuns as number === 0
     );
   }
diff --git a/projects/player/src/app/services/media-player.service.ts b/projects/player/src/app/services/media-player.service.ts
index 071dad7f2..08a742187 100644
--- a/projects/player/src/app/services/media-player.service.ts
+++ b/projects/player/src/app/services/media-player.service.ts
@@ -1,13 +1,13 @@
 import { Injectable } from '@angular/core';
-import { Observable, Subject } from 'rxjs';
-import { MediaPlayerElementComponent } from '../../../../common/directives/media-player-element-component.directive';
+import { Subject } from 'rxjs';
 
 @Injectable({
   providedIn: 'root'
 })
 export class MediaPlayerService {
-  mediaElements: { id: string; mediaComponent: MediaPlayerElementComponent; dependOn: string; valid: boolean }[] = [];
-  private _mediaStatusChanged = new Subject<string>();
+  mediaElements: { id: string; valid: boolean }[] = [];
+  mediaStatusChanged = new Subject<string>();
+  actualPlayingId: Subject<string | null> = new Subject();
 
   get mediaStatus(): string {
     const validMediaElements = this.mediaElements.filter(mediaElement => mediaElement.valid);
@@ -17,37 +17,27 @@ export class MediaPlayerService {
     return this.mediaElements.length ? 'none' : 'complete';
   }
 
-  get mediaStatusChanged(): Observable<string> {
-    return this._mediaStatusChanged.asObservable();
-  }
-
   registerMediaElement(
-    id: string, mediaComponent: MediaPlayerElementComponent, dependOn: string, valid: boolean
+    id: string, valid: boolean
   ): void {
     this.mediaElements.push({
-      id, mediaComponent, dependOn, valid
+      id, valid
     });
   }
 
   setActualPlayingMediaId(actualId: string | null): void {
-    this.mediaElements.forEach(mediaElement => mediaElement.mediaComponent.setActualPlayingMediaId(actualId));
+    this.actualPlayingId.next(actualId);
   }
 
   setValidStatusChanged(validId: string): void {
     const validMediaElement = this.mediaElements.find(mediaElement => mediaElement.id === validId);
     if (validMediaElement) {
       validMediaElement.valid = true;
+      this.mediaStatusChanged.next(validId);
     }
-    this._mediaStatusChanged.next(validId);
-    this.broadcastValidStatusChanged(validId);
   }
 
   reset(): void {
     this.mediaElements = [];
   }
-
-  private broadcastValidStatusChanged(validId: string): void {
-    const dependingMediaElements = this.mediaElements.filter(mediaElement => mediaElement.dependOn === validId);
-    dependingMediaElements.forEach(mediaElement => mediaElement.mediaComponent.setActivatedAfterID());
-  }
 }
-- 
GitLab