diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.ts
index d4146f480c..08ca38bbb1 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.ts
@@ -60,6 +60,9 @@ export class CheckingQuestionComponent extends SubscriptionDisposable implements
if (doc?.data == null) {
return;
}
+ if (doc.id !== this._questionDoc?.id) {
+ this.stopAudio();
+ }
this._questionDoc = doc;
}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.html
index b2fbd57c92..66720af771 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.html
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.html
@@ -112,7 +112,7 @@
{{ t("filter_questions") }}
[matTooltipDisabled]="isAudioPlaying()"
(click)="toggleAudio()"
>
- {{ isAudioPlaying() ? "pause" : "play_circle_outline" }}
+ {{ isAudioPlaying() ? "stop" : "play_circle_outline" }}
@@ -128,12 +128,14 @@ {{ t("filter_questions") }}
-
+
{{ t("filter_questions") }}
[projectDoc]="projectDoc"
>
-
-
+
{{ t("filter_questions") }}
>
+
+
+
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.spec.ts
index 02ae82f013..f5b777cb23 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.spec.ts
@@ -212,15 +212,15 @@ describe('CheckingComponent', () => {
discardPeriodicTasks();
}));
- it('should re-calculate scripture slide position on resize', fakeAsync(() => {
+ it('should re-calculate scripture slide position on drag end', fakeAsync(() => {
const testProject: SFProject = TestEnvironment.generateTestProject();
- testProject.checkingConfig.hideCommunityCheckingText = true;
const env = new TestEnvironment({ user: CHECKER_USER, testProject });
env.waitForSliderUpdate();
- (env.component as any)._scriptureAreaMaxSize = 1;
- expect(env.component.scriptureAreaMaxSize).toEqual(1);
- window.dispatchEvent(new Event('resize'));
- expect(env.component.scriptureAreaMaxSize).toBeGreaterThan(1);
+ env.component.splitComponent?.setVisibleAreaSizes(['*', 1]);
+ expect(env.component.splitComponent?.getVisibleAreaSizes()[1]).toEqual(1);
+ env.component.checkSliderPosition({ sizes: ['*', 20] });
+ env.waitForSliderUpdate();
+ expect(env.component.splitComponent?.getVisibleAreaSizes()[1]).toBeGreaterThan(1);
flush();
discardPeriodicTasks();
}));
@@ -1500,7 +1500,7 @@ describe('CheckingComponent', () => {
env.simulateNewRemoteAnswer();
expect(env.showUnreadAnswersButton).toBeNull();
expect(env.answers.length).withContext('broken unrelated functionality').toEqual(0);
- // Incoming remote answer should have been absorbed into the set of i
+ // Incoming remote answer should have been absorbed into the set of
// answers pending to show, since user was looking at the Add Answer button
expect(env.component.answersPanel!.answers.length).toEqual(2);
// We don't show the total answer count in the heading until the user adds her answer.
@@ -2108,27 +2108,17 @@ describe('CheckingComponent', () => {
discardPeriodicTasks();
}));
- it('audio continues when changing question on the same chapter', fakeAsync(() => {
+ it('audio stops when changing question on the same chapter', fakeAsync(() => {
const env = new TestEnvironment({ user: ADMIN_USER, scriptureAudio: true });
const audio = env.mockScriptureAudioAndPlay();
env.selectQuestion(4);
- verify(audio.stop()).never();
+ verify(audio.stop()).once();
expect(env.component).toBeDefined();
flush();
}));
- it('audio continues when adding an answer on a question', fakeAsync(() => {
- const env = new TestEnvironment({ user: ADMIN_USER, scriptureAudio: true });
- const audio = env.mockScriptureAudioAndPlay();
-
- env.answerQuestion('Answer while audio is playing');
- env.waitForQuestionTimersToComplete();
- verify(audio.stop()).never();
- expect(env.component).toBeDefined();
- }));
-
it('pauses chapter audio when adding a question', fakeAsync(() => {
const env = new TestEnvironment({ user: ADMIN_USER, scriptureAudio: true });
const audio = env.mockScriptureAudioAndPlay();
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.ts
index 8e5c5e2b7c..ecc8f62f8f 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.ts
@@ -16,7 +16,7 @@ import { SFProjectRole } from 'realtime-server/lib/esm/scriptureforge/models/sf-
import { getTextAudioId } from 'realtime-server/lib/esm/scriptureforge/models/text-audio';
import { TextInfo } from 'realtime-server/lib/esm/scriptureforge/models/text-info';
import { toVerseRef, VerseRefData } from 'realtime-server/lib/esm/scriptureforge/models/verse-ref-data';
-import { asyncScheduler, combineLatest, fromEvent, merge, Subscription } from 'rxjs';
+import { asyncScheduler, combineLatest, merge, Subscription } from 'rxjs';
import { distinctUntilChanged, filter, map, startWith, throttleTime } from 'rxjs/operators';
import { DataLoadingComponent } from 'xforge-common/data-loading-component';
import { FeatureFlagService } from 'xforge-common/feature-flags/feature-flag.service';
@@ -107,7 +107,7 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
projectUserConfigDoc?: SFProjectUserConfigDoc;
textDocId?: TextDocId;
totalVisibleQuestionsString: string = '0';
- visibleQuestions?: QuestionDoc[];
+ visibleQuestions: Readonly;
showScriptureAudioPlayer: boolean = false;
hasQuestionWithoutAudio: boolean = false;
isCreatingNewQuestion: boolean = false;
@@ -157,7 +157,6 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
private text?: TextInfo;
private isProjectAdmin: boolean = false;
private _scriptureAudioPlayer?: CheckingScriptureAudioPlayerComponent;
- private _scriptureAreaMaxSize: number | null = null;
constructor(
private readonly activatedRoute: ActivatedRoute,
@@ -190,10 +189,6 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
return this.questionFilters.get(this.activeQuestionFilter);
}
- get bookName(): string {
- return this.text == null ? '' : this.i18n.localizeBook(this.text.bookNum);
- }
-
get chapter(): number | undefined {
return this._chapter;
}
@@ -214,10 +209,6 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
}
}
- get chapterStrings(): string[] {
- return this.chapters.map(c => c.toString());
- }
-
get isQuestionListPermanent(): boolean {
return this._isDrawerPermanent;
}
@@ -320,7 +311,7 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
return this._book;
}
- private set book(book: number | undefined) {
+ set book(book: number | undefined) {
if (book === this.book) {
return;
}
@@ -440,42 +431,17 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
);
}
- private get minAnswerPanelPercent(): number {
- return Math.ceil((this.answerPanelElementMinimumHeight / this.splitContainerElementHeight) * 100);
- }
- private get fullyExpandedAnswerPanelPercent(): number {
- return Math.ceil((this.fullyExpandedAnswerPanelHeight / this.splitContainerElementHeight) * 100);
- }
-
private get splitContainerElementHeight(): number {
return this.splitContainerElement && this.splitComponent
? this.splitContainerElement.nativeElement.offsetHeight - this.splitComponent.gutterSize!
: 0;
}
- private get contentPanelHeight(): number {
- return this.scripturePanelContainerElement?.nativeElement.offsetHeight;
- }
-
private get scriptureAudioPlayerAreaHeight(): number {
const scriptureAudioPlayerArea: Element | null = document.querySelector('.scripture-audio-player-wrapper');
return scriptureAudioPlayerArea == null ? 0 : scriptureAudioPlayerArea.getBoundingClientRect().height;
}
- /** Percentage of the vertical space of the as-splitter, needed by just the Scripture audio player. */
- private get scriptureAudioPlayerHeightPercent(): number {
- return (this.scriptureAudioPlayerAreaHeight / this.splitContainerElementHeight) * 100;
- }
-
- /** maxSize for as-split-area for the Scripture+audio area. */
- public get scriptureAreaMaxSize(): number | null {
- return this._scriptureAreaMaxSize;
- }
-
- private set scriptureAreaMaxSize(value: number | null) {
- this._scriptureAreaMaxSize = value;
- }
-
ngOnInit(): void {
this.subscribe(
combineLatest([this.activatedRoute.params, this.activatedRoute.queryParams]),
@@ -760,15 +726,6 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
this.isScreenSmall = state.matches;
}
);
-
- this.subscribe(fromEvent(window, 'resize'), () => {
- if (this.hideChapterText) {
- this.scriptureAreaMaxSize = this.scriptureAudioPlayerHeightPercent;
- if (this.contentPanelHeight > this.scriptureAudioPlayerAreaHeight) {
- this.calculateScriptureSliderPosition();
- }
- }
- });
}
ngOnDestroy(): void {
@@ -926,7 +883,7 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
checkSliderPosition(event: any): void {
if (event.hasOwnProperty('sizes')) {
- if (event.sizes[1] < this.minAnswerPanelPercent) {
+ if (event.sizes[1] < this.answerPanelElementMinimumHeight) {
this.calculateScriptureSliderPosition();
}
}
@@ -965,6 +922,9 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
if (this.onlineStatusService.isOnline) {
questionDoc.updateAnswerFileCache();
}
+ if (!this.hideChapterText && !(actionSource?.isQuestionListChange ?? false)) {
+ this.toggleAudio(true);
+ }
// Ensure navigation is set to book/chapter of selected question
if (this.navigateQuestionChapter(questionDoc)) {
@@ -1083,9 +1043,17 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
this.showScriptureAudioPlayer = this.hideChapterText;
}
- toggleAudio(): void {
- this.showScriptureAudioPlayer = true;
- this._scriptureAudioPlayer?.isPlaying ? this._scriptureAudioPlayer?.pause() : this._scriptureAudioPlayer?.play();
+ toggleAudio(forceStopAndHide: boolean = false): void {
+ this._scriptureAudioPlayer?.isPlaying || forceStopAndHide
+ ? this._scriptureAudioPlayer?.stop()
+ : this._scriptureAudioPlayer?.play();
+
+ this.showScriptureAudioPlayer =
+ this.hideChapterText || this._scriptureAudioPlayer?.isPlaying
+ ? true
+ : forceStopAndHide
+ ? false
+ : !this.showScriptureAudioPlayer;
}
/**
@@ -1397,27 +1365,19 @@ export class CheckingComponent extends DataLoadingComponent implements OnInit, A
// 100 ms is a speculative value for waiting for elements to be loaded and updated in the DOM.
const changeUpdateDelayMs: number = 100;
setTimeout(async () => {
- if (this.splitComponent == null) {
+ if (this.splitComponent == null || this.hideChapterText) {
return;
}
- if (this.hideChapterText) {
- const answerPanelHeight = 100 - this.scriptureAudioPlayerHeightPercent;
- this.splitComponent?.setVisibleAreaSizes([this.scriptureAudioPlayerHeightPercent, answerPanelHeight]);
- this.scriptureAreaMaxSize = this.scriptureAudioPlayerHeightPercent;
+ let answerPanelHeight: number;
+ if (maximizeAnswerPanel) {
+ answerPanelHeight = Math.min(this.splitContainerElementHeight * 0.75, this.fullyExpandedAnswerPanelHeight);
} else {
- let answerPanelHeight: number;
- if (maximizeAnswerPanel) {
- answerPanelHeight = this.fullyExpandedAnswerPanelPercent;
- } else {
- answerPanelHeight = this.minAnswerPanelPercent;
- }
-
- answerPanelHeight = Math.min(75, answerPanelHeight);
- const scripturePanelHeight = 100 - answerPanelHeight;
-
- this.splitComponent.setVisibleAreaSizes([scripturePanelHeight, answerPanelHeight]);
- this.scriptureAreaMaxSize = null;
+ answerPanelHeight = this.answerPanelElementMinimumHeight;
}
+ this.splitComponent.setVisibleAreaSizes([
+ '*',
+ this.showScriptureAudioPlayer ? this.scriptureAudioPlayerAreaHeight : answerPanelHeight
+ ]);
}, changeUpdateDelayMs);
}