MOBILE-3814 course: Improve course list item performance

main
Pau Ferrer Ocaña 2022-02-10 22:06:32 +01:00
parent 54deab86f8
commit a129a6df9f
4 changed files with 34 additions and 57 deletions

View File

@ -6,12 +6,27 @@
<img *ngIf="course.courseImage" [src]="course.courseImage" core-external-content alt="" />
<ion-icon *ngIf="!course.courseImage" name="fas-graduation-cap" class="course-icon">
</ion-icon>
<ng-container
*ngIf="isEnrolled && ((downloadCourseEnabled && !courseOptionMenuEnabled && showDownload) || courseOptionMenuEnabled)">
<ng-container *ngTemplateOutlet="download"></ng-container>
</ng-container>
</div>
<ng-container *ngIf="isEnrolled && layout != 'summarycard'">
<div class="core-button-spinner" *ngIf="!courseOptionMenuEnabled && showDownload">
<core-download-refresh [status]="prefetchCourseData.status" [enabled]="showDownload"
[statusTranslatable]="prefetchCourseData.statusTranslatable" [canTrustDownload]="false"
[loading]="prefetchCourseData.loading" (action)="prefetchCourse()"></core-download-refresh>
</div>
<div class="core-button-spinner" *ngIf="courseOptionMenuEnabled">
<!-- Options menu. -->
<ion-button fill="clear" color="dark" (click)="showCourseOptionsMenu($event)" *ngIf="!showSpinner"
[attr.aria-label]="('core.displayoptions' | translate)">
<ion-icon name="ellipsis-vertical" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
<!-- Loading options course spinner. -->
<ion-spinner *ngIf="showSpinner" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>
</ng-container>
<ion-item class="ion-text-wrap" button detail="false" (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname"
[class.item-disabled]="course.visible == 0">
@ -46,8 +61,8 @@
</ion-icon>
</span>
<ion-icon *ngIf="downloadCourseEnabled && prefetchCourseData.downloadSucceeded" class="core-icon-downloaded"
name="cloud-done" color="success" role="status" [attr.aria-label]="'core.downloaded' | translate"></ion-icon>
<ion-icon *ngIf="prefetchCourseData.downloadSucceeded" class="core-icon-downloaded" name="cloud-done" color="success"
role="status" [attr.aria-label]="'core.downloaded' | translate"></ion-icon>
</p>
<ion-chip color="brand" *ngIf="course.categoryname"
@ -63,30 +78,7 @@
class="core-course-progress">
<core-progress-bar [progress]="progress" a11yText="core.courses.aria:courseprogress"></core-progress-bar>
</div>
<ng-container *ngIf="layout == 'list' || layout == 'listwithenrol' && isEnrolled">
<ng-container *ngTemplateOutlet="download"></ng-container>
</ng-container>
</ion-label>
</ion-item>
</ion-card>
<ng-template #download>
<div class="core-button-spinner" *ngIf="downloadCourseEnabled && !courseOptionMenuEnabled && showDownload">
<core-download-refresh [status]="prefetchCourseData.status" [enabled]="downloadCourseEnabled"
[statusTranslatable]="prefetchCourseData.statusTranslatable" [canTrustDownload]="false" [loading]="prefetchCourseData.loading"
(action)="prefetchCourse()"></core-download-refresh>
</div>
<div class="core-button-spinner" *ngIf="courseOptionMenuEnabled">
<!-- Options menu. -->
<ion-button fill="clear" color="dark" (click)="showCourseOptionsMenu($event)" *ngIf="!showSpinner"
[attr.aria-label]="('core.displayoptions' | translate)">
<ion-icon name="ellipsis-vertical" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
<!-- Loading options course spinner. -->
<ion-spinner *ngIf="showSpinner" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>
</ng-template>

View File

@ -54,6 +54,7 @@ ion-card {
display: flex;
flex-direction: column;
align-items: center;
z-index: 2;
ion-spinner {
margin-top: 4px;
@ -156,7 +157,7 @@ ion-card.core-course-list-card {
ion-icon.course-icon {
color: white;
opacity: 50%;
opacity: 0.5;
position: absolute;
left: 0;
right: 0;

View File

@ -55,7 +55,6 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
};
showSpinner = false;
downloadCourseEnabled = false;
courseOptionMenuEnabled = false;
progress = -1;
completionUserTracked: boolean | undefined = false;
@ -63,7 +62,6 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
protected courseStatus = CoreConstants.NOT_DOWNLOADED;
protected isDestroyed = false;
protected courseStatusObserver?: CoreEventObserver;
protected siteUpdatedObserver?: CoreEventObserver;
protected element: HTMLElement;
@ -93,31 +91,12 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
}
if (this.isEnrolled) {
if (this.showDownload) {
this.initPrefetchCourse();
}
this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite();
if (this.downloadCourseEnabled) {
this.initPrefetchCourse();
}
// This field is only available from 3.6 onwards.
this.courseOptionMenuEnabled = (this.layout != 'listwithenrol' && this.layout != 'summarycard') &&
this.course.isfavourite !== undefined;
// Refresh the enabled flag if site is updated.
this.siteUpdatedObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
const wasEnabled = this.downloadCourseEnabled;
this.initPrefetchCourse();
this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite();
if (!wasEnabled && this.downloadCourseEnabled) {
// Download course is enabled now, initialize it.
this.initPrefetchCourse();
}
}, CoreSites.getCurrentSiteId());
} else if ('enrollmentmethods' in this.course) {
this.enrolmentIcons = [];
@ -169,9 +148,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
* @inheritdoc
*/
ngOnChanges(): void {
if (this.showDownload && this.isEnrolled) {
this.initPrefetchCourse();
}
this.initPrefetchCourse();
this.updateCourseFields();
}
@ -203,7 +180,12 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
/**
* Initialize prefetch course.
*/
async initPrefetchCourse(): Promise<void> {
async initPrefetchCourse(forceInit = false): Promise<void> {
if (!this.isEnrolled || !this.showDownload ||
(this.courseOptionMenuEnabled && !forceInit)) {
return;
}
if (this.courseStatusObserver !== undefined) {
// Already initialized.
return;
@ -306,6 +288,8 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
event.preventDefault();
event.stopPropagation();
this.initPrefetchCourse(true);
const popoverData = await CoreDomUtils.openPopover<string>({
component: CoreCoursesCourseOptionsMenuComponent,
componentProps: {
@ -414,7 +398,6 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
ngOnDestroy(): void {
this.isDestroyed = true;
this.courseStatusObserver?.off();
this.siteUpdatedObserver?.off();
}
}

View File

@ -201,6 +201,7 @@ ion-header ion-toolbar {
.in-toolbar.button-clear {
--color: var(--core-header-toolbar-color);
--ion-toolbar-color: var(--core-header-toolbar-color);
--border-radius: var(--huge-radius);
}
.button.button-clear,