From ad45289f4bcd88f44e66df310111d12010ba8a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Wed, 13 Oct 2021 17:11:47 +0200 Subject: [PATCH] MOBILE-3686 courses: Add download options to course list item --- .../core-courses-course-list-item.html | 10 ++ .../course-list-item/course-list-item.ts | 112 +++++++++++++++++- .../course-progress/course-progress.ts | 5 +- .../features/courses/pages/list/list.html | 3 +- 4 files changed, 122 insertions(+), 8 deletions(-) diff --git a/src/core/features/courses/components/course-list-item/core-courses-course-list-item.html b/src/core/features/courses/components/course-list-item/core-courses-course-list-item.html index 0d81bc533..425d8e3f3 100644 --- a/src/core/features/courses/components/course-list-item/core-courses-course-list-item.html +++ b/src/core/features/courses/components/course-list-item/core-courses-course-list-item.html @@ -34,4 +34,14 @@ slot="end"> + +
+ +
diff --git a/src/core/features/courses/components/course-list-item/course-list-item.ts b/src/core/features/courses/components/course-list-item/course-list-item.ts index e4248e0e3..6d4da5a97 100644 --- a/src/core/features/courses/components/course-list-item/course-list-item.ts +++ b/src/core/features/courses/components/course-list-item/course-list-item.ts @@ -12,8 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, Input, OnInit } from '@angular/core'; -import { CoreCourseHelper } from '@features/course/services/course-helper'; +import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { CoreCourseProvider, CoreCourse } from '@features/course/services/course'; +import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; @@ -33,15 +34,26 @@ import { CoreCoursesHelper } from '../../services/courses-helper'; templateUrl: 'core-courses-course-list-item.html', styleUrls: ['course-list-item.scss'], }) -export class CoreCoursesCourseListItemComponent implements OnInit { +export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, OnChanges { @Input() course!: CoreCourseListItem; // The course to render. + @Input() showDownload = false; // If true, will show download button. + icons: CoreCoursesEnrolmentIcons[] = []; isEnrolled = false; + prefetchCourseData: CorePrefetchStatusInfo = { + icon: '', + statusTranslatable: 'core.loading', + status: '', + loading: true, + }; + + protected courseStatusObserver?: CoreEventObserver; + protected isDestroyed = false; /** - * Component being initialized. + * @inheritdoc */ async ngOnInit(): Promise { CoreCoursesHelper.loadCourseColorAndImage(this.course); @@ -55,6 +67,10 @@ export class CoreCoursesCourseListItemComponent implements OnInit { this.course.completionusertracked = course.completionusertracked; this.isEnrolled = true; + + if (this.showDownload) { + this.initPrefetchCourse(); + } } catch { this.isEnrolled = false; } @@ -91,6 +107,15 @@ export class CoreCoursesCourseListItemComponent implements OnInit { } } + /** + * @inheritdoc + */ + ngOnChanges(): void { + if (this.showDownload && this.isEnrolled) { + this.initPrefetchCourse(); + } + } + /** * Open a course. * @@ -107,6 +132,85 @@ export class CoreCoursesCourseListItemComponent implements OnInit { } } + /** + * Initialize prefetch course. + */ + async initPrefetchCourse(): Promise { + if (this.courseStatusObserver !== undefined) { + // Already initialized. + return; + } + + // Listen for status change in course. + this.courseStatusObserver = CoreEvents.on(CoreEvents.COURSE_STATUS_CHANGED, (data: CoreEventCourseStatusChanged) => { + if (data.courseId == this.course.id || data.courseId == CoreCourseProvider.ALL_COURSES_CLEARED) { + this.updateCourseStatus(data.status); + } + }, CoreSites.getCurrentSiteId()); + + // Determine course prefetch icon. + const status = await CoreCourse.getCourseStatus(this.course.id); + + this.updateCourseStatus(status); + + if (this.prefetchCourseData.loading) { + // Course is being downloaded. Get the download promise. + const promise = CoreCourseHelper.getCourseDownloadPromise(this.course.id); + if (promise) { + // There is a download promise. If it fails, show an error. + promise.catch((error) => { + if (!this.isDestroyed) { + CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true); + } + }); + } else { + // No download, this probably means that the app was closed while downloading. Set previous status. + CoreCourse.setCoursePreviousStatus(this.course.id); + } + } + + } + + /** + * Update the course status icon and title. + * + * @param status Status to show. + */ + protected updateCourseStatus(status: string): void { + const statusData = CoreCourseHelper.getCoursePrefetchStatusInfo(status); + + this.prefetchCourseData.status = statusData.status; + this.prefetchCourseData.icon = statusData.icon; + this.prefetchCourseData.statusTranslatable = statusData.statusTranslatable; + this.prefetchCourseData.loading = statusData.loading; + } + + /** + * Prefetch the course. + * + * @param e Click event. + */ + async prefetchCourse(e?: Event): Promise { + e?.preventDefault(); + e?.stopPropagation(); + + try { + await CoreCourseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course); + } catch (error) { + if (!this.isDestroyed) { + CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true); + } + } + } + + /** + * @inheritdoc + */ + ngOnDestroy(): void { + this.isDestroyed = true; + this.courseStatusObserver?.off(); + } + } /** diff --git a/src/core/features/courses/components/course-progress/course-progress.ts b/src/core/features/courses/components/course-progress/course-progress.ts index c4892208b..ece9a9b50 100644 --- a/src/core/features/courses/components/course-progress/course-progress.ts +++ b/src/core/features/courses/components/course-progress/course-progress.ts @@ -48,8 +48,6 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy, On @Input() showAll = false; // If true, will show all actions, options, star and progress. @Input() showDownload = true; // If true, will show download button. Only works if the options menu is not shown. - courseStatus = CoreConstants.NOT_DOWNLOADED; - isDownloading = false; prefetchCourseData: CorePrefetchStatusInfo = { icon: '', statusTranslatable: 'core.loading', @@ -64,6 +62,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy, On progress = -1; completionUserTracked: boolean | undefined = false; + protected courseStatus = CoreConstants.NOT_DOWNLOADED; protected isDestroyed = false; protected courseStatusObserver?: CoreEventObserver; protected siteUpdatedObserver?: CoreEventObserver; @@ -109,7 +108,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy, On * Initialize prefetch course. */ async initPrefetchCourse(): Promise { - if (typeof this.courseStatusObserver != 'undefined') { + if (this.courseStatusObserver !== undefined) { // Already initialized. return; } diff --git a/src/core/features/courses/pages/list/list.html b/src/core/features/courses/pages/list/list.html index fe2dbc491..838ce9ae1 100644 --- a/src/core/features/courses/pages/list/list.html +++ b/src/core/features/courses/pages/list/list.html @@ -34,7 +34,8 @@ - + +