forked from CIT/Vmeda.Online
		
	MOBILE-3411 h5pactivity: Add button to download the file
This commit is contained in:
		
							parent
							
								
									4bbd05bd55
								
							
						
					
					
						commit
						0196a738d7
					
				| @ -13,5 +13,21 @@ | ||||
| 
 | ||||
|     <core-course-module-description [description]="description" [component]="component" [componentId]="componentId" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-course-module-description> | ||||
| 
 | ||||
|     <!-- TODO --> | ||||
|     <ion-list *ngIf="deployedFile && !playing"> | ||||
|         <ion-item text-wrap *ngIf="stateMessage"> | ||||
|             <p >{{ stateMessage | translate }}</p> | ||||
|         </ion-item> | ||||
| 
 | ||||
|         <!-- Button to download the package. --> | ||||
|         <ion-item *ngIf="!downloading && needsDownload" text-wrap> | ||||
|             <a ion-button block (click)="downloadAndPlay($event)">{{ 'core.download' | translate }}</a> | ||||
|         </ion-item> | ||||
| 
 | ||||
|         <!-- Download progress. --> | ||||
|         <ion-item text-center *ngIf="downloading"> | ||||
|             <ion-spinner></ion-spinner> | ||||
|             <p *ngIf="progressMessage">{{ progressMessage | translate }}</p> | ||||
|             <p *ngIf="percentage <= 100">{{ 'core.percentagenumber' | translate:{$a: percentage} }}</p> | ||||
|         </ion-item> | ||||
|     </ion-list> | ||||
| </core-loading> | ||||
|  | ||||
| @ -14,8 +14,20 @@ | ||||
| 
 | ||||
| import { Component, Optional, Injector } from '@angular/core'; | ||||
| import { Content } from 'ionic-angular'; | ||||
| 
 | ||||
| import { CoreApp } from '@providers/app'; | ||||
| import { CoreFilepool } from '@providers/filepool'; | ||||
| import { CoreWSExternalFile } from '@providers/ws'; | ||||
| import { CoreDomUtils } from '@providers/utils/dom'; | ||||
| import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component'; | ||||
| import { AddonModH5PActivity, AddonModH5PActivityProvider, AddonModH5PActivityData } from '../../providers/h5pactivity'; | ||||
| import { CoreH5P } from '@core/h5p/providers/h5p'; | ||||
| import { CoreH5PDisplayOptions } from '@core/h5p/classes/core'; | ||||
| import { CoreH5PHelper } from '@core/h5p/classes/helper'; | ||||
| import { CoreConstants } from '@core/constants'; | ||||
| 
 | ||||
| import { | ||||
|     AddonModH5PActivity, AddonModH5PActivityProvider, AddonModH5PActivityData, AddonModH5PActivityAccessInfo | ||||
| } from '../../providers/h5pactivity'; | ||||
| 
 | ||||
