1414
1515import { Component , Optional , Injector } from '@angular/core' ;
1616import { Content } from 'ionic-angular' ;
17+
18+ import { CoreApp } from '@providers/app' ;
19+ import { CoreFilepool } from '@providers/filepool' ;
20+ import { CoreWSExternalFile } from '@providers/ws' ;
21+ import { CoreDomUtils } from '@providers/utils/dom' ;
1722import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component' ;
18- import { AddonModH5PActivity , AddonModH5PActivityProvider , AddonModH5PActivityData } from '../../providers/h5pactivity' ;
23+ import { CoreH5P } from '@core/h5p/providers/h5p' ;
24+ import { CoreH5PDisplayOptions } from '@core/h5p/classes/core' ;
25+ import { CoreH5PHelper } from '@core/h5p/classes/helper' ;
26+ import { CoreConstants } from '@core/constants' ;
27+
28+ import {
29+ AddonModH5PActivity , AddonModH5PActivityProvider , AddonModH5PActivityData , AddonModH5PActivityAccessInfo
30+ } from '../../providers/h5pactivity' ;
1931
2032/**
2133 * Component that displays an H5P activity entry page.
@@ -29,8 +41,18 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
2941 moduleName = 'h5pactivity' ;
3042
3143 h5pActivity : AddonModH5PActivityData ; // The H5P activity object.
44+ accessInfo : AddonModH5PActivityAccessInfo ; // Info about the user capabilities.
45+ deployedFile : CoreWSExternalFile ; // The H5P deployed file.
46+
47+ stateMessage : string ; // Message about the file state.
48+ downloading : boolean ; // Whether the H5P file is being downloaded.
49+ needsDownload : boolean ; // Whether the file needs to be downloaded.
50+ percentage : string ; // Download/unzip percentage.
51+ progressMessage : string ; // Message about download/unzip.
52+ playing : boolean ; // Whether the package is being played.
3253
3354 protected fetchContentDefaultError = 'addon.mod_h5pactivity.errorgetactivity' ;
55+ protected displayOptions : CoreH5PDisplayOptions ;
3456
3557 constructor ( injector : Injector ,
3658 @Optional ( ) protected content : Content ) {
@@ -66,12 +88,61 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
6688 this . h5pActivity = await AddonModH5PActivity . instance . getH5PActivity ( this . courseId , this . module . id ) ;
6789
6890 this . description = this . h5pActivity . intro ;
91+ this . displayOptions = CoreH5PHelper . decodeDisplayOptions ( this . h5pActivity . displayoptions ) ;
6992 this . dataRetrieved . emit ( this . h5pActivity ) ;
93+
94+ await Promise . all ( [
95+ this . fetchAccessInfo ( ) ,
96+ this . fetchDeployedFileData ( ) ,
97+ ] ) ;
7098 } finally {
7199 this . fillContextMenu ( refresh ) ;
72100 }
73101 }
74102
103+ /**
104+ * Fetch the access info and store it in the right variables.
105+ *
106+ * @return Promise resolved when done.
107+ */
108+ protected async fetchAccessInfo ( ) : Promise < void > {
109+ this . accessInfo = await AddonModH5PActivity . instance . getAccessInformation ( this . h5pActivity . id ) ;
110+ }
111+
112+ /**
113+ * Fetch the deployed file data if needed and store it in the right variables.
114+ *
115+ * @return Promise resolved when done.
116+ */
117+ protected async fetchDeployedFileData ( ) : Promise < void > {
118+ if ( this . h5pActivity . deployedfile ) {
119+ // File already deployed and still valid, use this one.
120+ this . deployedFile = this . h5pActivity . deployedfile ;
121+ } else {
122+ if ( ! this . h5pActivity . package || ! this . h5pActivity . package [ 0 ] ) {
123+ // Shouldn't happen.
124+ throw 'No H5P package found.' ;
125+ }
126+
127+ // Deploy the file in the server.
128+ this . deployedFile = await CoreH5P . instance . getTrustedH5PFile ( this . h5pActivity . package [ 0 ] . fileurl , this . displayOptions ) ;
129+ }
130+
131+ await this . calculateFileStatus ( ) ;
132+ }
133+
134+ /**
135+ * Calculate the status of the deployed file.
136+ *
137+ * @return Promise resolved when done.
138+ */
139+ protected async calculateFileStatus ( ) : Promise < void > {
140+ const state = await CoreFilepool . instance . getFileStateByUrl ( this . siteId , this . deployedFile . fileurl ,
141+ this . deployedFile . timemodified ) ;
142+
143+ this . showFileState ( state ) ;
144+ }
145+
75146 /**
76147 * Perform the invalidate content function.
77148 *
@@ -80,4 +151,120 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
80151 protected invalidateContent ( ) : Promise < any > {
81152 return AddonModH5PActivity . instance . invalidateActivityData ( this . courseId ) ;
82153 }
154+
155+ /**
156+ * Displays some data based on the state of the main file.
157+ *
158+ * @param state The state of the file.
159+ */
160+ protected showFileState ( state : string ) : void {
161+
162+ if ( state == CoreConstants . OUTDATED ) {
163+ this . stateMessage = 'addon.mod_h5pactivity.filestateoutdated' ;
164+ this . needsDownload = true ;
165+ } else if ( state == CoreConstants . NOT_DOWNLOADED ) {
166+ this . stateMessage = 'addon.mod_h5pactivity.filestatenotdownloaded' ;
167+ this . needsDownload = true ;
168+ } else if ( state == CoreConstants . DOWNLOADING ) {
169+ this . stateMessage = '' ;
170+
171+ if ( ! this . downloading ) {
172+ // It's being downloaded right now but the view isn't tracking it. "Restore" the download.
173+ this . downloadDeployedFile ( ) . then ( ( ) => {
174+ this . play ( ) ;
175+ } ) ;
176+ }
177+ } else {
178+ this . stateMessage = '' ;
179+ this . needsDownload = false ;
180+ }
181+ }
182+
183+ /**
184+ * Download the file and play it.
185+ *
186+ * @param e Click event.
187+ * @return Promise resolved when done.
188+ */
189+ async downloadAndPlay ( e : MouseEvent ) : Promise < void > {
190+ e && e . preventDefault ( ) ;
191+ e && e . stopPropagation ( ) ;
192+
193+ if ( ! CoreApp . instance . isOnline ( ) ) {
194+ CoreDomUtils . instance . showErrorModal ( 'core.networkerrormsg' , true ) ;
195+
196+ return ;
197+ }
198+
199+ try {
200+ // Confirm the download if needed.
201+ await CoreDomUtils . instance . confirmDownloadSize ( { size : this . deployedFile . filesize , total : true } ) ;
202+
203+ await this . downloadDeployedFile ( ) ;
204+
205+ if ( ! this . isDestroyed ) {
206+ this . play ( ) ;
207+ }
208+
209+ } catch ( error ) {
210+ if ( CoreDomUtils . instance . isCanceledError ( error ) || this . isDestroyed ) {
211+ // User cancelled or view destroyed, stop.
212+ return ;
213+ }
214+
215+ CoreDomUtils . instance . showErrorModalDefault ( error , 'core.errordownloading' , true ) ;
216+ }
217+ }
218+
219+ /**
220+ * Download athe H5P deployed file or restores an ongoing download.
221+ *
222+ * @return Promise resolved when done.
223+ */
224+ protected async downloadDeployedFile ( ) : Promise < void > {
225+ this . downloading = true ;
226+ this . progressMessage = 'core.downloading' ;
227+
228+ try {
229+ await CoreFilepool . instance . downloadUrl ( this . siteId , this . deployedFile . fileurl , false , this . component , this . componentId ,
230+ this . deployedFile . timemodified , ( data ) => {
231+
232+ if ( ! data ) {
233+ return ;
234+ }
235+
236+ if ( data . message ) {
237+ // Show a message.
238+ this . progressMessage = data . message ;
239+ this . percentage = undefined ;
240+ } else if ( typeof data . loaded != 'undefined' ) {
241+ if ( this . progressMessage == 'core.downloading' ) {
242+ // Downloading package.
243+ this . percentage = ( Number ( data . loaded / this . deployedFile . filesize ) * 100 ) . toFixed ( 1 ) ;
244+ } else if ( typeof data . total != 'undefined' ) {
245+ // Unzipping package.
246+ this . percentage = ( Number ( data . loaded / data . total ) * 100 ) . toFixed ( 1 ) ;
247+ } else {
248+ this . percentage = undefined ;
249+ }
250+ } else {
251+ this . percentage = undefined ;
252+ }
253+ } ) ;
254+
255+ } finally {
256+ this . progressMessage = undefined ;
257+ this . percentage = undefined ;
258+ this . downloading = false ;
259+ }
260+ }
261+
262+ /**
263+ * Play the package.
264+ */
265+ play ( ) : void {
266+ this . playing = true ;
267+
268+ // @TODO
269+ }
83270}
0 commit comments