MOBILE-3833 course: Improve performance after download or delete
parent
1a07331396
commit
37af8e3c69
|
@ -25,8 +25,8 @@
|
|||
<p class="item-heading ion-text-wrap">{{ 'addon.storagemanager.totaldownloads' | translate }}</p>
|
||||
</ion-label>
|
||||
<ion-badge color="light" slot="end">
|
||||
<ng-container *ngIf="sizeLoaded">{{ totalSize | coreBytesToSize }}</ng-container>
|
||||
<ng-container *ngIf="!sizeLoaded">{{ 'core.calculating' | translate }}</ng-container>
|
||||
<ng-container *ngIf="!calculatingSize">{{ totalSize | coreBytesToSize }}</ng-container>
|
||||
<ng-container *ngIf="calculatingSize">{{ 'core.calculating' | translate }}</ng-container>
|
||||
</ion-badge>
|
||||
</ion-item>
|
||||
<ion-button *ngIf="downloadCourseEnabled" (click)="prefetchCourse()" expand="block" fill="outline" class="ion-no-margin"
|
||||
|
@ -35,7 +35,7 @@
|
|||
<ion-spinner *ngIf="prefetchCourseData.loading" slot="start"></ion-spinner>
|
||||
{{ prefetchCourseData.statusTranslatable | translate }}
|
||||
</ion-button>
|
||||
<ion-button *ngIf="sizeLoaded && totalSize > 0" (click)="deleteForCourse()" expand="block" color="danger"
|
||||
<ion-button [disabled]="calculatingSize || totalSize <= 0" (click)="deleteForCourse()" expand="block" color="danger"
|
||||
class="ion-no-margin ion-margin-top">
|
||||
<ion-icon name="fas-trash" slot="start" [attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate:
|
||||
{ name: title }">
|
||||
|
@ -55,12 +55,12 @@
|
|||
</core-format-text>
|
||||
</p>
|
||||
<ion-badge [color]="section.downloadStatus == statusDownloaded ? 'success' : 'light'"
|
||||
*ngIf="section.sizeLoaded && section.totalSize > 0">
|
||||
*ngIf="!section.calculatingSize && section.totalSize > 0">
|
||||
<ion-icon name="fam-cloud-done" *ngIf="section.downloadStatus == statusDownloaded"
|
||||
[attr.aria-label]="'core.downloaded' | translate">
|
||||
</ion-icon>{{ section.totalSize | coreBytesToSize }}
|
||||
</ion-badge>
|
||||
<ion-badge color="light" *ngIf="!section.sizeLoaded">
|
||||
<ion-badge color="light" *ngIf="section.calculatingSize">
|
||||
{{ 'core.calculating' | translate }}
|
||||
</ion-badge>
|
||||
<!-- Download progress. -->
|
||||
|
@ -69,7 +69,8 @@
|
|||
</core-progress-bar>
|
||||
</p>
|
||||
</ion-label>
|
||||
<div class="storage-buttons" slot="end" *ngIf="(section.sizeLoaded && section.totalSize > 0) || downloadEnabled">
|
||||
<div class="storage-buttons" slot="end"
|
||||
*ngIf="(!section.calculatingSize && section.totalSize > 0) || downloadEnabled">
|
||||
<div *ngIf="downloadEnabled" slot="end" class="core-button-spinner">
|
||||
<core-download-refresh *ngIf="!section.isDownloading && section.downloadStatus != statusDownloaded"
|
||||
[status]="section.downloadStatus" [enabled]="true" (action)="prefecthSection(section)"
|
||||
|
@ -83,7 +84,7 @@
|
|||
{{section.count}} / {{section.total}}
|
||||
</ion-badge>
|
||||
</div>
|
||||
<ion-button (click)="deleteForSection(section)" *ngIf="section.sizeLoaded && section.totalSize > 0"
|
||||
<ion-button (click)="deleteForSection(section)" *ngIf="!section.calculatingSize && section.totalSize > 0"
|
||||
color="danger" fill="clear">
|
||||
<ion-icon name="fas-trash" slot="icon-only"
|
||||
[attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: { name: section.name }">
|
||||
|
@ -95,7 +96,7 @@
|
|||
<ion-card-content>
|
||||
<ng-container *ngFor="let module of section.modules">
|
||||
<ion-item class="ion-no-padding core-course-storage-activity"
|
||||
*ngIf="downloadEnabled || (module.sizeLoaded && module.totalSize > 0)">
|
||||
*ngIf="downloadEnabled || (!module.calculatingSize && module.totalSize > 0)">
|
||||
<core-mod-icon slot="start" *ngIf="module.handlerData.icon" [modicon]="module.handlerData.icon"
|
||||
[modname]="module.modname" [componentId]="module.instance">
|
||||
</core-mod-icon>
|
||||
|
@ -106,12 +107,12 @@
|
|||
</core-format-text>
|
||||
</h3>
|
||||
<ion-badge [color]="module.downloadStatus == statusDownloaded ? 'success' : 'light'"
|
||||
*ngIf="module.sizeLoaded && module.totalSize > 0">
|
||||
*ngIf="!module.calculatingSize && module.totalSize > 0">
|
||||
<ion-icon name="fam-cloud-done" *ngIf="module.downloadStatus == statusDownloaded"
|
||||
[attr.aria-label]="'core.downloaded' | translate">
|
||||
</ion-icon>{{ module.totalSize | coreBytesToSize }}
|
||||
</ion-badge>
|
||||
<ion-badge color="light" *ngIf="!module.sizeLoaded">
|
||||
<ion-badge color="light" *ngIf="module.calculatingSize">
|
||||
{{ 'core.calculating' | translate }}
|
||||
</ion-badge>
|
||||
</ion-label>
|
||||
|
@ -123,7 +124,7 @@
|
|||
(action)="prefetchModule(module, section)">
|
||||
</core-download-refresh>
|
||||
<ion-button fill="clear" (click)="deleteForModule(module, section)"
|
||||
*ngIf="module.sizeLoaded && module.totalSize > 0" color="danger">
|
||||
*ngIf="!module.calculatingSize && module.totalSize > 0" color="danger">
|
||||
<ion-icon name="fas-trash" slot="icon-only"
|
||||
[attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: { name: module.name }">
|
||||
</ion-icon>
|
||||
|
|
|
@ -48,7 +48,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
loaded = false;
|
||||
sections: AddonStorageManagerCourseSection[] = [];
|
||||
totalSize = 0;
|
||||
sizeLoaded = false;
|
||||
calculatingSize = true;
|
||||
|
||||
downloadEnabled = false;
|
||||
downloadCourseEnabled = false;
|
||||
|
@ -106,12 +106,20 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
|
||||
const sections = await CoreCourse.getSections(this.courseId, false, true);
|
||||
this.sections = (await CoreCourseHelper.addHandlerDataForModules(sections, this.courseId)).sections
|
||||
.map((section) => ({ ...section, totalSize: 0 }));
|
||||
.map(section => ({
|
||||
...section,
|
||||
totalSize: 0,
|
||||
calculatingSize: true,
|
||||
modules: section.modules.map(module => ({
|
||||
...module,
|
||||
calculatingSize: true,
|
||||
})),
|
||||
}));
|
||||
|
||||
this.loaded = true;
|
||||
|
||||
await Promise.all([
|
||||
this.loadSizes(),
|
||||
this.initSizes(),
|
||||
this.initCoursePrefetch(),
|
||||
this.initModulePrefetch(),
|
||||
]);
|
||||
|
@ -240,18 +248,9 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
/**
|
||||
* Init section, course and modules sizes.
|
||||
*/
|
||||
protected async loadSizes(): Promise<void> {
|
||||
this.totalSize = 0;
|
||||
this.sizeLoaded = false;
|
||||
|
||||
protected async initSizes(): Promise<void> {
|
||||
await Promise.all(this.sections.map(async (section) => {
|
||||
section.totalSize = 0;
|
||||
section.sizeLoaded = false;
|
||||
|
||||
await Promise.all(section.modules.map(async (module) => {
|
||||
module.totalSize = 0;
|
||||
module.sizeLoaded = false;
|
||||
|
||||
// Note: This function only gets the size for modules which are downloadable.
|
||||
// For other modules it always returns 0, even if they have downloaded some files.
|
||||
// However there is no 100% reliable way to actually track the files in this case.
|
||||
|
@ -268,13 +267,13 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
this.totalSize += size;
|
||||
}
|
||||
|
||||
module.sizeLoaded = true;
|
||||
module.calculatingSize = false;
|
||||
}));
|
||||
|
||||
section.sizeLoaded = true;
|
||||
section.calculatingSize = false;
|
||||
}));
|
||||
|
||||
this.sizeLoaded = true;
|
||||
this.calculatingSize = false;
|
||||
|
||||
// Mark course as not downloaded if course size is 0.
|
||||
if (this.totalSize == 0) {
|
||||
|
@ -282,6 +281,56 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the sizes of some modules.
|
||||
*
|
||||
* @param modules Modules.
|
||||
* @param section Section the modules belong to.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async updateModulesSizes(
|
||||
modules: AddonStorageManagerModule[],
|
||||
section?: AddonStorageManagerCourseSection,
|
||||
): Promise<void> {
|
||||
this.calculatingSize = true;
|
||||
|
||||
await Promise.all(modules.map(async (module) => {
|
||||
if (module.calculatingSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
module.calculatingSize = true;
|
||||
|
||||
if (!section) {
|
||||
section = this.sections.find((section) => section.modules.some((mod) => mod.id === module.id));
|
||||
if (section) {
|
||||
section.calculatingSize = true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const size = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, this.courseId);
|
||||
|
||||
const diff = (isNaN(size) ? 0 : size) - (module.totalSize ?? 0);
|
||||
|
||||
module.totalSize = Number(size);
|
||||
this.totalSize += diff;
|
||||
if (section) {
|
||||
section.totalSize += diff;
|
||||
}
|
||||
} catch {
|
||||
// Ignore errors, it shouldn't happen.
|
||||
} finally {
|
||||
module.calculatingSize = false;
|
||||
}
|
||||
}));
|
||||
|
||||
this.calculatingSize = false;
|
||||
if (section) {
|
||||
section.calculatingSize = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has requested a delete for the whole course data.
|
||||
*
|
||||
|
@ -406,7 +455,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
} finally {
|
||||
modal.dismiss();
|
||||
|
||||
await this.loadSizes();
|
||||
await this.updateModulesSizes(modules, section);
|
||||
CoreCourseHelper.calculateSectionsStatus(this.sections, this.courseId, false, false);
|
||||
}
|
||||
}
|
||||
|
@ -455,7 +504,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingsection', true);
|
||||
}
|
||||
} finally {
|
||||
await this.loadSizes();
|
||||
await this.updateModulesSizes(section.modules, section);
|
||||
}
|
||||
} catch (error) {
|
||||
// User cancelled or there was an error calculating the size.
|
||||
|
@ -501,7 +550,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
} finally {
|
||||
module.spinner = false;
|
||||
|
||||
await this.loadSizes();
|
||||
await this.updateModulesSizes([module]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,13 +662,13 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
|
||||
type AddonStorageManagerCourseSection = Omit<CoreCourseSectionWithStatus, 'modules'> & {
|
||||
totalSize: number;
|
||||
sizeLoaded?: boolean;
|
||||
calculatingSize: boolean;
|
||||
modules: AddonStorageManagerModule[];
|
||||
};
|
||||
|
||||
type AddonStorageManagerModule = CoreCourseModuleData & {
|
||||
totalSize?: number;
|
||||
sizeLoaded?: boolean;
|
||||
calculatingSize: boolean;
|
||||
prefetchHandler?: CoreCourseModulePrefetchHandler;
|
||||
spinner?: boolean;
|
||||
downloadStatus?: string;
|
||||
|
|
Loading…
Reference in New Issue