MOBILE-3833 course: Display data ASAP in course downloads
parent
9c2116c33b
commit
1a07331396
|
@ -1453,6 +1453,7 @@
|
|||
"core.block.tour_navigation_dashboard_content": "tool_usertours",
|
||||
"core.block.tour_navigation_dashboard_title": "tool_usertours",
|
||||
"core.browser": "local_moodlemobileapp",
|
||||
"core.calculating": "local_moodlemobileapp",
|
||||
"core.cancel": "moodle",
|
||||
"core.cannotconnect": "local_moodlemobileapp",
|
||||
"core.cannotconnecttrouble": "local_moodlemobileapp",
|
||||
|
@ -1673,6 +1674,7 @@
|
|||
"core.editor.underline": "atto_underline/pluginname",
|
||||
"core.editor.unorderedlist": "atto_unorderedlist/pluginname",
|
||||
"core.emptysplit": "local_moodlemobileapp",
|
||||
"core.endonesteptour": "tool_usertours",
|
||||
"core.error": "moodle",
|
||||
"core.errorchangecompletion": "local_moodlemobileapp",
|
||||
"core.errordeletefile": "local_moodlemobileapp",
|
||||
|
@ -2342,7 +2344,6 @@
|
|||
"core.usernotfullysetup": "error",
|
||||
"core.users": "moodle",
|
||||
"core.usersuspended": "tool_reportbuilder",
|
||||
"core.endonesteptour": "tool_usertours",
|
||||
"core.view": "moodle",
|
||||
"core.viewcode": "local_moodlemobileapp",
|
||||
"core.vieweditor": "local_moodlemobileapp",
|
||||
|
|
|
@ -24,15 +24,18 @@
|
|||
<ion-label>
|
||||
<p class="item-heading ion-text-wrap">{{ 'addon.storagemanager.totaldownloads' | translate }}</p>
|
||||
</ion-label>
|
||||
<ion-badge color="light" slot="end">{{ totalSize | coreBytesToSize }}
|
||||
<ion-badge color="light" slot="end">
|
||||
<ng-container *ngIf="sizeLoaded">{{ totalSize | coreBytesToSize }}</ng-container>
|
||||
<ng-container *ngIf="!sizeLoaded">{{ 'core.calculating' | translate }}</ng-container>
|
||||
</ion-badge>
|
||||
</ion-item>
|
||||
<ion-button *ngIf="downloadCourseEnabled" (click)="prefetchCourse()" expand="block" fill="outline" class="ion-no-margin">
|
||||
<ion-button *ngIf="downloadCourseEnabled" (click)="prefetchCourse()" expand="block" fill="outline" class="ion-no-margin"
|
||||
[disabled]="prefetchCourseData.loading">
|
||||
<ion-icon *ngIf="!prefetchCourseData.loading" [name]="prefetchCourseData.icon" slot="start"></ion-icon>
|
||||
<ion-spinner *ngIf="prefetchCourseData.loading" slot="start"></ion-spinner>
|
||||
{{ prefetchCourseData.statusTranslatable | translate }}
|
||||
</ion-button>
|
||||
<ion-button *ngIf="totalSize > 0" (click)="deleteForCourse()" expand="block" color="danger"
|
||||
<ion-button *ngIf="sizeLoaded && 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 }">
|
||||
|
@ -52,18 +55,21 @@
|
|||
</core-format-text>
|
||||
</p>
|
||||
<ion-badge [color]="section.downloadStatus == statusDownloaded ? 'success' : 'light'"
|
||||
*ngIf="section.totalSize > 0">
|
||||
*ngIf="section.sizeLoaded && 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">
|
||||
{{ 'core.calculating' | translate }}
|
||||
</ion-badge>
|
||||
<!-- Download progress. -->
|
||||
<p *ngIf="downloadEnabled && section.isDownloading">
|
||||
<core-progress-bar [progress]="section.total == 0 ? -1 : section.count / section.total">
|
||||
</core-progress-bar>
|
||||
</p>
|
||||
</ion-label>
|
||||
<div class="storage-buttons" slot="end" *ngIf="section.totalSize > 0 || downloadEnabled">
|
||||
<div class="storage-buttons" slot="end" *ngIf="(section.sizeLoaded && 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)"
|
||||
|
@ -77,7 +83,8 @@
|
|||
{{section.count}} / {{section.total}}
|
||||
</ion-badge>
|
||||
</div>
|
||||
<ion-button (click)="deleteForSection(section)" *ngIf="section.totalSize > 0" color="danger" fill="clear">
|
||||
<ion-button (click)="deleteForSection(section)" *ngIf="section.sizeLoaded && 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 }">
|
||||
</ion-icon>
|
||||
|
@ -87,7 +94,8 @@
|
|||
</ion-card-header>
|
||||
<ion-card-content>
|
||||
<ng-container *ngFor="let module of section.modules">
|
||||
<ion-item class="ion-no-padding core-course-storage-activity" *ngIf="downloadEnabled || module.totalSize > 0">
|
||||
<ion-item class="ion-no-padding core-course-storage-activity"
|
||||
*ngIf="downloadEnabled || (module.sizeLoaded && 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>
|
||||
|
@ -98,11 +106,14 @@
|
|||
</core-format-text>
|
||||
</h3>
|
||||
<ion-badge [color]="module.downloadStatus == statusDownloaded ? 'success' : 'light'"
|
||||
*ngIf="module.totalSize > 0">
|
||||
*ngIf="module.sizeLoaded && 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">
|
||||
{{ 'core.calculating' | translate }}
|
||||
</ion-badge>
|
||||
</ion-label>
|
||||
|
||||
<div class="storage-buttons" slot="end">
|
||||
|
@ -111,8 +122,8 @@
|
|||
[canTrustDownload]="true" [loading]="module.spinner || module.handlerData.spinner"
|
||||
(action)="prefetchModule(module, section)">
|
||||
</core-download-refresh>
|
||||
<ion-button fill="clear" (click)="deleteForModule(module, section)" *ngIf="module.totalSize > 0"
|
||||
color="danger">
|
||||
<ion-button fill="clear" (click)="deleteForModule(module, section)"
|
||||
*ngIf="module.sizeLoaded && 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,6 +48,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
loaded = false;
|
||||
sections: AddonStorageManagerCourseSection[] = [];
|
||||
totalSize = 0;
|
||||
sizeLoaded = false;
|
||||
|
||||
downloadEnabled = false;
|
||||
downloadCourseEnabled = false;
|
||||
|
@ -107,13 +108,13 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
this.sections = (await CoreCourseHelper.addHandlerDataForModules(sections, this.courseId)).sections
|
||||
.map((section) => ({ ...section, totalSize: 0 }));
|
||||
|
||||
this.loaded = true;
|
||||
|
||||
await Promise.all([
|
||||
this.loadSizes(),
|
||||
this.initCoursePrefetch(),
|
||||
this.initModulePrefetch(),
|
||||
]);
|
||||
|
||||
this.loaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,12 +242,15 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
*/
|
||||
protected async loadSizes(): Promise<void> {
|
||||
this.totalSize = 0;
|
||||
this.sizeLoaded = false;
|
||||
|
||||
const promises: Promise<void>[] = [];
|
||||
this.sections.forEach((section) => {
|
||||
await Promise.all(this.sections.map(async (section) => {
|
||||
section.totalSize = 0;
|
||||
section.modules.forEach((module) => {
|
||||
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.
|
||||
|
@ -255,21 +259,22 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
// But these aren't necessarily consistent, for example mod_frog vs mmaModFrog.
|
||||
// There is nothing enforcing correct values.
|
||||
// Most modules which have large files are downloadable, so I think this is sufficient.
|
||||
const promise = CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, this.courseId).then((size) => {
|
||||
// There are some cases where the return from this is not a valid number.
|
||||
if (!isNaN(size)) {
|
||||
module.totalSize = Number(size);
|
||||
section.totalSize += size;
|
||||
this.totalSize += size;
|
||||
}
|
||||
const size = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, this.courseId);
|
||||
|
||||
return;
|
||||
});
|
||||
promises.push(promise);
|
||||
});
|
||||
});
|
||||
// There are some cases where the return from this is not a valid number.
|
||||
if (!isNaN(size)) {
|
||||
module.totalSize = Number(size);
|
||||
section.totalSize += size;
|
||||
this.totalSize += size;
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
module.sizeLoaded = true;
|
||||
}));
|
||||
|
||||
section.sizeLoaded = true;
|
||||
}));
|
||||
|
||||
this.sizeLoaded = true;
|
||||
|
||||
// Mark course as not downloaded if course size is 0.
|
||||
if (this.totalSize == 0) {
|
||||
|
@ -608,11 +613,13 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy {
|
|||
|
||||
type AddonStorageManagerCourseSection = Omit<CoreCourseSectionWithStatus, 'modules'> & {
|
||||
totalSize: number;
|
||||
sizeLoaded?: boolean;
|
||||
modules: AddonStorageManagerModule[];
|
||||
};
|
||||
|
||||
type AddonStorageManagerModule = CoreCourseModuleData & {
|
||||
totalSize?: number;
|
||||
sizeLoaded?: boolean;
|
||||
prefetchHandler?: CoreCourseModulePrefetchHandler;
|
||||
spinner?: boolean;
|
||||
downloadStatus?: string;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"areyousure": "Are you sure?",
|
||||
"back": "Back",
|
||||
"browser": "Browser",
|
||||
"calculating": "Calculating",
|
||||
"cancel": "Cancel",
|
||||
"cannotconnect": "Cannot connect",
|
||||
"cannotconnecttrouble": "We're having trouble connecting to your site.",
|
||||
|
|
Loading…
Reference in New Issue