From b3f3324d0d69b80798cb182648aa9babc7cc72d8 Mon Sep 17 00:00:00 2001 From: jojohoch <joachim.hoch@iqb.hu-berlin.de> Date: Tue, 4 Jul 2023 11:11:25 +0200 Subject: [PATCH] [player] Save if the animation of an animated section was done --- .../player/modules/verona/models/verona.ts | 4 +- .../src/app/classes/storable-timer.spec.ts | 7 +++ ...er-state-variable.ts => storable-timer.ts} | 10 ++-- .../player/src/app/classes/storable.spec.ts | 7 +++ projects/player/src/app/classes/storable.ts | 9 +++ .../app/classes/timer-state-variable.spec.ts | 7 --- .../app/components/page/page.component.html | 3 +- .../section-visibility-handling.directive.ts | 58 +++++++++++++------ .../src/app/services/unit-state.service.ts | 6 +- 9 files changed, 74 insertions(+), 37 deletions(-) create mode 100644 projects/player/src/app/classes/storable-timer.spec.ts rename projects/player/src/app/classes/{timer-state-variable.ts => storable-timer.ts} (79%) create mode 100644 projects/player/src/app/classes/storable.spec.ts create mode 100644 projects/player/src/app/classes/storable.ts delete mode 100644 projects/player/src/app/classes/timer-state-variable.spec.ts diff --git a/projects/player/modules/verona/models/verona.ts b/projects/player/modules/verona/models/verona.ts index 19def54f5..f7610393b 100644 --- a/projects/player/modules/verona/models/verona.ts +++ b/projects/player/modules/verona/models/verona.ts @@ -5,8 +5,8 @@ export type RunningState = 'running' | 'stopped'; export type Progress = 'none' | 'some' | 'complete'; export type PagingMode = 'separate' | 'concat-scroll' | 'concat-scroll-snap'; export type StateReportPolicy = 'none' | 'eager' | 'on-demand'; -export type ElementCodeStatus = 'DERIVED' | 'NOT_REACHED' | 'DISPLAYED' | 'VALUE_CHANGED'; -export enum ElementCodeStatusValue { DERIVED = 0, NOT_REACHED = 1, DISPLAYED = 2, VALUE_CHANGED = 3} +export type ElementCodeStatus = 'VIRTUAL' | 'NOT_REACHED' | 'DISPLAYED' | 'VALUE_CHANGED'; +export enum ElementCodeStatusValue { VIRTUAL = 0, NOT_REACHED = 1, DISPLAYED = 2, VALUE_CHANGED = 3} export interface StatusChangeElement { id: string; diff --git a/projects/player/src/app/classes/storable-timer.spec.ts b/projects/player/src/app/classes/storable-timer.spec.ts new file mode 100644 index 000000000..33a24b995 --- /dev/null +++ b/projects/player/src/app/classes/storable-timer.spec.ts @@ -0,0 +1,7 @@ +import { StorableTimer } from './storable-timer'; + +describe('StorableTimer', () => { + it('should create an instance', () => { + expect(new StorableTimer('test', 0, 3000)).toBeTruthy(); + }); +}); diff --git a/projects/player/src/app/classes/timer-state-variable.ts b/projects/player/src/app/classes/storable-timer.ts similarity index 79% rename from projects/player/src/app/classes/timer-state-variable.ts rename to projects/player/src/app/classes/storable-timer.ts index 1bf405432..1d0cfc6b6 100644 --- a/projects/player/src/app/classes/timer-state-variable.ts +++ b/projects/player/src/app/classes/storable-timer.ts @@ -1,19 +1,17 @@ import { EventEmitter } from '@angular/core'; import { ValueChangeElement } from 'common/models/elements/element'; +import { Storable } from 'player/src/app/classes/storable'; -export class TimerStateVariable { - id: string; - value: number; +export class StorableTimer extends Storable { duration: number; timerStateValueChanged = new EventEmitter<ValueChangeElement>(); timerStateEnded = new EventEmitter(); private interval: number = 0; - constructor(id: string, duration: number, value = 0) { - this.id = id; + constructor(id: string, duration: number, value: number = 0) { + super(id, value); this.duration = duration; - this.value = value; } run(): void { diff --git a/projects/player/src/app/classes/storable.spec.ts b/projects/player/src/app/classes/storable.spec.ts new file mode 100644 index 000000000..adf0ed559 --- /dev/null +++ b/projects/player/src/app/classes/storable.spec.ts @@ -0,0 +1,7 @@ +import { Storable } from './storable'; + +describe('Storable', () => { + it('should create an instance', () => { + expect(new Storable('test', 1)).toBeTruthy(); + }); +}); diff --git a/projects/player/src/app/classes/storable.ts b/projects/player/src/app/classes/storable.ts new file mode 100644 index 000000000..54c05c0ca --- /dev/null +++ b/projects/player/src/app/classes/storable.ts @@ -0,0 +1,9 @@ +export class Storable { + id: string; + value: number; + + constructor(id: string, value: number) { + this.id = id; + this.value = value; + } +} diff --git a/projects/player/src/app/classes/timer-state-variable.spec.ts b/projects/player/src/app/classes/timer-state-variable.spec.ts deleted file mode 100644 index 1e8af0f53..000000000 --- a/projects/player/src/app/classes/timer-state-variable.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { TimerStateVariable } from './timer-state-variable'; - -describe('State', () => { - it('should create an instance', () => { - expect(new TimerStateVariable('test', 0, 3000)).toBeTruthy(); - }); -}); diff --git a/projects/player/src/app/components/page/page.component.html b/projects/player/src/app/components/page/page.component.html index f8aa0610f..231600c01 100644 --- a/projects/player/src/app/components/page/page.component.html +++ b/projects/player/src/app/components/page/page.component.html @@ -3,7 +3,7 @@ [intersectionContainer]="pagesContainer" (intersecting)="selectedIndexChange.emit(scrollPageIndex)"> <aspect-section - *ngFor="let section of page.sections" + *ngFor="let section of page.sections; let i = index" class="section" [class.static-section]="!section.dynamicPositioning" [style.backgroundColor]="section.dynamicPositioning ? null : section.backgroundColor" @@ -11,6 +11,7 @@ [pageIndex]=pageIndex [section]="section" aspectSectionVisibilityHandling + [sectionIndex]="i" [pageSections]="page.sections"> </aspect-section> </div> diff --git a/projects/player/src/app/directives/section-visibility-handling.directive.ts b/projects/player/src/app/directives/section-visibility-handling.directive.ts index a197906ae..3586433c5 100644 --- a/projects/player/src/app/directives/section-visibility-handling.directive.ts +++ b/projects/player/src/app/directives/section-visibility-handling.directive.ts @@ -5,9 +5,10 @@ import { Subject } from 'rxjs'; import { Section } from 'common/models/section'; import { takeUntil } from 'rxjs/operators'; import { UnitStateService } from 'player/src/app/services/unit-state.service'; -import { TimerStateVariable } from 'player/src/app/classes/timer-state-variable'; +import { StorableTimer } from 'player/src/app/classes/storable-timer'; import { ValueChangeElement } from 'common/models/elements/element'; -import { ElementCode, ElementCodeStatusValue } from 'player/modules/verona/models/verona'; +import { ElementCode } from 'player/modules/verona/models/verona'; +import { Storable } from 'player/src/app/classes/storable'; @Directive({ selector: '[aspectSectionVisibilityHandling]' @@ -15,6 +16,8 @@ import { ElementCode, ElementCodeStatusValue } from 'player/modules/verona/model export class SectionVisibilityHandlingDirective implements OnInit, OnDestroy { @Input() section!: Section; @Input() pageSections!: Section[]; + @Input() pageIndex!: number; + @Input() sectionIndex!: number; private ngUnsubscribe = new Subject<void>(); private rulesAreFulfilled: boolean = false; @@ -31,7 +34,10 @@ export class SectionVisibilityHandlingDirective implements OnInit, OnDestroy { } private addSubscription(): void { - if (this.section.enableReHide || !this.hasSeenElements()) { + if (this.section.enableReHide || + (this.section.visibilityDelay && !this.isTimerStateFullFilled) || + (this.section.animatedVisibility && !this.isAnimatedVisibilityFullFilled) + ) { this.displayHiddenSection(); this.unitStateService.elementCodeChanged .pipe(takeUntil(this.ngUnsubscribe)) @@ -43,21 +49,36 @@ export class SectionVisibilityHandlingDirective implements OnInit, OnDestroy { } } + private get isTimerStateFullFilled(): boolean { + return this.unitStateService + .getElementCodeById(this.timerStateVariableId)?.value as number >= this.section.visibilityDelay; + } + + private get isAnimatedVisibilityFullFilled(): boolean { + return this.unitStateService + .getElementCodeById(this.animationVariableId)?.value === 1; + } + private isRuleCode(code: ElementCode): boolean { return this.section.visibilityRules .map(rule => rule.id) .some(id => id === code.id) || - (!!this.section.visibilityDelay && code.id === this.timerStateVariableId); + (!!this.section.visibilityDelay && code.id === this.timerStateVariableId) || + (this.section.animatedVisibility && code.id === this.animationVariableId); } private get timerStateVariableId(): string { - return `${this.section.visibilityRules[0].id}- - ${this.section.visibilityRules[0].value}- - ${this.section.visibilityDelay}`; + const firstRule = this.section.visibilityRules[0]; + return `${firstRule.id}-${firstRule.value}-${this.pageIndex}-${this.sectionIndex}-${this.section.visibilityDelay}`; + } + + private get animationVariableId(): string { + const firstRule = this.section.visibilityRules[0]; + return `${firstRule.id}-${firstRule.value}-${this.pageIndex}-${this.sectionIndex}-scroll-animation`; } private initTimerStateVariable(): void { - const timerStateVariable = new TimerStateVariable( + const timerStateVariable = new StorableTimer( this.timerStateVariableId, this.section.visibilityDelay ); this.unitStateService.registerElement(timerStateVariable.id, timerStateVariable.value); @@ -75,8 +96,7 @@ export class SectionVisibilityHandlingDirective implements OnInit, OnDestroy { this.rulesAreFulfilled = true; this.initTimerStateVariable(); } - this.setVisibility((this.unitStateService - .getElementCodeById(this.timerStateVariableId)?.value as number) >= this.section.visibilityDelay); + this.setVisibility(this.isTimerStateFullFilled); } else { this.setVisibility(true); } @@ -88,7 +108,9 @@ export class SectionVisibilityHandlingDirective implements OnInit, OnDestroy { private setVisibility(visible: boolean): void { this.elementRef.nativeElement.style.display = visible ? null : 'none'; if (visible) { - if (this.section.animatedVisibility && !this.hasSeenElements()) { + if (this.section.animatedVisibility && !this.isAnimatedVisibilityFullFilled) { + const animationVariable = new Storable(this.animationVariableId, 1); + this.unitStateService.registerElement(animationVariable.id, 1); this.scrollIntoView(); } if (!this.section.enableReHide) { @@ -146,13 +168,13 @@ export class SectionVisibilityHandlingDirective implements OnInit, OnDestroy { }); } - private hasSeenElements(): boolean { - return this.section.getAllElements() - .map(element => this.unitStateService.getElementCodeById(element.id)) - .some(code => (code ? - ElementCodeStatusValue[code.status] > ElementCodeStatusValue.NOT_REACHED : - false)); - } + // private hasSeenElements(): boolean { + // return this.section.getAllElements() + // .map(element => this.unitStateService.getElementCodeById(element.id)) + // .some(code => (code ? + // ElementCodeStatusValue[code.status] > ElementCodeStatusValue.NOT_REACHED : + // false)); + // } ngOnDestroy(): void { this.ngUnsubscribe.next(); diff --git a/projects/player/src/app/services/unit-state.service.ts b/projects/player/src/app/services/unit-state.service.ts index fc56c79fb..7a712246d 100644 --- a/projects/player/src/app/services/unit-state.service.ts +++ b/projects/player/src/app/services/unit-state.service.ts @@ -66,7 +66,7 @@ export class UnitStateService { this.setElementCodeValue(elementValue.id, elementValue.value); const unitStateElementCode = this.getElementCodeById(elementValue.id); if (unitStateElementCode) { - if (unitStateElementCode.status !== 'DERIVED') { + if (unitStateElementCode.status !== 'VIRTUAL') { this.setElementCodeStatus(elementValue.id, 'VALUE_CHANGED'); } else { this._elementCodeChanged.next(unitStateElementCode); @@ -152,12 +152,12 @@ export class UnitStateService { let unitStateElementCode = this.getElementCodeById(id); if (!unitStateElementCode) { // when reloading a unit, elementCodes are already pushed - const status = domElement ? 'NOT_REACHED' : 'DERIVED'; + const status = domElement ? 'NOT_REACHED' : 'VIRTUAL'; unitStateElementCode = { id, value, status }; this.elementCodes.push(unitStateElementCode); this._elementCodeChanged.next(unitStateElementCode); } else if (Object.keys(this.elementIdPageIndexMap).length === this.elementCodes - .filter(e => e.status !== 'DERIVED').length) { + .filter(e => e.status !== 'VIRTUAL').length) { // if all elements are registered, we can rebuild the presentedPages array this.buildPresentedPages(); } -- GitLab