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 @@
-
+
+