| /** | ||||
|  * Component that displays an H5P activity entry page. | ||||
| @ -29,8 +41,18 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv | ||||
|     moduleName = 'h5pactivity'; | ||||
| 
 | ||||
|     h5pActivity: AddonModH5PActivityData; // The H5P activity object.
 | ||||
|     accessInfo: AddonModH5PActivityAccessInfo; // Info about the user capabilities.
 | ||||
|     deployedFile: CoreWSExternalFile; // The H5P deployed file.
 | ||||
| 
 | ||||
|     stateMessage: string; // Message about the file state.
 | ||||
|     downloading: boolean; // Whether the H5P file is being downloaded.
 | ||||
|     needsDownload: boolean; // Whether the file needs to be downloaded.
 | ||||
|     percentage: string; // Download/unzip percentage.
 | ||||
|     progressMessage: string; // Message about download/unzip.
 | ||||
|     playing: boolean; // Whether the package is being played.
 | ||||
| 
 | ||||
|     protected fetchContentDefaultError = 'addon.mod_h5pactivity.errorgetactivity'; | ||||
|     protected displayOptions: CoreH5PDisplayOptions; | ||||
| 
 | ||||
|     constructor(injector: Injector, | ||||
|             @Optional() protected content: Content) { | ||||
| @ -66,12 +88,61 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv | ||||
|             this.h5pActivity = await AddonModH5PActivity.instance.getH5PActivity(this.courseId, this.module.id); | ||||
| 
 | ||||
|             this.description = this.h5pActivity.intro; | ||||
|             this.displayOptions = CoreH5PHelper.decodeDisplayOptions(this.h5pActivity.displayoptions); | ||||
|             this.dataRetrieved.emit(this.h5pActivity); | ||||
| 
 | ||||
|             await Promise.all([ | ||||
|                 this.fetchAccessInfo(), | ||||
|                 this.fetchDeployedFileData(), | ||||
|             ]); | ||||
|         } finally { | ||||
|             this.fillContextMenu(refresh); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fetch the access info and store it in the right variables. | ||||
|      * | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async fetchAccessInfo(): Promise<void> { | ||||
|         this.accessInfo = await AddonModH5PActivity.instance.getAccessInformation(this.h5pActivity.id); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fetch the deployed file data if needed and store it in the right variables. | ||||
|      * | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async fetchDeployedFileData(): Promise<void> { | ||||
|         if (this.h5pActivity.deployedfile) { | ||||
|             // File already deployed and still valid, use this one.
 | ||||
|             this.deployedFile = this.h5pActivity.deployedfile; | ||||
|         } else { | ||||
|             if (!this.h5pActivity.package || !this.h5pActivity.package[0]) { | ||||
|                 // Shouldn't happen.
 | ||||
|                 throw 'No H5P package found.'; | ||||
|             } | ||||
| 
 | ||||
|             // Deploy the file in the server.
 | ||||
|             this.deployedFile = await CoreH5P.instance.getTrustedH5PFile(this.h5pActivity.package[0].fileurl, this.displayOptions); | ||||
|         } | ||||
| 
 | ||||
|         await this.calculateFileStatus(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Calculate the status of the deployed file. | ||||
|      * | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async calculateFileStatus(): Promise<void> { | ||||
|         const state = await CoreFilepool.instance.getFileStateByUrl(this.siteId, this.deployedFile.fileurl, | ||||
|                 this.deployedFile.timemodified); | ||||
| 
 | ||||
|         this.showFileState(state); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Perform the invalidate content function. | ||||
|      * | ||||
| @ -80,4 +151,120 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv | ||||
|     protected invalidateContent(): Promise<any> { | ||||
|        return AddonModH5PActivity.instance.invalidateActivityData(this.courseId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Displays some data based on the state of the main file. | ||||
|      * | ||||
|      * @param state The state of the file. | ||||
|      */ | ||||
|     protected showFileState(state: string): void { | ||||
| 
 | ||||
|         if (state == CoreConstants.OUTDATED) { | ||||
|             this.stateMessage = 'addon.mod_h5pactivity.filestateoutdated'; | ||||
|             this.needsDownload = true; | ||||
|         } else if (state == CoreConstants.NOT_DOWNLOADED) { | ||||
|             this.stateMessage = 'addon.mod_h5pactivity.filestatenotdownloaded'; | ||||
|             this.needsDownload = true; | ||||
|         } else if (state == CoreConstants.DOWNLOADING) { | ||||
|             this.stateMessage = ''; | ||||
| 
 | ||||
|             if (!this.downloading) { | ||||
|                 // It's being downloaded right now but the view isn't tracking it. "Restore" the download.
 | ||||
|                 this.downloadDeployedFile().then(() => { | ||||
|                     this.play(); | ||||
|                 }); | ||||
|             } | ||||
|         } else { | ||||
|             this.stateMessage = ''; | ||||
|             this.needsDownload = false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Download the file and play it. | ||||
|      * | ||||
|      * @param e Click event. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     async downloadAndPlay(e: MouseEvent): Promise<void> { | ||||
|         e && e.preventDefault(); | ||||
|         e && e.stopPropagation(); | ||||
| 
 | ||||
|         if (!CoreApp.instance.isOnline()) { | ||||
|             CoreDomUtils.instance.showErrorModal('core.networkerrormsg', true); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             // Confirm the download if needed.
 | ||||
|             await CoreDomUtils.instance.confirmDownloadSize({ size: this.deployedFile.filesize, total: true }); | ||||
| 
 | ||||
|             await this.downloadDeployedFile(); | ||||
| 
 | ||||
|             if (!this.isDestroyed) { | ||||
|                 this.play(); | ||||
|             } | ||||
| 
 | ||||
|         } catch (error) { | ||||
|             if (CoreDomUtils.instance.isCanceledError(error) || this.isDestroyed) { | ||||
|                 // User cancelled or view destroyed, stop.
 | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             CoreDomUtils.instance.showErrorModalDefault(error, 'core.errordownloading', true); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Download athe H5P deployed file or restores an ongoing download. | ||||
|      * | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async downloadDeployedFile(): Promise<void> { | ||||
|         this.downloading = true; | ||||
|         this.progressMessage = 'core.downloading'; | ||||
| 
 | ||||
|         try { | ||||
|             await CoreFilepool.instance.downloadUrl(this.siteId, this.deployedFile.fileurl, false, this.component, this.componentId, | ||||
|                     this.deployedFile.timemodified, (data) => { | ||||
| 
 | ||||
|                 if (!data) { | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 if (data.message) { | ||||
|                     // Show a message.
 | ||||
|                     this.progressMessage = data.message; | ||||
|                     this.percentage = undefined; | ||||
|                 } else if (typeof data.loaded != 'undefined') { | ||||
|                     if (this.progressMessage == 'core.downloading') { | ||||
|                         // Downloading package.
 | ||||
|                         this.percentage = (Number(data.loaded / this.deployedFile.filesize) * 100).toFixed(1); | ||||
|                     } else if (typeof data.total != 'undefined') { | ||||
|                         // Unzipping package.
 | ||||
|                         this.percentage = (Number(data.loaded / data.total) * 100).toFixed(1); | ||||
|                     } else { | ||||
|                         this.percentage = undefined; | ||||
|                     } | ||||
|                 } else { | ||||
|                     this.percentage = undefined; | ||||
|                 } | ||||
|             }); | ||||
| 
 | ||||
|         } finally { | ||||
|             this.progressMessage = undefined; | ||||
|             this.percentage = undefined; | ||||
|             this.downloading = false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Play the package. | ||||
|      */ | ||||
|     play(): void { | ||||
|         this.playing = true; | ||||
| 
 | ||||
|         // @TODO
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,7 @@ | ||||
| { | ||||
|     "errorgetactivity": "Error getting H5P activity data.", | ||||
|     "modulenameplural": "H5P" | ||||
|     "filestatenotdownloaded": "The H5P package is not downloaded. You need to download it to be able to use it.", | ||||
|     "filestateoutdated": "The H5P package has been modified since the last download. You need to download it again to be able to use it.", | ||||
|     "modulenameplural": "H5P", | ||||
|     "storingfiles": "Storing files" | ||||
| } | ||||
| @ -17,6 +17,7 @@ import { Injectable } from '@angular/core'; | ||||
| import { CoreSites } from '@providers/sites'; | ||||
| import { CoreWSExternalWarning, CoreWSExternalFile } from '@providers/ws'; | ||||
| import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; | ||||
| import { CoreCourseLogHelper } from '@core/course/providers/log-helper'; | ||||
| 
 | ||||
| import { makeSingleton, Translate } from '@singletons/core.singletons'; | ||||
| 
 | ||||
| @ -29,6 +30,39 @@ export class AddonModH5PActivityProvider { | ||||
| 
 | ||||
|     protected ROOT_CACHE_KEY = 'mmaModH5PActivity:'; | ||||
| 
 | ||||
|     /** | ||||
|      * Get cache key for access information WS calls. | ||||
|      * | ||||
|      * @param id H5P activity ID. | ||||
|      * @return Cache key. | ||||
|      */ | ||||
|     protected getAccessInformationCacheKey(id: number): string { | ||||
|         return this.ROOT_CACHE_KEY + 'accessInfo:' + id; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get access information for a given H5P activity. | ||||
|      * | ||||
|      * @param id H5P activity ID. | ||||
|      * @param forceCache True to always get the value from cache. false otherwise. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the data. | ||||
|      */ | ||||
|     async getAccessInformation(id: number, forceCache?: boolean, siteId?: string): Promise<AddonModH5PActivityAccessInfo> { | ||||
| 
 | ||||
|         const site = await CoreSites.instance.getSite(siteId); | ||||
| 
 | ||||
|         const params = { | ||||
|             h5pactivityid: id, | ||||
|         }; | ||||
|         const preSets = { | ||||
|             cacheKey: this.getAccessInformationCacheKey(id), | ||||
|             omitExpires: forceCache, | ||||
|         }; | ||||
| 
 | ||||
|         return site.read('mod_h5pactivity_get_h5pactivity_access_information', params, preSets); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get cache key for H5P activity data WS calls. | ||||
|      * | ||||
| @ -54,6 +88,7 @@ export class AddonModH5PActivityProvider { | ||||
|             : Promise<AddonModH5PActivityData> { | ||||
| 
 | ||||
|         const site = await CoreSites.instance.getSite(siteId); | ||||
| 
 | ||||
|         const params = { | ||||
|             courseids: [courseId], | ||||
|         }; | ||||
| @ -66,7 +101,7 @@ export class AddonModH5PActivityProvider { | ||||
|             preSets.omitExpires = true; | ||||
|         } | ||||
| 
 | ||||
|         const response: AddonModH5PActivityGetByCoursesRresult = | ||||
|         const response: AddonModH5PActivityGetByCoursesResult = | ||||
|                 await site.read('mod_h5pactivity_get_h5pactivities_by_courses', params, preSets); | ||||
| 
 | ||||
|         if (response && response.h5pactivities) { | ||||
| @ -108,6 +143,20 @@ export class AddonModH5PActivityProvider { | ||||
|         return this.getH5PActivityByField(courseId, 'id', id, forceCache, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Invalidates access information. | ||||
|      * | ||||
|      * @param id H5P activity ID. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved when the data is invalidated. | ||||
|      */ | ||||
|     async invalidateAccessInformation(id: number, siteId?: string): Promise<void> { | ||||
| 
 | ||||
|         const site = await CoreSites.instance.getSite(siteId); | ||||
| 
 | ||||
|         await site.invalidateWsCacheForKey(this.getAccessInformationCacheKey(id)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Invalidates H5P activity data. | ||||
|      * | ||||
| @ -115,10 +164,10 @@ export class AddonModH5PActivityProvider { | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved when the data is invalidated. | ||||
|      */ | ||||
|     async invalidateActivityData(courseId: number, siteId?: string): Promise<any> { | ||||
|     async invalidateActivityData(courseId: number, siteId?: string): Promise<void> { | ||||
|         const site = await CoreSites.instance.getSite(siteId); | ||||
| 
 | ||||
|         return site.invalidateWsCacheForKey(this.getH5PActivityDataCacheKey(courseId)); | ||||
|         await site.invalidateWsCacheForKey(this.getH5PActivityDataCacheKey(courseId)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -131,6 +180,35 @@ export class AddonModH5PActivityProvider { | ||||
| 
 | ||||
|         return site.wsAvailable('mod_h5pactivity_get_h5pactivities_by_courses'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Report an H5P activity as being viewed. | ||||
|      * | ||||
|      * @param id H5P activity ID. | ||||
|      * @param name Name of the activity. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved when the WS call is successful. | ||||
|      */ | ||||
|     async logView(id: number, name?: string, siteId?: string): Promise<void> { | ||||
|         const params = { | ||||
|             h5pactivityid: id, | ||||
|         }; | ||||
| 
 | ||||
|         const result: AddonModH5PActivityViewResult = await CoreCourseLogHelper.instance.logSingle( | ||||
|             'mod_h5pactivity_view_h5pactivity', | ||||
|             params, | ||||
|             AddonModH5PActivityProvider.COMPONENT, | ||||
|             id, | ||||
|             name, | ||||
|             'h5pactivity', | ||||
|             {}, | ||||
|             siteId | ||||
|         ); | ||||
| 
 | ||||
|         if (!result.status) { | ||||
|             throw result.warnings[0] || 'Error marking H5P activity as viewed.'; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export class AddonModH5PActivity extends makeSingleton(AddonModH5PActivityProvider) {} | ||||
| @ -167,7 +245,26 @@ export type AddonModH5PActivityData = { | ||||
| /** | ||||
|  * Result of WS mod_h5pactivity_get_h5pactivities_by_courses. | ||||
|  */ | ||||
| export type AddonModH5PActivityGetByCoursesRresult = { | ||||
| export type AddonModH5PActivityGetByCoursesResult = { | ||||
|     h5pactivities: AddonModH5PActivityData[]; | ||||
|     warnings?: CoreWSExternalWarning[]; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Result of WS mod_h5pactivity_get_h5pactivity_access_information. | ||||
|  */ | ||||
| export type AddonModH5PActivityAccessInfo = { | ||||
|     warnings?: CoreWSExternalWarning[]; | ||||
|     canview?: boolean; // Whether the user has the capability mod/h5pactivity:view allowed.
 | ||||
|     canaddinstance?: boolean; // Whether the user has the capability mod/h5pactivity:addinstance allowed.
 | ||||
|     cansubmit?: boolean; // Whether the user has the capability mod/h5pactivity:submit allowed.
 | ||||
|     canreviewattempts?: boolean; // Whether the user has the capability mod/h5pactivity:reviewattempts allowed.
 | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Result of WS mod_h5pactivity_view_h5pactivity. | ||||
|  */ | ||||
| export type AddonModH5PActivityViewResult = { | ||||
|     status: boolean; // Status: true if success.
 | ||||
|     warnings?: CoreWSExternalWarning[]; | ||||
| }; | ||||
|  | ||||
| @ -1257,7 +1257,7 @@ export class AddonModScormProvider { | ||||
|     /** | ||||
|      * Invalidates access information. | ||||
|      * | ||||
|      * @param forumId SCORM ID. | ||||
|      * @param scormId SCORM ID. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved when the data is invalidated. | ||||
|      */ | ||||
| @ -1544,7 +1544,7 @@ export class AddonModScormProvider { | ||||
| 
 | ||||
|         return this.logHelper.logSingle('mod_scorm_view_scorm', params, AddonModScormProvider.COMPONENT, id, name, 'scorm', {}, | ||||
|                 siteId); | ||||
| } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Saves a SCORM tracking record. | ||||
|  | ||||
| @ -660,7 +660,10 @@ | ||||
|     "addon.mod_glossary.searchquery": "Search query", | ||||
|     "addon.mod_glossary.tagarea_glossary_entries": "Glossary entries", | ||||
|     "addon.mod_h5pactivity.errorgetactivity": "Error getting H5P activity data.", | ||||
|     "addon.mod_h5pactivity.filestatenotdownloaded": "The H5P package is not downloaded. You need to download it to be able to use it.", | ||||
|     "addon.mod_h5pactivity.filestateoutdated": "The H5P package has been modified since the last download. You need to download it again to be able to use it.", | ||||
|     "addon.mod_h5pactivity.modulenameplural": "H5P", | ||||
|     "addon.mod_h5pactivity.storingfiles": "Storing files", | ||||
|     "addon.mod_imscp.deploymenterror": "Content package error!", | ||||
|     "addon.mod_imscp.modulenameplural": "IMS content packages", | ||||
|     "addon.mod_imscp.showmoduledescription": "Show description", | ||||
|  | ||||
| @ -20,6 +20,8 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications'; | ||||
| 
 | ||||
| import { makeSingleton } from '@singletons/core.singletons'; | ||||
| 
 | ||||
| /** | ||||
|  * Helper to manage logging to Moodle. | ||||
|  */ | ||||
| @ -355,3 +357,5 @@ export class CoreCourseLogHelperProvider { | ||||
|         })); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export class CoreCourseLogHelper extends makeSingleton(CoreCourseLogHelperProvider) {} | ||||
|  | ||||
| @ -16,8 +16,9 @@ import { CoreFile, CoreFileProvider } from '@providers/file'; | ||||
| import { CoreSites } from '@providers/sites'; | ||||
| import { CoreMimetypeUtils } from '@providers/utils/mimetype'; | ||||
| import { CoreTextUtils } from '@providers/utils/text'; | ||||
| import { CoreUtils } from '@providers/utils/utils'; | ||||
| import { CoreH5P } from '../providers/h5p'; | ||||
| import { CoreH5PCore } from './core'; | ||||
| import { CoreH5PCore, CoreH5PDisplayOptions } from './core'; | ||||
| import { FileEntry } from '@ionic-native/file'; | ||||
| 
 | ||||
| /** | ||||
| @ -25,6 +26,25 @@ import { FileEntry } from '@ionic-native/file'; | ||||
|  */ | ||||
| export class CoreH5PHelper { | ||||
| 
 | ||||
|     /** | ||||
|      * Convert the number representation of display options into an object. | ||||
|      * | ||||
|      * @param displayOptions Number representing display options. | ||||
|      * @return Object with display options. | ||||
|      */ | ||||
|     static decodeDisplayOptions(displayOptions: number): CoreH5PDisplayOptions { | ||||
|         const config: any = {}; | ||||
|         const displayOptionsObject = CoreH5P.instance.h5pCore.getDisplayOptionsAsObject(displayOptions); | ||||
| 
 | ||||
|         config.export = 0; // Don't allow downloading in the app.
 | ||||
|         config.embed = CoreUtils.instance.notNullOrUndefined(displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_EMBED]) ? | ||||
|                 displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_EMBED] : 0; | ||||
|         config.copyright = CoreUtils.instance.notNullOrUndefined(displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_COPYRIGHT]) ? | ||||
|                 displayOptionsObject[CoreH5PCore.DISPLAY_OPTION_COPYRIGHT] : 0; | ||||
| 
 | ||||
|         return config; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the core H5P assets, including all core H5P JavaScript and CSS. | ||||
|      * | ||||
| @ -107,19 +127,25 @@ export class CoreH5PHelper { | ||||
|      * @param fileUrl The file URL used to download the file. | ||||
|      * @param file The file entry of the downloaded file. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @param onProgress Function to call on progress. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     static async saveH5P(fileUrl: string, file: FileEntry, siteId?: string): Promise<void> { | ||||
|     static async saveH5P(fileUrl: string, file: FileEntry, siteId?: string, onProgress?: (event: any) => any): Promise<void> { | ||||
|         siteId = siteId || CoreSites.instance.getCurrentSiteId(); | ||||
| 
 | ||||
|         // Unzip the file.
 | ||||
|         const folderName = CoreMimetypeUtils.instance.removeExtension(file.name); | ||||
|         const destFolder = CoreTextUtils.instance.concatenatePaths(CoreFileProvider.TMPFOLDER, 'h5p/' + folderName); | ||||
| 
 | ||||
|         // Notify that the unzip is starting.
 | ||||
|         onProgress && onProgress({message: 'core.unzipping'}); | ||||
| 
 | ||||
|         // Unzip the file.
 | ||||
|         await CoreFile.instance.unzipFile(file.toURL(), destFolder); | ||||
|         await CoreFile.instance.unzipFile(file.toURL(), destFolder, onProgress); | ||||
| 
 | ||||
|         try { | ||||
|             // Notify that the unzip is starting.
 | ||||
|             onProgress && onProgress({message: 'addon.mod_h5pactivity.storingfiles'}); | ||||
| 
 | ||||
|             // Read the contents of the unzipped dir, process them and store them.
 | ||||
|             const contents = await CoreFile.instance.getDirectoryContents(destFolder); | ||||
| 
 | ||||
|  | ||||
| @ -219,11 +219,11 @@ export class CoreH5PPlayer { | ||||
|      * Get the content index file. | ||||
|      * | ||||
|      * @param fileUrl URL of the H5P package. | ||||
|      * @param urlParams URL params. | ||||
|      * @param displayOptions Display options. | ||||
|      * @param siteId The site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the file URL if exists, rejected otherwise. | ||||
|      */ | ||||
|     async getContentIndexFileUrl(fileUrl: string, urlParams?: {[name: string]: string}, siteId?: string): Promise<string> { | ||||
|     async getContentIndexFileUrl(fileUrl: string, displayOptions?: CoreH5PDisplayOptions, siteId?: string): Promise<string> { | ||||
|         siteId = siteId || CoreSites.instance.getCurrentSiteId(); | ||||
| 
 | ||||
|         const path = await this.h5pCore.h5pFS.getContentIndexFileUrl(fileUrl, siteId); | ||||
| @ -231,9 +231,9 @@ export class CoreH5PPlayer { | ||||
|         // Add display options to the URL.
 | ||||
|         const data = await this.h5pCore.h5pFramework.getContentDataByUrl(fileUrl, siteId); | ||||
| 
 | ||||
|         const options = this.h5pCore.fixDisplayOptions(this.getDisplayOptionsFromUrlParams(urlParams), data.id); | ||||
|         displayOptions = this.h5pCore.fixDisplayOptions(displayOptions, data.id); | ||||
| 
 | ||||
|         return CoreUrlUtils.instance.addParamsToUrl(path, options, undefined, true); | ||||
|         return CoreUrlUtils.instance.addParamsToUrl(path, displayOptions, undefined, true); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -93,11 +93,12 @@ export class CoreH5PPlayerComponent implements OnInit, OnChanges, OnDestroy { | ||||
|         this.loading = true; | ||||
| 
 | ||||
|         let localUrl: string; | ||||
|         const displayOptions = CoreH5P.instance.h5pPlayer.getDisplayOptionsFromUrlParams(this.urlParams); | ||||
| 
 | ||||
|         if (this.canDownload && CoreFileHelper.instance.isStateDownloaded(this.state)) { | ||||
|             // Package is downloaded, use the local URL.
 | ||||
|             try { | ||||
|                 localUrl = await CoreH5P.instance.h5pPlayer.getContentIndexFileUrl(this.urlParams.url, this.urlParams, this.siteId); | ||||
|                 localUrl = await CoreH5P.instance.h5pPlayer.getContentIndexFileUrl(this.urlParams.url, displayOptions, this.siteId); | ||||
|             } catch (error) { | ||||
|                 // Index file doesn't exist, probably deleted because a lib was updated. Try to create it again.
 | ||||
|                 try { | ||||
| @ -108,7 +109,7 @@ export class CoreH5PPlayerComponent implements OnInit, OnChanges, OnDestroy { | ||||
|                     await CoreH5PHelper.saveH5P(this.urlParams.url, file, this.siteId); | ||||
| 
 | ||||
|                     // File treated. Try to get the index file URL again.
 | ||||
|                     localUrl = await CoreH5P.instance.h5pPlayer.getContentIndexFileUrl(this.urlParams.url, this.urlParams, | ||||
|                     localUrl = await CoreH5P.instance.h5pPlayer.getContentIndexFileUrl(this.urlParams.url, displayOptions, | ||||
|                             this.siteId); | ||||
|                 } catch (error) { | ||||
|                     // Still failing. Delete the H5P package?
 | ||||
|  | ||||
| @ -18,6 +18,7 @@ import { CoreMimetypeUtils } from '@providers/utils/mimetype'; | ||||
| import { CoreUrlUtils } from '@providers/utils/url'; | ||||
| import { CoreUtils } from '@providers/utils/utils'; | ||||
| import { CoreH5P } from './h5p'; | ||||
| import { CoreSites } from '@providers/sites'; | ||||
| import { CoreWSExternalFile } from '@providers/ws'; | ||||
| import { FileEntry } from '@ionic-native/file'; | ||||
| import { Translate } from '@singletons/core.singletons'; | ||||
| @ -50,7 +51,14 @@ export class CoreH5PPluginFileHandler implements CorePluginFileHandler { | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the file to use. Rejected if cannot download. | ||||
|      */ | ||||
|     getDownloadableFile(file: CoreWSExternalFile, siteId?: string): Promise<CoreWSExternalFile> { | ||||
|     async getDownloadableFile(file: CoreWSExternalFile, siteId?: string): Promise<CoreWSExternalFile> { | ||||
|         const site = await CoreSites.instance.getSite(siteId); | ||||
| 
 | ||||
|         if (site.containsUrl(file.fileurl) && file.fileurl.match(/pluginfile\.php\/[^\/]+\/core_h5p\/export\//i)) { | ||||
|             // It's already a deployed file, use it.
 | ||||
|             return file; | ||||
|         } | ||||
| 
 | ||||
|         return CoreH5P.instance.getTrustedH5PFile(file.fileurl, {}, false, siteId); | ||||
|     } | ||||
| 
 | ||||
| @ -85,7 +93,7 @@ export class CoreH5PPluginFileHandler implements CorePluginFileHandler { | ||||
|      */ | ||||
|     async getFileSize(file: CoreWSExternalFile, siteId?: string): Promise<number> { | ||||
|         try { | ||||
|             const trustedFile = await CoreH5P.instance.getTrustedH5PFile(file.fileurl, {}, false, siteId); | ||||
|             const trustedFile = await this.getDownloadableFile(file, siteId); | ||||
| 
 | ||||
|             return trustedFile.filesize; | ||||
|         } catch (error) { | ||||
| @ -145,9 +153,10 @@ export class CoreH5PPluginFileHandler implements CorePluginFileHandler { | ||||
|      * @param fileUrl The file URL used to download the file. | ||||
|      * @param file The file entry of the downloaded file. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @param onProgress Function to call on progress. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     treatDownloadedFile(fileUrl: string, file: FileEntry, siteId?: string): Promise<void> { | ||||
|         return CoreH5PHelper.saveH5P(fileUrl, file, siteId); | ||||
|     treatDownloadedFile(fileUrl: string, file: FileEntry, siteId?: string, onProgress?: (event: any) => any): Promise<void> { | ||||
|         return CoreH5PHelper.saveH5P(fileUrl, file, siteId, onProgress); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1058,7 +1058,7 @@ export class CoreFilepoolProvider { | ||||
|                 return this.wsProvider.downloadFile(fileUrl, filePath, addExtension, onProgress).then((entry) => { | ||||
|                     fileEntry = entry; | ||||
| 
 | ||||
|                     return this.pluginFileDelegate.treatDownloadedFile(fileUrl, fileEntry, siteId); | ||||
|                     return this.pluginFileDelegate.treatDownloadedFile(fileUrl, fileEntry, siteId, onProgress); | ||||
|                 }).then(() => { | ||||
|                     const data: CoreFilepoolFileEntry = poolFileObject || {}; | ||||
| 
 | ||||
|  | ||||
| @ -108,9 +108,10 @@ export interface CorePluginFileHandler extends CoreDelegateHandler { | ||||
|      * @param fileUrl The file URL used to download the file. | ||||
|      * @param file The file entry of the downloaded file. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @param onProgress Function to call on progress. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     treatDownloadedFile?(fileUrl: string, file: FileEntry, siteId?: string): Promise<any>; | ||||
|     treatDownloadedFile?(fileUrl: string, file: FileEntry, siteId?: string, onProgress?: (event: any) => any): Promise<any>; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -360,13 +361,14 @@ export class CorePluginFileDelegate extends CoreDelegate { | ||||
|      * @param fileUrl The file URL used to download the file. | ||||
|      * @param file The file entry of the downloaded file. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @param onProgress Function to call on progress. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     treatDownloadedFile(fileUrl: string, file: FileEntry, siteId?: string): Promise<any> { | ||||
|     treatDownloadedFile(fileUrl: string, file: FileEntry, siteId?: string, onProgress?: (event: any) => any): Promise<any> { | ||||
|         const handler = this.getHandlerForFile({fileurl: fileUrl}); | ||||
| 
 | ||||
|         if (handler && handler.treatDownloadedFile) { | ||||
|             return handler.treatDownloadedFile(fileUrl, file, siteId); | ||||
|             return handler.treatDownloadedFile(fileUrl, file, siteId, onProgress); | ||||
|         } | ||||
| 
 | ||||
|         return Promise.resolve(); | ||||
|  | ||||
| @ -872,6 +872,16 @@ export class CoreUtilsProvider { | ||||
|         return this.uniqueArray(array1.concat(array2), key); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if a value isn't null or undefined. | ||||
|      * | ||||
|      * @param value Value to check. | ||||
|      * @return True if not null and not undefined. | ||||
|      */ | ||||
|     notNullOrUndefined(value: any): boolean { | ||||
|         return typeof value != 'undefined' && value !== null; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Open a file using platform specific method. | ||||
|      * | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user