Skip to content

Commit 5b05940

Browse files
committed
MOBILE-4792 quiz: Add infinite loading in quiz review page
1 parent 452d30b commit 5b05940

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

src/addons/mod/quiz/pages/review/review.html

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ <h1>{{ 'addon.mod_quiz.review' | translate }}</h1>
3939
[contextInstanceId]="cmId" [courseId]="courseId" [review]="true" [preferredBehaviour]="quiz?.preferredbehaviour" />
4040
</addon-mod-quiz-question-card>
4141
</ng-container>
42+
43+
<core-infinite-loading *ngIf="showAll" [enabled]="canLoadMore" (action)="loadMore($event)" />
4244
</ng-container>
4345

4446
<div collapsible-footer appearOnBottom *ngIf="loaded && numPages > 1" slot="fixed">

src/addons/mod/quiz/pages/review/review.ts

+53-6
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ import { AddonModQuizQuestionCardComponent } from '../../components/question-car
4141
import { AddonModQuizAttemptInfoComponent } from '../../components/attempt-info/attempt-info';
4242
import { CoreSharedModule } from '@/core/shared.module';
4343
import { CoreQuestionComponent } from '@features/question/components/question/question';
44+
import { CoreWait } from '@singletons/wait';
45+
import { CoreLoadings } from '@services/overlays/loadings';
4446

4547
/**
4648
* Page that allows reviewing a quiz attempt.
@@ -60,6 +62,8 @@ export default class AddonModQuizReviewPage implements OnInit {
6062

6163
@ViewChild(IonContent) content?: IonContent;
6264

65+
protected static readonly QUESTIONS_PER_LOAD_WHEN_SHOW_ALL = 10;
66+
6367
attempt?: AddonModQuizAttemptWSData; // The attempt being reviewed.
6468
component = ADDON_MOD_QUIZ_COMPONENT_LEGACY; // Component to link the files to.
6569
showAll = false; // Whether to view all questions in the same page.
@@ -78,6 +82,8 @@ export default class AddonModQuizReviewPage implements OnInit {
7882
quiz?: AddonModQuizQuizWSData; // The quiz the attempt belongs to.
7983
courseId!: number; // The course ID the quiz belongs to.
8084
cmId!: number; // Course module id the attempt belongs to.
85+
canLoadMore = false;
86+
allQuestions: CoreQuestionQuestionForView[] = []; // When using infinite loading, this will contain all the questions.
8187

8288
protected attemptId!: number; // The attempt being reviewed.
8389
protected currentPage!: number; // The current page being reviewed.
@@ -123,12 +129,12 @@ export default class AddonModQuizReviewPage implements OnInit {
123129
* @param slot Slot of the question to scroll to.
124130
*/
125131
async changePage(page: number, slot?: number): Promise<void> {
126-
if (slot !== undefined && (this.attempt?.currentpage == -1 || page == this.currentPage)) {
132+
if (slot !== undefined && (this.attempt?.currentpage === -1 || page === this.currentPage)) {
127133
// Scrol to a certain question in the current page.
128134
this.scrollToQuestion(slot);
129135

130136
return;
131-
} else if (page == this.currentPage) {
137+
} else if (page === this.currentPage) {
132138
// If the user is navigating to the current page and no question specified, we do nothing.
133139
return;
134140
}
@@ -195,9 +201,15 @@ export default class AddonModQuizReviewPage implements OnInit {
195201
this.additionalData = data.additionaldata;
196202
this.currentPage = page;
197203

198-
this.questions = data.questions;
199-
this.nextPage = page + 1;
200-
this.previousPage = page - 1;
204+
if (page === -1) {
205+
this.allQuestions = data.questions;
206+
this.questions = data.questions.slice(0, AddonModQuizReviewPage.QUESTIONS_PER_LOAD_WHEN_SHOW_ALL);
207+
this.canLoadMore = this.allQuestions.length > this.questions.length;
208+
} else {
209+
this.questions = data.questions;
210+
this.nextPage = page + 1;
211+
this.previousPage = page - 1;
212+
}
201213

202214
this.questions.forEach((question) => {
203215
// Get the readable mark for each question.
@@ -208,6 +220,21 @@ export default class AddonModQuizReviewPage implements OnInit {
208220
});
209221
}
210222

223+
/**
224+
* Show more questions (only used when showing all the questions at the same time).
225+
*
226+
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
227+
*/
228+
loadMore(infiniteComplete?: () => void): void {
229+
this.questions = this.questions.concat(this.allQuestions.slice(
230+
this.questions.length,
231+
this.questions.length + AddonModQuizReviewPage.QUESTIONS_PER_LOAD_WHEN_SHOW_ALL,
232+
));
233+
this.canLoadMore = this.allQuestions.length > this.questions.length;
234+
235+
infiniteComplete?.();
236+
}
237+
211238
/**
212239
* Load data to navigate the questions using the navigation modal.
213240
*/
@@ -253,7 +280,27 @@ export default class AddonModQuizReviewPage implements OnInit {
253280
*
254281
* @param slot Slot of the question to scroll to.
255282
*/
256-
protected scrollToQuestion(slot: number): void {
283+
protected async scrollToQuestion(slot: number): Promise<void> {
284+
if (this.showAll && this.canLoadMore) {
285+
// First make sure that the question is visible.
286+
const pageIndex = this.allQuestions.findIndex(question => question.slot === slot);
287+
if (pageIndex > this.questions.length) {
288+
// Not visible, load the needed questions.
289+
// Show a loading modal because if there are a lot of questions to load it can take a few seconds to render.
290+
const loading = await CoreLoadings.show();
291+
292+
const lastQuestionToLoad = Math.ceil(pageIndex / AddonModQuizReviewPage.QUESTIONS_PER_LOAD_WHEN_SHOW_ALL) *
293+
AddonModQuizReviewPage.QUESTIONS_PER_LOAD_WHEN_SHOW_ALL;
294+
this.questions = this.questions.concat(this.allQuestions.slice(this.questions.length, lastQuestionToLoad));
295+
this.canLoadMore = this.allQuestions.length > this.questions.length;
296+
297+
// Wait some ticks to let the questions render, otherwise the scroll might end up in a wrong position.
298+
await CoreWait.nextTicks(5);
299+
await loading.dismiss();
300+
await CoreWait.nextTick(); // For some reason scrolling doesn't work right after dismiss, wait a tick.
301+
}
302+
}
303+
257304
CoreDom.scrollToElement(
258305
this.elementRef.nativeElement,
259306
`#addon-mod_quiz-question-${slot}`,

0 commit comments

Comments
 (0)