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