From 96c562eec4c74443ff0251111a936d8e57cb5005 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Mon, 21 Mar 2022 14:57:24 +0100 Subject: [PATCH 1/2] MOBILE-3833 course: Improve load time of course summary --- .../pages/course-summary/course-summary.ts | 128 +++++++++++------- 1 file changed, 81 insertions(+), 47 deletions(-) diff --git a/src/core/features/course/pages/course-summary/course-summary.ts b/src/core/features/course/pages/course-summary/course-summary.ts index a34255bfa..21a7de434 100644 --- a/src/core/features/course/pages/course-summary/course-summary.ts +++ b/src/core/features/course/pages/course-summary/course-summary.ts @@ -38,6 +38,7 @@ import { CoreCoursesHelper, CoreCourseWithImageAndColor } from '@features/course import { Subscription } from 'rxjs'; import { CoreColors } from '@singletons/colors'; import { CoreText } from '@singletons/text'; +import { CorePromisedValue } from '@classes/promised-value'; /** * Page that shows the summary of a course including buttons to enrol and other available options. @@ -70,7 +71,8 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = []; protected useGuestAccess = false; - protected guestInstanceId?: number; + protected guestInstanceId = new CorePromisedValue(); + protected courseData = new CorePromisedValue(); protected waitStart = 0; protected enrolUrl = ''; protected pageDestroyed = false; @@ -130,11 +132,12 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { * password is required for guest access. */ protected async canAccessAsGuest(): Promise { - if (this.guestInstanceId === undefined) { + const guestInstanceId = await this.guestInstanceId; + if (guestInstanceId === undefined) { return false; } - const info = await CoreCourses.getCourseGuestEnrolmentInfo(this.guestInstanceId); + const info = await CoreCourses.getCourseGuestEnrolmentInfo(guestInstanceId); // Guest access with password is not supported by the app. return !!info.status && !info.passwordrequired; @@ -146,32 +149,70 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { * @param refresh If it's refreshing content. */ protected async getCourse(refresh = false): Promise { - // Get course enrolment methods. - this.selfEnrolInstances = []; this.otherEnrolments = false; try { - const enrolmentMethods = await CoreCourses.getCourseEnrolmentMethods(this.courseId); - this.guestInstanceId = undefined; - - enrolmentMethods.forEach((method) => { - if (!method.status) { - return; - } - - if (method.type === 'self') { - this.selfEnrolInstances.push(method); - } else if (method.type === 'guest') { - this.guestInstanceId = method.id; - } else { - // Other enrolments that comes from that WS should need user action. - this.otherEnrolments = true; - } - }); + await Promise.all([ + this.getEnrolmentMethods(), + this.getCourseData(), + this.loadCourseExtraData(), + ]); } catch (error) { CoreDomUtils.showErrorModalDefault(error, 'Error getting enrolment data'); } + await this.setCourseColor(); + + if (!this.course || + !('progress' in this.course) || + typeof this.course.progress !== 'number' || + this.course.progress < 0 || + this.course.completionusertracked === false + ) { + this.progress = undefined; + } else { + this.progress = this.course.progress; + } + + await this.loadMenuHandlers(refresh); + + this.dataLoaded = true; + } + + /** + * Get course enrolment methods. + */ + protected async getEnrolmentMethods(): Promise { + this.selfEnrolInstances = []; + this.guestInstanceId.reset(); + + const enrolmentMethods = await CoreCourses.getCourseEnrolmentMethods(this.courseId); + + enrolmentMethods.forEach((method) => { + if (!method.status) { + return; + } + + if (method.type === 'self') { + this.selfEnrolInstances.push(method); + } else if (method.type === 'guest') { + this.guestInstanceId.resolve(method.id); + } else { + // Other enrolments that comes from that WS should need user action. + this.otherEnrolments = true; + } + }); + + if (!this.guestInstanceId.isSettled()) { + // No guest instance found. + this.guestInstanceId.resolve(undefined); + } + } + + /** + * Get course data. + */ + protected async getCourseData(): Promise { try { // Check if user is enrolled in the course. try { @@ -192,16 +233,26 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { this.useGuestAccess = this.canAccessCourse; } + this.courseData.resolve(this.course); + } + + /** + * Load some extra data for the course. + */ + protected async loadCourseExtraData(): Promise { try { const courseByField = await CoreCourses.getCourseByField('id', this.courseId); - if (this.course) { - this.course.customfields = courseByField.customfields; - this.course.contacts = courseByField.contacts; - this.course.displayname = courseByField.displayname; - this.course.categoryname = courseByField.categoryname; - this.course.overviewfiles = courseByField.overviewfiles; + const courseData = await this.courseData; + + if (courseData) { + courseData.customfields = courseByField.customfields; + courseData.contacts = courseByField.contacts; + courseData.displayname = courseByField.displayname; + courseData.categoryname = courseByField.categoryname; + courseData.overviewfiles = courseByField.overviewfiles; } else { this.course = courseByField; + this.courseData.resolve(courseByField); } // enrollmentmethods contains ALL enrolment methods including manual. @@ -212,23 +263,6 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { } catch { // Ignore errors. } - - await this.setCourseColor(); - - if (!this.course || - !('progress' in this.course) || - typeof this.course.progress !== 'number' || - this.course.progress < 0 || - this.course.completionusertracked === false - ) { - this.progress = undefined; - } else { - this.progress = this.course.progress; - } - - await this.loadMenuHandlers(refresh); - - this.dataLoaded = true; } /** @@ -375,8 +409,8 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { promises.push(CoreCourses.invalidateCourseEnrolmentMethods(this.courseId)); promises.push(CoreCourseOptionsDelegate.clearAndInvalidateCoursesOptions(this.courseId)); promises.push(CoreCourses.invalidateCoursesByField('id', this.courseId)); - if (this.guestInstanceId) { - promises.push(CoreCourses.invalidateCourseGuestEnrolmentInfo(this.guestInstanceId)); + if (this.guestInstanceId.value) { + promises.push(CoreCourses.invalidateCourseGuestEnrolmentInfo(this.guestInstanceId.value)); } await Promise.all(promises).finally(() => this.getCourse()).finally(() => { From d2b9cf89d87de59f2356dc51675e3533dbcea615 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 22 Mar 2022 15:48:49 +0100 Subject: [PATCH 2/2] MOBILE-3833 module: Improve performance of getModuleStoredSize --- .../services/module-prefetch-delegate.ts | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/core/features/course/services/module-prefetch-delegate.ts b/src/core/features/course/services/module-prefetch-delegate.ts index d75e36759..1556a75da 100644 --- a/src/core/features/course/services/module-prefetch-delegate.ts +++ b/src/core/features/course/services/module-prefetch-delegate.ts @@ -482,23 +482,17 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { - let downloadedSize = await this.getModuleDownloadedSize(module, courseId); - - if (isNaN(downloadedSize)) { - downloadedSize = 0; - } - const site = CoreSites.getCurrentSite(); const handler = this.getPrefetchHandlerFor(module.modname); - if (!handler || !site) { - // If there is no handler then we can't find out the component name. - // We can't work out the cached size, so just return downloaded size. - return downloadedSize; - } - const cachedSize = await site.getComponentCacheSize(handler.component, module.id); + const [downloadedSize, cachedSize] = await Promise.all([ + this.getModuleDownloadedSize(module, courseId), + handler && site ? site.getComponentCacheSize(handler.component, module.id) : 0, + ]); - return cachedSize + downloadedSize; + const totalSize = cachedSize + downloadedSize; + + return isNaN(totalSize) ? 0 : totalSize; } /**