forked from EVOgeek/Vmeda.Online
		
	MOBILE-2235 h5p: Implement H5P download and unzip
This commit is contained in:
		
							parent
							
								
									9b637fc496
								
							
						
					
					
						commit
						c4a58d9ee8
					
				| @ -69,11 +69,14 @@ export class AddonFilterDisplayH5PHandler extends CoreFilterDefaultHandler { | ||||
|      * @param filter The filter. | ||||
|      * @param options Options passed to the filters. | ||||
|      * @param viewContainerRef The ViewContainerRef where the container is. | ||||
|      * @param component Component. | ||||
|      * @param componentId Component ID. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return If async, promise resolved when done. | ||||
|      */ | ||||
|     handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, | ||||
|             viewContainerRef: ViewContainerRef, siteId?: string): void | Promise<void> { | ||||
|             viewContainerRef: ViewContainerRef, component?: string, componentId?: string | number, siteId?: string) | ||||
|             : void | Promise<void> { | ||||
| 
 | ||||
|         const placeholders = <HTMLElement[]> Array.from(container.querySelectorAll('div.core-h5p-tmp-placeholder')); | ||||
| 
 | ||||
| @ -85,6 +88,8 @@ export class AddonFilterDisplayH5PHandler extends CoreFilterDefaultHandler { | ||||
|                 componentRef = viewContainerRef.createComponent(factory); | ||||
| 
 | ||||
|             componentRef.instance.src = url; | ||||
|             componentRef.instance.component = component; | ||||
|             componentRef.instance.componentId = componentId; | ||||
| 
 | ||||
|             // Move the component to its right position.
 | ||||
|             placeholder.parentElement.replaceChild(componentRef.instance.elementRef.nativeElement, placeholder); | ||||
|  | ||||
| @ -162,11 +162,14 @@ export class AddonFilterMathJaxLoaderHandler extends CoreFilterDefaultHandler { | ||||
|      * @param filter The filter. | ||||
|      * @param options Options passed to the filters. | ||||
|      * @param viewContainerRef The ViewContainerRef where the container is. | ||||
|      * @param component Component. | ||||
|      * @param componentId Component ID. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return If async, promise resolved when done. | ||||
|      */ | ||||
|     handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, | ||||
|             viewContainerRef: ViewContainerRef, siteId?: string): void | Promise<void> { | ||||
|             viewContainerRef: ViewContainerRef, component?: string, componentId?: string | number, siteId?: string) | ||||
|             : void | Promise<void> { | ||||
| 
 | ||||
|         return this.waitForReady().then(() => { | ||||
|             this.window.M.filter_mathjaxloader.typeset(container); | ||||
|  | ||||
| @ -32,6 +32,7 @@ import { AddonModAssignSyncProvider } from './assign-sync'; | ||||
| import { AddonModAssignFeedbackDelegate } from './feedback-delegate'; | ||||
| import { AddonModAssignSubmissionDelegate } from './submission-delegate'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch assigns. | ||||
| @ -51,6 +52,7 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected assignProvider: AddonModAssignProvider, | ||||
|             protected textUtils: CoreTextUtilsProvider, | ||||
|             protected feedbackDelegate: AddonModAssignFeedbackDelegate, | ||||
| @ -62,7 +64,8 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan | ||||
|             protected assignHelper: AddonModAssignHelperProvider, | ||||
|             protected syncProvider: AddonModAssignSyncProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -23,6 +23,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreCourseResourcePrefetchHandlerBase } from '@core/course/classes/resource-prefetch-handler'; | ||||
| import { AddonModBookProvider } from './book'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch books. | ||||
| @ -42,9 +43,11 @@ export class AddonModBookPrefetchHandler extends CoreCourseResourcePrefetchHandl | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected bookProvider: AddonModBookProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -25,6 +25,7 @@ import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/acti | ||||
| import { CoreUserProvider } from '@core/user/providers/user'; | ||||
| import { AddonModChatProvider, AddonModChatChat } from './chat'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch chats. | ||||
| @ -43,11 +44,13 @@ export class AddonModChatPrefetchHandler extends CoreCourseActivityPrefetchHandl | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             private groupsProvider: CoreGroupsProvider, | ||||
|             private userProvider: CoreUserProvider, | ||||
|             private chatProvider: AddonModChatProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -25,6 +25,7 @@ import { CoreUserProvider } from '@core/user/providers/user'; | ||||
| import { AddonModChoiceSyncProvider } from './sync'; | ||||
| import { AddonModChoiceProvider } from './choice'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch choices. | ||||
| @ -46,11 +47,13 @@ export class AddonModChoicePrefetchHandler extends CoreCourseActivityPrefetchHan | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected choiceProvider: AddonModChoiceProvider, | ||||
|             protected userProvider: CoreUserProvider, | ||||
|             protected injector: Injector) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -28,6 +28,7 @@ import { AddonModDataProvider, AddonModDataEntry } from './data'; | ||||
| import { AddonModDataSyncProvider } from './sync'; | ||||
| import { AddonModDataHelperProvider } from './helper'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch databases. | ||||
| @ -47,6 +48,7 @@ export class AddonModDataPrefetchHandler extends CoreCourseActivityPrefetchHandl | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected dataProvider: AddonModDataProvider, | ||||
|             protected timeUtils: CoreTimeUtilsProvider, | ||||
|             protected dataHelper: AddonModDataHelperProvider, | ||||
| @ -54,7 +56,8 @@ export class AddonModDataPrefetchHandler extends CoreCourseActivityPrefetchHandl | ||||
|             protected commentsProvider: CoreCommentsProvider, | ||||
|             protected syncProvider: AddonModDataSyncProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -27,6 +27,7 @@ import { CoreTimeUtilsProvider } from '@providers/utils/time'; | ||||
| import { CoreGroupsProvider } from '@providers/groups'; | ||||
| import { AddonModFeedbackSyncProvider } from './sync'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch feedbacks. | ||||
| @ -48,13 +49,15 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected feedbackProvider: AddonModFeedbackProvider, | ||||
|             protected feedbackHelper: AddonModFeedbackHelperProvider, | ||||
|             protected timeUtils: CoreTimeUtilsProvider, | ||||
|             protected groupsProvider: CoreGroupsProvider, | ||||
|             protected injector: Injector) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -23,6 +23,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreCourseResourcePrefetchHandlerBase } from '@core/course/classes/resource-prefetch-handler'; | ||||
| import { AddonModFolderProvider } from './folder'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch folders. | ||||
| @ -41,9 +42,11 @@ export class AddonModFolderPrefetchHandler extends CoreCourseResourcePrefetchHan | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected folderProvider: AddonModFolderProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -26,6 +26,7 @@ import { CoreGroupsProvider } from '@providers/groups'; | ||||
| import { AddonModForumProvider } from './forum'; | ||||
| import { AddonModForumSyncProvider } from './sync'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch forums. | ||||
| @ -45,12 +46,14 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             private userProvider: CoreUserProvider, | ||||
|             private groupsProvider: CoreGroupsProvider, | ||||
|             private forumProvider: AddonModForumProvider, | ||||
|             private syncProvider: AddonModForumSyncProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -25,6 +25,7 @@ import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/acti | ||||
| import { AddonModGlossaryProvider } from './glossary'; | ||||
| import { AddonModGlossarySyncProvider } from './sync'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch forums. | ||||
| @ -44,11 +45,13 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected glossaryProvider: AddonModGlossaryProvider, | ||||
|             protected commentsProvider: CoreCommentsProvider, | ||||
|             protected syncProvider: AddonModGlossarySyncProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -23,6 +23,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreCourseResourcePrefetchHandlerBase } from '@core/course/classes/resource-prefetch-handler'; | ||||
| import { AddonModImscpProvider } from './imscp'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch IMSCPs. | ||||
| @ -41,9 +42,11 @@ export class AddonModImscpPrefetchHandler extends CoreCourseResourcePrefetchHand | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected imscpProvider: AddonModImscpProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -23,6 +23,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreCourseResourcePrefetchHandlerBase } from '@core/course/classes/resource-prefetch-handler'; | ||||
| import { AddonModLabelProvider } from './label'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch labels. | ||||
| @ -43,9 +44,11 @@ export class AddonModLabelPrefetchHandler extends CoreCourseResourcePrefetchHand | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected labelProvider: AddonModLabelProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -26,6 +26,7 @@ import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/acti | ||||
| import { AddonModLessonProvider } from './lesson'; | ||||
| import { AddonModLessonSyncProvider } from './lesson-sync'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch lessons. | ||||
| @ -48,12 +49,14 @@ export class AddonModLessonPrefetchHandler extends CoreCourseActivityPrefetchHan | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected modalCtrl: ModalController, | ||||
|             protected groupsProvider: CoreGroupsProvider, | ||||
|             protected lessonProvider: AddonModLessonProvider, | ||||
|             protected injector: Injector) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -108,7 +111,9 @@ export class AddonModLessonPrefetchHandler extends CoreCourseActivityPrefetchHan | ||||
|             let files = lesson.mediafiles || []; | ||||
|             files = files.concat(this.getIntroFilesFromInstance(module, lesson)); | ||||
| 
 | ||||
|             result = this.utils.sumFileSizes(files); | ||||
|             return this.pluginFileDelegate.getFilesSize(files); | ||||
|         }).then((res) => { | ||||
|             result = res; | ||||
| 
 | ||||
|             // Get the pages to calculate the size.
 | ||||
|             return this.lessonProvider.getPages(lesson.id, password, false, false, siteId); | ||||
|  | ||||
| @ -23,6 +23,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; | ||||
| import { AddonModLtiProvider } from './lti'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch LTIs. LTIs cannot be prefetched, but the handler will be used to invalidate some data on course PTR. | ||||
| @ -41,9 +42,11 @@ export class AddonModLtiPrefetchHandler extends CoreCourseActivityPrefetchHandle | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected ltiProvider: AddonModLtiProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -24,6 +24,7 @@ import { CoreCourseResourcePrefetchHandlerBase } from '@core/course/classes/reso | ||||
| import { AddonModPageProvider } from './page'; | ||||
| import { AddonModPageHelperProvider } from './helper'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch pages. | ||||
| @ -43,10 +44,12 @@ export class AddonModPagePrefetchHandler extends CoreCourseResourcePrefetchHandl | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected pageProvider: AddonModPageProvider, | ||||
|             protected pageHelper: AddonModPageHelperProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -29,6 +29,7 @@ import { AddonModQuizAccessRuleDelegate } from './access-rules-delegate'; | ||||
| import { AddonModQuizSyncProvider } from './quiz-sync'; | ||||
| import { CoreConstants } from '@core/constants'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch quizzes. | ||||
| @ -50,6 +51,7 @@ export class AddonModQuizPrefetchHandler extends CoreCourseActivityPrefetchHandl | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected injector: Injector, | ||||
|             protected quizProvider: AddonModQuizProvider, | ||||
|             protected textUtils: CoreTextUtilsProvider, | ||||
| @ -57,7 +59,8 @@ export class AddonModQuizPrefetchHandler extends CoreCourseActivityPrefetchHandl | ||||
|             protected accessRuleDelegate: AddonModQuizAccessRuleDelegate, | ||||
|             protected questionHelper: CoreQuestionHelperProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -25,6 +25,7 @@ import { AddonModResourceProvider } from './resource'; | ||||
| import { AddonModResourceHelperProvider } from './helper'; | ||||
| import { CoreConstants } from '@core/constants'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch resources. | ||||
| @ -43,10 +44,12 @@ export class AddonModResourcePrefetchHandler extends CoreCourseResourcePrefetchH | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected resourceProvider: AddonModResourceProvider, | ||||
|             protected resourceHelper: AddonModResourceHelperProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -26,6 +26,7 @@ import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/acti | ||||
| import { AddonModScormProvider } from './scorm'; | ||||
| import { AddonModScormSyncProvider } from './scorm-sync'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Progress event used when downloading a SCORM. | ||||
| @ -67,12 +68,14 @@ export class AddonModScormPrefetchHandler extends CoreCourseActivityPrefetchHand | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected fileProvider: CoreFileProvider, | ||||
|             protected textUtils: CoreTextUtilsProvider, | ||||
|             protected scormProvider: AddonModScormProvider, | ||||
|             protected injector: Injector) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -25,6 +25,7 @@ import { AddonModSurveyProvider } from './survey'; | ||||
| import { AddonModSurveySyncProvider } from './sync'; | ||||
| import { AddonModSurveyHelperProvider } from './helper'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch surveys. | ||||
| @ -46,11 +47,13 @@ export class AddonModSurveyPrefetchHandler extends CoreCourseActivityPrefetchHan | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected surveyProvider: AddonModSurveyProvider, | ||||
|             protected surveyHelper: AddonModSurveyHelperProvider, | ||||
|             protected injector: Injector) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -23,6 +23,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreCourseResourcePrefetchHandlerBase } from '@core/course/classes/resource-prefetch-handler'; | ||||
| import { AddonModUrlProvider } from './url'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch URLs. URLs cannot be prefetched, but the handler will be used to invalidate some data on course PTR. | ||||
| @ -40,9 +41,11 @@ export class AddonModUrlPrefetchHandler extends CoreCourseResourcePrefetchHandle | ||||
|             filepoolProvider: CoreFilepoolProvider, | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider) { | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -29,6 +29,7 @@ import { CoreUserProvider } from '@core/user/providers/user'; | ||||
| import { AddonModWikiProvider } from './wiki'; | ||||
| import { AddonModWikiSyncProvider } from './wiki-sync'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch wikis. | ||||
| @ -48,6 +49,7 @@ export class AddonModWikiPrefetchHandler extends CoreCourseActivityPrefetchHandl | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected wikiProvider: AddonModWikiProvider, | ||||
|             protected userProvider: CoreUserProvider, | ||||
|             protected textUtils: CoreTextUtilsProvider, | ||||
| @ -56,7 +58,8 @@ export class AddonModWikiPrefetchHandler extends CoreCourseActivityPrefetchHandl | ||||
|             protected gradesHelper: CoreGradesHelperProvider, | ||||
|             protected syncProvider: AddonModWikiSyncProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -96,7 +99,7 @@ export class AddonModWikiPrefetchHandler extends CoreCourseActivityPrefetchHandl | ||||
|             siteId = this.sitesProvider.getCurrentSiteId(); | ||||
| 
 | ||||
|         promises.push(this.getFiles(module, courseId, single, siteId).then((files) => { | ||||
|             return this.utils.sumFileSizes(files); | ||||
|             return this.pluginFileDelegate.getFilesSize(files); | ||||
|         })); | ||||
| 
 | ||||
|         promises.push(this.getAllPages(module, courseId, false, true, siteId).then((pages) => { | ||||
|  | ||||
| @ -27,6 +27,7 @@ import { AddonModWorkshopProvider } from './workshop'; | ||||
| import { AddonModWorkshopSyncProvider } from './sync'; | ||||
| import { AddonModWorkshopHelperProvider } from './helper'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch workshops. | ||||
| @ -47,13 +48,15 @@ export class AddonModWorkshopPrefetchHandler extends CoreCourseActivityPrefetchH | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             private groupsProvider: CoreGroupsProvider, | ||||
|             private userProvider: CoreUserProvider, | ||||
|             private workshopProvider: AddonModWorkshopProvider, | ||||
|             private workshopHelper: AddonModWorkshopHelperProvider, | ||||
|             private syncProvider: AddonModWorkshopSyncProvider) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -23,6 +23,7 @@ import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| import { CoreConstants } from '@core/constants'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Component to handle a remote file. Shows the file name, icon (depending on mimetype) and a button | ||||
| @ -56,10 +57,16 @@ export class CoreFileComponent implements OnInit, OnDestroy { | ||||
|     protected timemodified: number; | ||||
|     protected observer; | ||||
| 
 | ||||
|     constructor(private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, private domUtils: CoreDomUtilsProvider, | ||||
|             private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider, | ||||
|             private fileHelper: CoreFileHelperProvider, private mimeUtils: CoreMimetypeUtilsProvider, | ||||
|             private eventsProvider: CoreEventsProvider, private textUtils: CoreTextUtilsProvider) { | ||||
|     constructor(private sitesProvider: CoreSitesProvider, | ||||
|             private utils: CoreUtilsProvider, | ||||
|             private domUtils: CoreDomUtilsProvider, | ||||
|             private filepoolProvider: CoreFilepoolProvider, | ||||
|             private appProvider: CoreAppProvider, | ||||
|             private fileHelper: CoreFileHelperProvider, | ||||
|             private mimeUtils: CoreMimetypeUtilsProvider, | ||||
|             private eventsProvider: CoreEventsProvider, | ||||
|             private textUtils: CoreTextUtilsProvider, | ||||
|             private pluginFileDelegate: CorePluginFileDelegate) { | ||||
|         this.onDelete = new EventEmitter(); | ||||
|     } | ||||
| 
 | ||||
| @ -141,8 +148,6 @@ export class CoreFileComponent implements OnInit, OnDestroy { | ||||
|         e && e.preventDefault(); | ||||
|         e && e.stopPropagation(); | ||||
| 
 | ||||
|         let promise; | ||||
| 
 | ||||
|         if (this.isDownloading && !openAfterDownload) { | ||||
|             return; | ||||
|         } | ||||
| @ -177,20 +182,26 @@ export class CoreFileComponent implements OnInit, OnDestroy { | ||||
|             }); | ||||
|         } else { | ||||
|             // File doesn't need to be opened (it's a prefetch). Show confirm modal if file size is defined and it's big.
 | ||||
|             promise = this.fileSize ? this.domUtils.confirmDownloadSize({ size: this.fileSize, total: true }) : Promise.resolve(); | ||||
|             promise.then(() => { | ||||
|                 // User confirmed, add the file to queue.
 | ||||
|                 return this.filepoolProvider.invalidateFileByUrl(this.siteId, this.fileUrl).finally(() => { | ||||
|                     this.isDownloading = true; | ||||
|             this.pluginFileDelegate.getFileSize({fileurl: this.fileUrl, filesize: this.fileSize}, this.siteId).then((size) => { | ||||
| 
 | ||||
|                     this.filepoolProvider.addToQueueByUrl(this.siteId, this.fileUrl, this.component, | ||||
|                         this.componentId, this.timemodified, undefined, undefined, 0, this.file).catch((error) => { | ||||
|                             this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true); | ||||
|                             this.calculateState(); | ||||
|                         }); | ||||
|                 const promise = size ? this.domUtils.confirmDownloadSize({ size: size, total: true }) : Promise.resolve(); | ||||
| 
 | ||||
|                 return promise.then(() => { | ||||
|                     // User confirmed, add the file to queue.
 | ||||
|                     return this.filepoolProvider.invalidateFileByUrl(this.siteId, this.fileUrl).finally(() => { | ||||
|                         this.isDownloading = true; | ||||
| 
 | ||||
|                         this.filepoolProvider.addToQueueByUrl(this.siteId, this.fileUrl, this.component, | ||||
|                             this.componentId, this.timemodified, undefined, undefined, 0, this.file).catch((error) => { | ||||
|                                 this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true); | ||||
|                                 this.calculateState(); | ||||
|                             }); | ||||
|                     }); | ||||
|                 }).catch(() => { | ||||
|                     // User cancelled.
 | ||||
|                 }); | ||||
|             }).catch(() => { | ||||
|                 // Ignore error.
 | ||||
|             }).catch((error) => { | ||||
|                 this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -21,6 +21,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreCourseProvider } from '../providers/course'; | ||||
| import { CoreCourseModulePrefetchHandler } from '../providers/module-prefetch-delegate'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Base prefetch handler to be registered in CoreCourseModulePrefetchDelegate. Prefetch handlers should inherit either | ||||
| @ -67,7 +68,8 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref | ||||
|             protected filepoolProvider: CoreFilepoolProvider, | ||||
|             protected sitesProvider: CoreSitesProvider, | ||||
|             protected domUtils: CoreDomUtilsProvider, | ||||
|             protected filterHelper: CoreFilterHelperProvider) { } | ||||
|             protected filterHelper: CoreFilterHelperProvider, | ||||
|             protected pluginFileDelegate: CorePluginFileDelegate) { } | ||||
| 
 | ||||
|     /** | ||||
|      * Add an ongoing download to the downloadPromises list. When the promise finishes it will be removed. | ||||
| @ -137,7 +139,7 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref | ||||
|      */ | ||||
|     getDownloadSize(module: any, courseId: number, single?: boolean): Promise<{ size: number, total: boolean }> { | ||||
|         return this.getFiles(module, courseId).then((files) => { | ||||
|             return this.utils.sumFileSizes(files); | ||||
|             return this.pluginFileDelegate.getFilesSize(files); | ||||
|         }).catch(() => { | ||||
|             return { size: -1, total: false }; | ||||
|         }); | ||||
|  | ||||
| @ -51,11 +51,14 @@ export class CoreFilterDefaultHandler implements CoreFilterHandler { | ||||
|      * @param filter The filter. | ||||
|      * @param options Options passed to the filters. | ||||
|      * @param viewContainerRef The ViewContainerRef where the container is. | ||||
|      * @param component Component. | ||||
|      * @param componentId Component ID. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return If async, promise resolved when done. | ||||
|      */ | ||||
|     handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, | ||||
|             viewContainerRef: ViewContainerRef, siteId?: string): void | Promise<void> { | ||||
|             viewContainerRef: ViewContainerRef, component?: string, componentId?: string | number, siteId?: string) | ||||
|             : void | Promise<void> { | ||||
|         // To be overridden.
 | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -49,11 +49,14 @@ export interface CoreFilterHandler extends CoreDelegateHandler { | ||||
|      * @param filter The filter. | ||||
|      * @param options Options passed to the filters. | ||||
|      * @param viewContainerRef The ViewContainerRef where the container is. | ||||
|      * @param component Component. | ||||
|      * @param componentId Component ID. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return If async, promise resolved when done. | ||||
|      */ | ||||
|     handleHtml?(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, | ||||
|             viewContainerRef: ViewContainerRef, siteId?: string): void | Promise<void>; | ||||
|             viewContainerRef: ViewContainerRef, component?: string, componentId?: string | number, siteId?: string) | ||||
|             : void | Promise<void>; | ||||
| 
 | ||||
|     /** | ||||
|      * Check if the filter should be applied in a certain site based on some filter options. | ||||
| @ -160,11 +163,13 @@ export class CoreFilterDelegate extends CoreDelegate { | ||||
|      * @param viewContainerRef The ViewContainerRef where the container is. | ||||
|      * @param options Options passed to the filters. | ||||
|      * @param skipFilters Names of filters that shouldn't be applied. | ||||
|      * @param component Component. | ||||
|      * @param componentId Component ID. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     handleHtml(container: HTMLElement, filters: CoreFilterFilter[], viewContainerRef?: ViewContainerRef, options?: any, | ||||
|             skipFilters?: string[], siteId?: string): Promise<any> { | ||||
|             skipFilters?: string[], component?: string, componentId?: string | number, siteId?: string): Promise<any> { | ||||
| 
 | ||||
|         // Wait for filters to be initialized.
 | ||||
|         return this.handlersInitPromise.then(() => { | ||||
| @ -184,7 +189,7 @@ export class CoreFilterDelegate extends CoreDelegate { | ||||
| 
 | ||||
|                 promise = promise.then(() => { | ||||
|                     return Promise.resolve(this.executeFunctionOnEnabled(filter.filter, 'handleHtml', | ||||
|                             [container, filter, options, viewContainerRef, siteId])).catch((error) => { | ||||
|                             [container, filter, options, viewContainerRef, component, componentId, siteId])).catch((error) => { | ||||
|                         this.logger.error('Error handling HTML' + filter.filter, error); | ||||
|                     }); | ||||
|                 }); | ||||
|  | ||||
| @ -1,11 +1,9 @@ | ||||
| <div *ngIf="!showPackage" class="core-h5p-placeholder"> | ||||
|     <button *ngIf="!loading && !errorMessage" class="core-h5p-placeholder-play-button" ion-button icon-only clear (click)="play($event)"> | ||||
|     <button *ngIf="!loading" class="core-h5p-placeholder-play-button" ion-button icon-only clear (click)="play($event)"> | ||||
|         <core-icon name="fa-play-circle"></core-icon> | ||||
|     </button> | ||||
| 
 | ||||
|     <ion-spinner *ngIf="loading && !errorMessage" class="core-h5p-placeholder-spinner"></ion-spinner> | ||||
| 
 | ||||
|     <div *ngIf="errorMessage" class="core-h5p-placeholder-error">{{ errorMessage }}</div> | ||||
|     <ion-spinner *ngIf="loading" class="core-h5p-placeholder-spinner"></ion-spinner> | ||||
| 
 | ||||
|     <div class="core-h5p-placeholder-download-container"> | ||||
|         <core-download-refresh [status]="state" [enabled]="canDownload" [loading]="calculating" [canTrustDownload]="true" (action)="download()"></core-download-refresh> | ||||
|  | ||||
| @ -42,13 +42,6 @@ ion-app.app-root core-h5p-player { | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         .core-h5p-placeholder-error { | ||||
|             position: absolute; | ||||
|             width: 100%; | ||||
|             text-align: center; | ||||
|             top: 50%; | ||||
|         } | ||||
| 
 | ||||
|         ion-spinner circle { | ||||
|             stroke: $core-h5p-placeholder-text-color; | ||||
|         } | ||||
|  | ||||
| @ -12,12 +12,17 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Component, Input, ElementRef, OnInit, SimpleChange } from '@angular/core'; | ||||
| import { Component, Input, ElementRef, OnInit, OnDestroy, OnChanges, SimpleChange } from '@angular/core'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CoreEventsProvider } from '@providers/events'; | ||||
| import { CoreFilepoolProvider } from '@providers/filepool'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| import { CoreUrlUtilsProvider } from '@providers/utils/url'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreH5PProvider } from '@core/h5p/providers/h5p'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Component to render an H5P package. | ||||
| @ -26,23 +31,38 @@ import { CoreH5PProvider } from '@core/h5p/providers/h5p'; | ||||
|     selector: 'core-h5p-player', | ||||
|     templateUrl: 'core-h5p-player.html' | ||||
| }) | ||||
| export class CoreH5PPlayerComponent implements OnInit { | ||||
| export class CoreH5PPlayerComponent implements OnInit, OnChanges, OnDestroy { | ||||
|     @Input() src: string; // The URL of the player to display the H5P package.
 | ||||
|     @Input() component?: string; // Component.
 | ||||
|     @Input() componentId?: string | number; // Component ID to use in conjunction with the component.
 | ||||
| 
 | ||||
|     playerSrc: string; | ||||
|     showPackage = false; | ||||
|     loading = false; | ||||
|     status: string; | ||||
|     state: string; | ||||
|     canDownload: boolean; | ||||
|     calculating = true; | ||||
|     errorMessage: string; | ||||
| 
 | ||||
|     protected siteId: string; | ||||
|     protected siteCanDownload: boolean; | ||||
|     protected observer; | ||||
|     protected urlParams; | ||||
| 
 | ||||
|     constructor(public elementRef: ElementRef, | ||||
|             protected sitesProvider: CoreSitesProvider, | ||||
|             protected urlUtils: CoreUrlUtilsProvider, | ||||
|             protected utils: CoreUtilsProvider, | ||||
|             protected textUtils: CoreTextUtilsProvider, | ||||
|             protected h5pProvider: CoreH5PProvider) { } | ||||
|             protected h5pProvider: CoreH5PProvider, | ||||
|             protected filepoolProvider: CoreFilepoolProvider, | ||||
|             protected eventsProvider: CoreEventsProvider, | ||||
|             protected appProvider: CoreAppProvider, | ||||
|             protected domUtils: CoreDomUtilsProvider, | ||||
|             protected pluginFileDelegate: CorePluginFileDelegate) { | ||||
| 
 | ||||
|         this.siteId = sitesProvider.getCurrentSiteId(); | ||||
|         this.siteCanDownload = this.sitesProvider.getCurrentSite().canDownloadFiles(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Component being initialized. | ||||
| @ -85,37 +105,49 @@ export class CoreH5PPlayerComponent implements OnInit { | ||||
|     /** | ||||
|      * Download the package. | ||||
|      */ | ||||
|     download(): void { | ||||
|         // @TODO: Implement package download.
 | ||||
|     download(e: Event): void { | ||||
|         e && e.preventDefault(); | ||||
|         e && e.stopPropagation(); | ||||
| 
 | ||||
|         if (!this.appProvider.isOnline()) { | ||||
|             this.domUtils.showErrorModal('core.networkerrormsg', true); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Get the file size and ask the user to confirm.
 | ||||
|         this.pluginFileDelegate.getFileSize({fileurl: this.urlParams.url}, this.siteId).then((size) => { | ||||
|             return this.domUtils.confirmDownloadSize({ size: size, total: true }).then(() => { | ||||
| 
 | ||||
|                 // User confirmed, add to the queue.
 | ||||
|                 return this.filepoolProvider.addToQueueByUrl(this.siteId, this.urlParams.url, this.component, this.componentId); | ||||
|             }, () => { | ||||
|                 // User cancelled.
 | ||||
|             }); | ||||
|         }).catch((error) => { | ||||
|             this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true); | ||||
|             this.calculateState(); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if the package can be downloaded. | ||||
|      */ | ||||
|     protected checkCanDownload(): void { | ||||
|         if (this.src && this.h5pProvider.canGetTrustedH5PFileInSite()) { | ||||
|             const params = this.urlUtils.extractUrlParams(this.src); | ||||
|         this.observer && this.observer.off(); | ||||
|         this.urlParams = this.urlUtils.extractUrlParams(this.src); | ||||
| 
 | ||||
|             // @todo: Check if H5P offline is disabled in the site.
 | ||||
|         if (this.src && this.siteCanDownload && this.h5pProvider.canGetTrustedH5PFileInSite()) { | ||||
| 
 | ||||
|             // Now check if the package can be played.
 | ||||
|             this.calculating = true; | ||||
| 
 | ||||
|             const options = { | ||||
|                 frame: this.utils.isTrueOrOne(params.frame), | ||||
|                 export: this.utils.isTrueOrOne(params.export), | ||||
|                 embed: this.utils.isTrueOrOne(params.embed), | ||||
|                 copyright: this.utils.isTrueOrOne(params.copyright), | ||||
|             }; | ||||
|             this.calculateState(); | ||||
| 
 | ||||
|             this.h5pProvider.getTrustedH5PFile(params.url, options).then((file) => { | ||||
|                 this.canDownload = true; | ||||
|                 this.errorMessage = undefined; | ||||
|             }).catch((error) => { | ||||
|                 this.canDownload = false; | ||||
|                 this.errorMessage = this.textUtils.getErrorMessageFromError(error); | ||||
|             }).finally(() => { | ||||
|                 this.calculating = false; | ||||
|             // Listen for changes in the state.
 | ||||
|             this.filepoolProvider.getFileEventNameByUrl(this.siteId, this.urlParams.url).then((eventName) => { | ||||
|                 this.observer = this.eventsProvider.on(eventName, () => { | ||||
|                     this.calculateState(); | ||||
|                 }); | ||||
|             }); | ||||
| 
 | ||||
|             return; | ||||
| @ -123,6 +155,29 @@ export class CoreH5PPlayerComponent implements OnInit { | ||||
| 
 | ||||
|         this.calculating = false; | ||||
|         this.canDownload = false; | ||||
|         this.errorMessage = undefined; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Calcuñate state of the file. | ||||
|      * | ||||
|      * @param fileUrl The H5P file URL. | ||||
|      */ | ||||
|     protected calculateState(): void { | ||||
|         // Get the status of the file.
 | ||||
|         this.filepoolProvider.getFileStateByUrl(this.siteId, this.urlParams.url).then((state) => { | ||||
|             this.canDownload = true; | ||||
|             this.state = state; | ||||
|         }).catch((error) => { | ||||
|             this.canDownload = false; | ||||
|         }).finally(() => { | ||||
|             this.calculating = false; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Component destroyed. | ||||
|      */ | ||||
|     ngOnDestroy(): void { | ||||
|         this.observer && this.observer.off(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -15,6 +15,8 @@ | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { CoreH5PComponentsModule } from './components/components.module'; | ||||
| import { CoreH5PProvider } from './providers/h5p'; | ||||
| import { CoreH5PPluginFileHandler } from './providers/pluginfile-handler'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| // List of providers (without handlers).
 | ||||
| export const CORE_H5P_PROVIDERS: any[] = [ | ||||
| @ -27,8 +29,15 @@ export const CORE_H5P_PROVIDERS: any[] = [ | ||||
|         CoreH5PComponentsModule | ||||
|     ], | ||||
|     providers: [ | ||||
|         CoreH5PProvider | ||||
|         CoreH5PProvider, | ||||
|         CoreH5PPluginFileHandler | ||||
|     ], | ||||
|     exports: [] | ||||
| }) | ||||
| export class CoreH5PModule { } | ||||
| export class CoreH5PModule { | ||||
|     constructor(pluginfileDelegate: CorePluginFileDelegate, | ||||
|             pluginfileHandler: CoreH5PPluginFileHandler) { | ||||
| 
 | ||||
|         pluginfileDelegate.registerHandler(pluginfileHandler); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -17,6 +17,7 @@ import { CoreLoggerProvider } from '@providers/logger'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; | ||||
| import { CoreWSExternalWarning, CoreWSExternalFile } from '@providers/ws'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| 
 | ||||
| /** | ||||
|  * Service to provide H5P functionalities. | ||||
| @ -29,7 +30,8 @@ export class CoreH5PProvider { | ||||
|     protected logger; | ||||
| 
 | ||||
|     constructor(logger: CoreLoggerProvider, | ||||
|             private sitesProvider: CoreSitesProvider) { | ||||
|             private sitesProvider: CoreSitesProvider, | ||||
|             private textUtils: CoreTextUtilsProvider) { | ||||
| 
 | ||||
|         this.logger = logger.getInstance('CoreFilterProvider'); | ||||
|     } | ||||
| @ -69,13 +71,15 @@ export class CoreH5PProvider { | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the file data. | ||||
|      */ | ||||
|     getTrustedH5PFile(url: string, options: CoreH5PGetTrustedFileOptions, ignoreCache?: boolean, siteId?: string) | ||||
|     getTrustedH5PFile(url: string, options?: CoreH5PGetTrustedFileOptions, ignoreCache?: boolean, siteId?: string) | ||||
|             : Promise<CoreWSExternalFile> { | ||||
| 
 | ||||
|         options = options || {}; | ||||
| 
 | ||||
|         return this.sitesProvider.getSite(siteId).then((site) => { | ||||
| 
 | ||||
|             const data = { | ||||
|                     url: url, | ||||
|                     url: this.treatH5PUrl(url, site.getURL()), | ||||
|                     frame: options.frame ? 1 : 0, | ||||
|                     export: options.export ? 1 : 0, | ||||
|                     embed: options.embed ? 1 : 0, | ||||
| @ -124,6 +128,21 @@ export class CoreH5PProvider { | ||||
|         return this.ROOT_CACHE_KEY + 'trustedH5PFile:'; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Treat an H5P url before sending it to WS. | ||||
|      * | ||||
|      * @param url H5P file URL. | ||||
|      * @param siteUrl Site URL. | ||||
|      * @return Treated url. | ||||
|      */ | ||||
|     protected treatH5PUrl(url: string, siteUrl: string): string { | ||||
|         if (url.indexOf(this.textUtils.concatenatePaths(siteUrl, '/webservice/pluginfile.php')) === 0) { | ||||
|             url = url.replace('/webservice/pluginfile', '/pluginfile'); | ||||
|         } | ||||
| 
 | ||||
|         return url; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Invalidates all trusted H5P file WS calls. | ||||
|      * | ||||
|  | ||||
							
								
								
									
										121
									
								
								src/core/h5p/providers/pluginfile-handler.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								src/core/h5p/providers/pluginfile-handler.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | ||||
| // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { CoreFileProvider } from '@providers/file'; | ||||
| import { CorePluginFileHandler } from '@providers/plugin-file-delegate'; | ||||
| import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| import { CoreUrlUtilsProvider } from '@providers/utils/url'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreH5PProvider } from './h5p'; | ||||
| import { CoreWSExternalFile } from '@providers/ws'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to treat H5P files. | ||||
|  */ | ||||
| @Injectable() | ||||
| export class CoreH5PPluginFileHandler implements CorePluginFileHandler { | ||||
|     name = 'CoreH5PPluginFileHandler'; | ||||
| 
 | ||||
|     constructor(protected urlUtils: CoreUrlUtilsProvider, | ||||
|             protected mimeUtils: CoreMimetypeUtilsProvider, | ||||
|             protected textUtils: CoreTextUtilsProvider, | ||||
|             protected utils: CoreUtilsProvider, | ||||
|             protected fileProvider: CoreFileProvider, | ||||
|             protected h5pProvider: CoreH5PProvider) { } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether a file can be downloaded. If so, return the file to download. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the file to use. Rejected if cannot download. | ||||
|      */ | ||||
|     canDownloadFile(file: CoreWSExternalFile, siteId?: string): Promise<CoreWSExternalFile> { | ||||
|         return this.h5pProvider.getTrustedH5PFile(file.fileurl, {}, false, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Given an HTML element, get the URLs of the files that should be downloaded and weren't treated by | ||||
|      * CoreDomUtilsProvider.extractDownloadableFilesFromHtml. | ||||
|      * | ||||
|      * @param container Container where to get the URLs from. | ||||
|      * @return {string[]} List of URLs. | ||||
|      */ | ||||
|     getDownloadableFiles(container: HTMLElement): string[] { | ||||
|         const iframes = <HTMLIFrameElement[]> Array.from(container.querySelectorAll('iframe.h5p-iframe')); | ||||
|         const urls = []; | ||||
| 
 | ||||
|         for (let i = 0; i < iframes.length; i++) { | ||||
|             const params = this.urlUtils.extractUrlParams(iframes[i].src); | ||||
| 
 | ||||
|             if (params.url) { | ||||
|                 urls.push(params.url); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return urls; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a file size. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the size. | ||||
|      */ | ||||
|     getFileSize(file: CoreWSExternalFile, siteId?: string): Promise<number> { | ||||
|         return this.h5pProvider.getTrustedH5PFile(file.fileurl, {}, false, siteId).then((file) => { | ||||
|             return file.filesize; | ||||
|         }).catch((error): any => { | ||||
|             if (this.utils.isWebServiceError(error)) { | ||||
|                 // WS returned an error, it means it cannot be downloaded.
 | ||||
|                 return 0; | ||||
|             } | ||||
| 
 | ||||
|             return Promise.reject(error); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether the file should be treated by this handler. It is used in functions where the component isn't used. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @return Whether the file should be treated by this handler. | ||||
|      */ | ||||
|     shouldHandleFile(file: CoreWSExternalFile): boolean { | ||||
|         return this.mimeUtils.guessExtensionFromUrl(file.fileurl) == 'h5p'; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Treat a downloaded file. | ||||
|      * | ||||
|      * @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. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     treatDownloadedFile(fileUrl: string, file: FileEntry, siteId?: string): Promise<any> { | ||||
|         // Unzip the file.
 | ||||
|         const destFolder = this.textUtils.concatenatePaths(CoreFileProvider.TMPFOLDER, | ||||
|                 'h5p/' + this.mimeUtils.removeExtension(file.name)); | ||||
| 
 | ||||
|         return this.fileProvider.createDir(destFolder).then(() => { | ||||
|             return this.fileProvider.unzipFile(file.toURL(), destFolder); | ||||
|         }).then(() => { | ||||
|             // @todo: Deploy the package.
 | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @ -22,6 +22,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreSitePluginsProvider } from '../../providers/siteplugins'; | ||||
| import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to prefetch a module site plugin. | ||||
| @ -39,13 +40,15 @@ export class CoreSitePluginsModulePrefetchHandler extends CoreCourseActivityPref | ||||
|             sitesProvider: CoreSitesProvider, | ||||
|             domUtils: CoreDomUtilsProvider, | ||||
|             filterHelper: CoreFilterHelperProvider, | ||||
|             pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected sitePluginsProvider: CoreSitePluginsProvider, | ||||
|             component: string, | ||||
|             name: string, | ||||
|             modName: string, | ||||
|             protected handlerSchema: any) { | ||||
| 
 | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); | ||||
|         super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper, | ||||
|                 pluginFileDelegate); | ||||
| 
 | ||||
|         this.component = component; | ||||
|         this.name = name; | ||||
|  | ||||
| @ -32,6 +32,7 @@ import { CoreQuestionProvider } from '@core/question/providers/question'; | ||||
| import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreCoursesProvider } from '@core/courses/providers/courses'; | ||||
| import { CoreFilterHelperProvider } from '@core/filter/providers/helper'; | ||||
| import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; | ||||
| 
 | ||||
| // Delegates
 | ||||
| import { CoreMainMenuDelegate } from '@core/mainmenu/providers/delegate'; | ||||
| @ -117,7 +118,8 @@ export class CoreSitePluginsHelperProvider { | ||||
|             private workshopAssessmentStrategyDelegate: AddonWorkshopAssessmentStrategyDelegate, | ||||
|             private courseProvider: CoreCourseProvider, | ||||
|             private blockDelegate: CoreBlockDelegate, | ||||
|             private filterHelper: CoreFilterHelperProvider) { | ||||
|             private filterHelper: CoreFilterHelperProvider, | ||||
|             private pluginFileDelegate: CorePluginFileDelegate) { | ||||
| 
 | ||||
|         this.logger = loggerProvider.getInstance('CoreSitePluginsHelperProvider'); | ||||
| 
 | ||||
| @ -841,7 +843,7 @@ export class CoreSitePluginsHelperProvider { | ||||
|             // Register the prefetch handler.
 | ||||
|             this.prefetchDelegate.registerHandler(new CoreSitePluginsModulePrefetchHandler(this.translate, this.appProvider, | ||||
|                 this.utils, this.courseProvider, this.filepoolProvider, this.sitesProvider, this.domUtils, this.filterHelper, | ||||
|                 this.sitePluginsProvider, plugin.component, uniqueName, modName, handlerSchema)); | ||||
|                 this.pluginFileDelegate, this.sitePluginsProvider, plugin.component, uniqueName, modName, handlerSchema)); | ||||
|         } | ||||
| 
 | ||||
|         return uniqueName; | ||||
|  | ||||
| @ -375,7 +375,7 @@ export class CoreFormatTextDirective implements OnChanges { | ||||
|             if (result.options.filter) { | ||||
|                 // Let filters hnadle HTML. We do it here because we don't want them to block the render of the text.
 | ||||
|                 this.filterDelegate.handleHtml(this.element, result.filters, this.viewContainerRef, result.options, [], | ||||
|                         result.siteId); | ||||
|                         this.component, this.componentId, result.siteId); | ||||
|             } | ||||
| 
 | ||||
|             this.element.classList.remove('core-disable-media-adapt'); | ||||
|  | ||||
| @ -21,7 +21,7 @@ import { CoreInitDelegate } from './init'; | ||||
| import { CoreLoggerProvider } from './logger'; | ||||
| import { CorePluginFileDelegate } from './plugin-file-delegate'; | ||||
| import { CoreSitesProvider, CoreSiteSchema } from './sites'; | ||||
| import { CoreWSProvider } from './ws'; | ||||
| import { CoreWSProvider, CoreWSExternalFile } from './ws'; | ||||
| import { CoreDomUtilsProvider } from './utils/dom'; | ||||
| import { CoreMimetypeUtilsProvider } from './utils/mimetype'; | ||||
| import { CoreTextUtilsProvider } from './utils/text'; | ||||
| @ -473,8 +473,8 @@ export class CoreFilepoolProvider { | ||||
|      * downloading a file automatically does this. Note that this method does not check if the file exists in the pool. | ||||
|      */ | ||||
|     addFileLinkByUrl(siteId: string, fileUrl: string, component: string, componentId?: string | number): Promise<any> { | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((fileUrl) => { | ||||
|             const fileId = this.getFileIdByUrl(fileUrl); | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((file) => { | ||||
|             const fileId = this.getFileIdByUrl(file.fileurl); | ||||
| 
 | ||||
|             return this.addFileLink(siteId, fileId, component, componentId); | ||||
|         }); | ||||
| @ -605,11 +605,12 @@ export class CoreFilepoolProvider { | ||||
|      * @param priority The priority this file should get in the queue (range 0-999). | ||||
|      * @param options Extra options (isexternalfile, repositorytype). | ||||
|      * @param revision File revision. If not defined, it will be calculated using the URL. | ||||
|      * @param alreadyFixed Whether the URL has already been fixed. | ||||
|      * @return Resolved on success. | ||||
|      */ | ||||
|     addToQueueByUrl(siteId: string, fileUrl: string, component?: string, componentId?: string | number, timemodified: number = 0, | ||||
|             filePath?: string, onProgress?: (event: any) => any, priority: number = 0, options: any = {}, revision?: number) | ||||
|             : Promise<any> { | ||||
|             filePath?: string, onProgress?: (event: any) => any, priority: number = 0, options: any = {}, revision?: number, | ||||
|             alreadyFixed?: boolean): Promise<any> { | ||||
|         let fileId, | ||||
|             link, | ||||
|             queueDeferred; | ||||
| @ -623,94 +624,102 @@ export class CoreFilepoolProvider { | ||||
|                 return Promise.reject(null); | ||||
|             } | ||||
| 
 | ||||
|             return this.fixPluginfileURL(siteId, fileUrl).then((fileUrl) => { | ||||
|                 const primaryKey = { siteId: siteId, fileId: fileId }; | ||||
|             if (alreadyFixed) { | ||||
|                 // Already fixed, if we reached here it means it can be downloaded.
 | ||||
|                 return <CoreWSExternalFile> {fileurl: fileUrl}; | ||||
|             } else { | ||||
|                 return this.fixPluginfileURL(siteId, fileUrl); | ||||
|             } | ||||
|         }).then((file) => { | ||||
| 
 | ||||
|                 revision = revision || this.getRevisionFromUrl(fileUrl); | ||||
|                 fileId = this.getFileIdByUrl(fileUrl); | ||||
|             fileUrl = file.fileurl; | ||||
|             timemodified = file.timemodified || timemodified; | ||||
|             revision = revision || this.getRevisionFromUrl(fileUrl); | ||||
|             fileId = this.getFileIdByUrl(fileUrl); | ||||
| 
 | ||||
|                 // Set up the component.
 | ||||
|                 if (typeof component != 'undefined') { | ||||
|                     link = { | ||||
|                         component: component, | ||||
|                         componentId: this.fixComponentId(componentId) | ||||
|                     }; | ||||
|                 } | ||||
|             const primaryKey = { siteId: siteId, fileId: fileId }; | ||||
| 
 | ||||
|                 // Retrieve the queue deferred now if it exists.
 | ||||
|                 // This is to prevent errors if file is removed from queue while we're checking if the file is in queue.
 | ||||
|                 queueDeferred = this.getQueueDeferred(siteId, fileId, false, onProgress); | ||||
|             // Set up the component.
 | ||||
|             if (typeof component != 'undefined') { | ||||
|                 link = { | ||||
|                     component: component, | ||||
|                     componentId: this.fixComponentId(componentId) | ||||
|                 }; | ||||
|             } | ||||
| 
 | ||||
|                 return this.hasFileInQueue(siteId, fileId).then((entry: CoreFilepoolQueueEntry) => { | ||||
|                     const newData: any = {}; | ||||
|                     let foundLink = false; | ||||
|             // Retrieve the queue deferred now if it exists.
 | ||||
|             // This is to prevent errors if file is removed from queue while we're checking if the file is in queue.
 | ||||
|             queueDeferred = this.getQueueDeferred(siteId, fileId, false, onProgress); | ||||
| 
 | ||||
|                     if (entry) { | ||||
|                         // We already have the file in queue, we update the priority and links.
 | ||||
|                         if (entry.priority < priority) { | ||||
|                             newData.priority = priority; | ||||
|                         } | ||||
|                         if (revision && entry.revision !== revision) { | ||||
|                             newData.revision = revision; | ||||
|                         } | ||||
|                         if (timemodified && entry.timemodified !== timemodified) { | ||||
|                             newData.timemodified = timemodified; | ||||
|                         } | ||||
|                         if (filePath && entry.path !== filePath) { | ||||
|                             newData.path = filePath; | ||||
|                         } | ||||
|                         if (entry.isexternalfile !== options.isexternalfile && (entry.isexternalfile || options.isexternalfile)) { | ||||
|                             newData.isexternalfile = options.isexternalfile; | ||||
|                         } | ||||
|                         if (entry.repositorytype !== options.repositorytype && (entry.repositorytype || options.repositorytype)) { | ||||
|                             newData.repositorytype = options.repositorytype; | ||||
|                         } | ||||
|             return this.hasFileInQueue(siteId, fileId).then((entry: CoreFilepoolQueueEntry) => { | ||||
|                 const newData: any = {}; | ||||
|                 let foundLink = false; | ||||
| 
 | ||||
|                         if (link) { | ||||
|                             // We need to add the new link if it does not exist yet.
 | ||||
|                             if (entry.links && entry.links.length) { | ||||
|                                 for (const i in entry.links) { | ||||
|                                     const fileLink = entry.links[i]; | ||||
|                                     if (fileLink.component == link.component && fileLink.componentId == link.componentId) { | ||||
|                                         foundLink = true; | ||||
|                                         break; | ||||
|                                     } | ||||
|                 if (entry) { | ||||
|                     // We already have the file in queue, we update the priority and links.
 | ||||
|                     if (entry.priority < priority) { | ||||
|                         newData.priority = priority; | ||||
|                     } | ||||
|                     if (revision && entry.revision !== revision) { | ||||
|                         newData.revision = revision; | ||||
|                     } | ||||
|                     if (timemodified && entry.timemodified !== timemodified) { | ||||
|                         newData.timemodified = timemodified; | ||||
|                     } | ||||
|                     if (filePath && entry.path !== filePath) { | ||||
|                         newData.path = filePath; | ||||
|                     } | ||||
|                     if (entry.isexternalfile !== options.isexternalfile && (entry.isexternalfile || options.isexternalfile)) { | ||||
|                         newData.isexternalfile = options.isexternalfile; | ||||
|                     } | ||||
|                     if (entry.repositorytype !== options.repositorytype && (entry.repositorytype || options.repositorytype)) { | ||||
|                         newData.repositorytype = options.repositorytype; | ||||
|                     } | ||||
| 
 | ||||
|                     if (link) { | ||||
|                         // We need to add the new link if it does not exist yet.
 | ||||
|                         if (entry.links && entry.links.length) { | ||||
|                             for (const i in entry.links) { | ||||
|                                 const fileLink = entry.links[i]; | ||||
|                                 if (fileLink.component == link.component && fileLink.componentId == link.componentId) { | ||||
|                                     foundLink = true; | ||||
|                                     break; | ||||
|                                 } | ||||
|                             } | ||||
| 
 | ||||
|                             if (!foundLink) { | ||||
|                                 newData.links = entry.links || []; | ||||
|                                 newData.links.push(link); | ||||
|                                 newData.links = JSON.stringify(entry.links); | ||||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|                         if (Object.keys(newData).length) { | ||||
|                             // Update only when required.
 | ||||
|                             this.logger.debug(`Updating file ${fileId} which is already in queue`); | ||||
| 
 | ||||
|                             return this.appDB.updateRecords(this.QUEUE_TABLE, newData, primaryKey).then(() => { | ||||
|                                 return this.getQueuePromise(siteId, fileId, true, onProgress); | ||||
|                             }); | ||||
|                         if (!foundLink) { | ||||
|                             newData.links = entry.links || []; | ||||
|                             newData.links.push(link); | ||||
|                             newData.links = JSON.stringify(entry.links); | ||||
|                         } | ||||
| 
 | ||||
|                         this.logger.debug(`File ${fileId} already in queue and does not require update`); | ||||
|                         if (queueDeferred) { | ||||
|                             // If we were able to retrieve the queue deferred before, we use that one.
 | ||||
|                             return queueDeferred.promise; | ||||
|                         } else { | ||||
|                             // Create a new deferred and return its promise.
 | ||||
|                             return this.getQueuePromise(siteId, fileId, true, onProgress); | ||||
|                         } | ||||
|                     } else { | ||||
|                         return this.addToQueue( | ||||
|                             siteId, fileId, fileUrl, priority, revision, timemodified, filePath, onProgress, options, link); | ||||
|                     } | ||||
|                 }, () => { | ||||
|                     // Unsure why we could not get the record, let's add to the queue anyway.
 | ||||
| 
 | ||||
|                     if (Object.keys(newData).length) { | ||||
|                         // Update only when required.
 | ||||
|                         this.logger.debug(`Updating file ${fileId} which is already in queue`); | ||||
| 
 | ||||
|                         return this.appDB.updateRecords(this.QUEUE_TABLE, newData, primaryKey).then(() => { | ||||
|                             return this.getQueuePromise(siteId, fileId, true, onProgress); | ||||
|                         }); | ||||
|                     } | ||||
| 
 | ||||
|                     this.logger.debug(`File ${fileId} already in queue and does not require update`); | ||||
|                     if (queueDeferred) { | ||||
|                         // If we were able to retrieve the queue deferred before, we use that one.
 | ||||
|                         return queueDeferred.promise; | ||||
|                     } else { | ||||
|                         // Create a new deferred and return its promise.
 | ||||
|                         return this.getQueuePromise(siteId, fileId, true, onProgress); | ||||
|                     } | ||||
|                 } else { | ||||
|                     return this.addToQueue( | ||||
|                         siteId, fileId, fileUrl, priority, revision, timemodified, filePath, onProgress, options, link); | ||||
|                 }); | ||||
|                 } | ||||
|             }, () => { | ||||
|                 // Unsure why we could not get the record, let's add to the queue anyway.
 | ||||
|                 return this.addToQueue( | ||||
|                     siteId, fileId, fileUrl, priority, revision, timemodified, filePath, onProgress, options, link); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| @ -719,7 +728,7 @@ export class CoreFilepoolProvider { | ||||
|      * Adds a file to the queue if the size is allowed to be downloaded. | ||||
|      * | ||||
|      * @param siteId The site ID. | ||||
|      * @param fileUrl The absolute URL to the file. | ||||
|      * @param fileUrl The absolute URL to the file, already fixed. | ||||
|      * @param component The component to link the file to. | ||||
|      * @param componentId An ID to use in conjunction with the component. | ||||
|      * @param timemodified The time this file was modified. | ||||
| @ -760,18 +769,18 @@ export class CoreFilepoolProvider { | ||||
|                 // Check if the file should be downloaded.
 | ||||
|                 if (sizeUnknown) { | ||||
|                     if (downloadUnknown && isWifi) { | ||||
|                         return this.addToQueueByUrl( | ||||
|                             siteId, fileUrl, component, componentId, timemodified, undefined, undefined, 0, options, revision); | ||||
|                         return this.addToQueueByUrl(siteId, fileUrl, component, componentId, timemodified, undefined, undefined, | ||||
|                                 0, options, revision, true); | ||||
|                     } | ||||
|                 } else if (size <= this.DOWNLOAD_THRESHOLD || (isWifi && size <= this.WIFI_DOWNLOAD_THRESHOLD)) { | ||||
|                     return this.addToQueueByUrl( | ||||
|                         siteId, fileUrl, component, componentId, timemodified, undefined, undefined, 0, options, revision); | ||||
|                     return this.addToQueueByUrl(siteId, fileUrl, component, componentId, timemodified, undefined, undefined, 0, | ||||
|                             options, revision, true); | ||||
|                 } | ||||
|             }); | ||||
|         } else { | ||||
|             // No need to check size, just add it to the queue.
 | ||||
|             return this.addToQueueByUrl(siteId, fileUrl, component, componentId, timemodified, undefined, undefined, 0, options, | ||||
|                     revision); | ||||
|                     revision, true); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -938,7 +947,13 @@ export class CoreFilepoolProvider { | ||||
|                     return Promise.reject(null); | ||||
|                 } | ||||
| 
 | ||||
|                 return this.wsProvider.downloadFile(fileUrl, filePath, addExtension, onProgress).then((fileEntry) => { | ||||
|                 let fileEntry; | ||||
| 
 | ||||
|                 return this.wsProvider.downloadFile(fileUrl, filePath, addExtension, onProgress).then((entry) => { | ||||
|                     fileEntry = entry; | ||||
| 
 | ||||
|                     return this.pluginFileDelegate.treatDownloadedFile(fileUrl, fileEntry, siteId); | ||||
|                 }).then(() => { | ||||
|                     const data: CoreFilepoolFileEntry = poolFileObject || {}; | ||||
| 
 | ||||
|                     data.downloadTime = Date.now(); | ||||
| @ -1157,8 +1172,10 @@ export class CoreFilepoolProvider { | ||||
|             promise; | ||||
| 
 | ||||
|         if (this.fileProvider.isAvailable()) { | ||||
|             return this.fixPluginfileURL(siteId, fileUrl).then((fixedUrl) => { | ||||
|                 fileUrl = fixedUrl; | ||||
|             return this.fixPluginfileURL(siteId, fileUrl).then((file) => { | ||||
| 
 | ||||
|                 fileUrl = file.fileurl; | ||||
|                 timemodified = file.timemodified || timemodified; | ||||
| 
 | ||||
|                 options = Object.assign({}, options); // Create a copy to prevent modifying the original object.
 | ||||
|                 options.timemodified = timemodified || 0; | ||||
| @ -1313,15 +1330,24 @@ export class CoreFilepoolProvider { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Add the wstoken url and points to the correct script. | ||||
|      * Check whether the file can be downloaded, add the wstoken url and points to the correct script. | ||||
|      * | ||||
|      * @param siteId The site ID. | ||||
|      * @param fileUrl The file URL. | ||||
|      * @return Resolved with fixed URL on success, rejected otherwise. | ||||
|      * @param timemodified The timemodified of the file. | ||||
|      * @return Promise resolved with the file data to use. | ||||
|      */ | ||||
|     protected fixPluginfileURL(siteId: string, fileUrl: string): Promise<string> { | ||||
|         return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|             return site.checkAndFixPluginfileURL(fileUrl); | ||||
|     protected fixPluginfileURL(siteId: string, fileUrl: string, timemodified: number = 0): Promise<CoreWSExternalFile> { | ||||
| 
 | ||||
|         return this.pluginFileDelegate.canDownloadFile({fileurl: fileUrl, timemodified: timemodified}).then((file) => { | ||||
| 
 | ||||
|             return this.sitesProvider.getSite(siteId).then((site) => { | ||||
|                 return site.checkAndFixPluginfileURL(file.fileurl); | ||||
|             }).then((fixedUrl) => { | ||||
|                 file.fileurl = fixedUrl; | ||||
| 
 | ||||
|                 return file; | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| @ -1351,8 +1377,8 @@ export class CoreFilepoolProvider { | ||||
|      */ | ||||
|     getDirectoryUrlByUrl(siteId: string, fileUrl: string): Promise<string> { | ||||
|         if (this.fileProvider.isAvailable()) { | ||||
|             return this.fixPluginfileURL(siteId, fileUrl).then((fileUrl) => { | ||||
|                 const fileId = this.getFileIdByUrl(fileUrl), | ||||
|             return this.fixPluginfileURL(siteId, fileUrl).then((file) => { | ||||
|                 const fileId = this.getFileIdByUrl(file.fileurl), | ||||
|                     filePath = <string> this.getFilePath(siteId, fileId, ''); // No extension, the function will return a string.
 | ||||
| 
 | ||||
|                 return this.fileProvider.getDir(filePath).then((dirEntry) => { | ||||
| @ -1394,8 +1420,8 @@ export class CoreFilepoolProvider { | ||||
|      * @return Promise resolved with event name. | ||||
|      */ | ||||
|     getFileEventNameByUrl(siteId: string, fileUrl: string): Promise<string> { | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((fileUrl) => { | ||||
|             const fileId = this.getFileIdByUrl(fileUrl); | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((file) => { | ||||
|             const fileId = this.getFileIdByUrl(file.fileurl); | ||||
| 
 | ||||
|             return this.getFileEventName(siteId, fileId); | ||||
|         }); | ||||
| @ -1490,8 +1516,8 @@ export class CoreFilepoolProvider { | ||||
|      * @return Promise resolved with the path to the file relative to storage root. | ||||
|      */ | ||||
|     getFilePathByUrl(siteId: string, fileUrl: string): Promise<string> { | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((fileUrl) => { | ||||
|             const fileId = this.getFileIdByUrl(fileUrl); | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((file) => { | ||||
|             const fileId = this.getFileIdByUrl(file.fileurl); | ||||
| 
 | ||||
|             return this.getFilePath(siteId, fileId); | ||||
|         }); | ||||
| @ -1587,8 +1613,10 @@ export class CoreFilepoolProvider { | ||||
|             : Promise<string> { | ||||
|         let fileId; | ||||
| 
 | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((fixedUrl) => { | ||||
|             fileUrl = fixedUrl; | ||||
|         return this.fixPluginfileURL(siteId, fileUrl, timemodified).then((file) => { | ||||
| 
 | ||||
|             fileUrl = file.fileurl; | ||||
|             timemodified = file.timemodified || timemodified; | ||||
|             revision = revision || this.getRevisionFromUrl(fileUrl); | ||||
|             fileId = this.getFileIdByUrl(fileUrl); | ||||
| 
 | ||||
| @ -1618,6 +1646,8 @@ export class CoreFilepoolProvider { | ||||
|                     }); | ||||
|                 }); | ||||
|             }); | ||||
|         }, () => { | ||||
|             return CoreConstants.NOT_DOWNLOADABLE; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| @ -1655,8 +1685,10 @@ export class CoreFilepoolProvider { | ||||
|                     }); | ||||
|             }; | ||||
| 
 | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((fixedUrl) => { | ||||
|             fileUrl = fixedUrl; | ||||
|         return this.fixPluginfileURL(siteId, fileUrl, timemodified).then((file) => { | ||||
| 
 | ||||
|             fileUrl = file.fileurl; | ||||
|             timemodified = file.timemodified || timemodified; | ||||
|             revision = revision || this.getRevisionFromUrl(fileUrl); | ||||
|             fileId = this.getFileIdByUrl(fileUrl); | ||||
| 
 | ||||
| @ -1779,8 +1811,8 @@ export class CoreFilepoolProvider { | ||||
|      */ | ||||
|     getInternalUrlByUrl(siteId: string, fileUrl: string): Promise<string> { | ||||
|         if (this.fileProvider.isAvailable()) { | ||||
|             return this.fixPluginfileURL(siteId, fileUrl).then((fileUrl) => { | ||||
|                 const fileId = this.getFileIdByUrl(fileUrl); | ||||
|             return this.fixPluginfileURL(siteId, fileUrl).then((file) => { | ||||
|                 const fileId = this.getFileIdByUrl(file.fileurl); | ||||
| 
 | ||||
|                 return this.getInternalUrlById(siteId, fileId); | ||||
|             }); | ||||
| @ -1843,8 +1875,8 @@ export class CoreFilepoolProvider { | ||||
|      * @return Promise resolved with the path of the package. | ||||
|      */ | ||||
|     getPackageDirPathByUrl(siteId: string, url: string): Promise<string> { | ||||
|         return this.fixPluginfileURL(siteId, url).then((fixedUrl) => { | ||||
|             const dirName = this.getPackageDirNameByUrl(fixedUrl); | ||||
|         return this.fixPluginfileURL(siteId, url).then((file) => { | ||||
|             const dirName = this.getPackageDirNameByUrl(file.fileurl); | ||||
| 
 | ||||
|             return this.getFilePath(siteId, dirName, ''); | ||||
|         }); | ||||
| @ -1859,8 +1891,8 @@ export class CoreFilepoolProvider { | ||||
|      */ | ||||
|     getPackageDirUrlByUrl(siteId: string, url: string): Promise<string> { | ||||
|         if (this.fileProvider.isAvailable()) { | ||||
|             return this.fixPluginfileURL(siteId, url).then((fixedUrl) => { | ||||
|                 const dirName = this.getPackageDirNameByUrl(fixedUrl), | ||||
|             return this.fixPluginfileURL(siteId, url).then((file) => { | ||||
|                 const dirName = this.getPackageDirNameByUrl(file.fileurl), | ||||
|                     dirPath = <string> this.getFilePath(siteId, dirName, ''); // No extension, the function will return a string.
 | ||||
| 
 | ||||
|                 return this.fileProvider.getDir(dirPath).then((dirEntry) => { | ||||
| @ -2270,8 +2302,8 @@ export class CoreFilepoolProvider { | ||||
|      * Please note that, if a file is stale, the user will be presented the stale file if there is no network access. | ||||
|      */ | ||||
|     invalidateFileByUrl(siteId: string, fileUrl: string): Promise<any> { | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((fileUrl) => { | ||||
|             const fileId = this.getFileIdByUrl(fileUrl); | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((file) => { | ||||
|             const fileId = this.getFileIdByUrl(file.fileurl); | ||||
| 
 | ||||
|             return this.sitesProvider.getSiteDb(siteId).then((db) => { | ||||
|                 return db.updateRecords(this.FILES_TABLE, { stale: 1 }, { fileId: fileId }); | ||||
| @ -2318,8 +2350,8 @@ export class CoreFilepoolProvider { | ||||
|      * @param Promise resolved if file is downloading, rejected otherwise. | ||||
|      */ | ||||
|     isFileDownloadingByUrl(siteId: string, fileUrl: string): Promise<any> { | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((fileUrl) => { | ||||
|             const fileId = this.getFileIdByUrl(fileUrl); | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((file) => { | ||||
|             const fileId = this.getFileIdByUrl(file.fileurl); | ||||
| 
 | ||||
|             return this.hasFileInQueue(siteId, fileId); | ||||
|         }); | ||||
| @ -2667,8 +2699,8 @@ export class CoreFilepoolProvider { | ||||
|      * @return Resolved on success, rejected on failure. | ||||
|      */ | ||||
|     removeFileByUrl(siteId: string, fileUrl: string): Promise<any> { | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((fileUrl) => { | ||||
|             const fileId = this.getFileIdByUrl(fileUrl); | ||||
|         return this.fixPluginfileURL(siteId, fileUrl).then((file) => { | ||||
|             const fileId = this.getFileIdByUrl(file.fileurl); | ||||
| 
 | ||||
|             return this.removeFileById(siteId, fileId); | ||||
|         }); | ||||
|  | ||||
| @ -14,6 +14,7 @@ | ||||
| 
 | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { CoreLoggerProvider } from './logger'; | ||||
| import { CoreWSExternalFile } from '@providers/ws'; | ||||
| 
 | ||||
| /** | ||||
|  * Interface that all plugin file handlers must implement. | ||||
| @ -26,8 +27,9 @@ export interface CorePluginFileHandler { | ||||
| 
 | ||||
|     /** | ||||
|      * The "component" of the handler. It should match the "component" of pluginfile URLs. | ||||
|      * It is used to treat revision from URLs. | ||||
|      */ | ||||
|     component: string; | ||||
|     component?: string; | ||||
| 
 | ||||
|     /** | ||||
|      * Return the RegExp to match the revision on pluginfile URLs. | ||||
| @ -44,6 +46,51 @@ export interface CorePluginFileHandler { | ||||
|      * @return String to remove the revision on pluginfile url. | ||||
|      */ | ||||
|     getComponentRevisionReplace?(args: string[]): string; | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether a file can be downloaded. If so, return the file to download. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the file to use. Rejected if cannot download. | ||||
|      */ | ||||
|     canDownloadFile?(file: CoreWSExternalFile, siteId?: string): Promise<CoreWSExternalFile>; | ||||
| 
 | ||||
|     /** | ||||
|      * Given an HTML element, get the URLs of the files that should be downloaded and weren't treated by | ||||
|      * CoreDomUtilsProvider.extractDownloadableFilesFromHtml. | ||||
|      * | ||||
|      * @param container Container where to get the URLs from. | ||||
|      * @return {string[]} List of URLs. | ||||
|      */ | ||||
|     getDownloadableFiles?(container: HTMLElement): string[]; | ||||
| 
 | ||||
|     /** | ||||
|      * Get a file size. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the size. | ||||
|      */ | ||||
|     getFileSize?(file: CoreWSExternalFile, siteId?: string): Promise<number>; | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether the file should be treated by this handler. It is used in functions where the component isn't used. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @return Whether the file should be treated by this handler. | ||||
|      */ | ||||
|     shouldHandleFile?(file: CoreWSExternalFile): boolean; | ||||
| 
 | ||||
|     /** | ||||
|      * Treat a downloaded file. | ||||
|      * | ||||
|      * @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. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     treatDownloadedFile?(fileUrl: string, file: FileEntry, siteId?: string): Promise<any>; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -58,6 +105,39 @@ export class CorePluginFileDelegate { | ||||
|         this.logger = logger.getInstance('CorePluginFileDelegate'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether a file can be downloaded. If so, return the file to download. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the file to use. Rejected if cannot download. | ||||
|      */ | ||||
|     canDownloadFile(file: CoreWSExternalFile, siteId?: string): Promise<CoreWSExternalFile> { | ||||
|         const handler = this.getHandlerForFile(file); | ||||
| 
 | ||||
|         return this.canHandlerDownloadFile(file, handler, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether a file can be downloaded. If so, return the file to download. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param handler The handler to use. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the file to use. Rejected if cannot download. | ||||
|      */ | ||||
|     protected canHandlerDownloadFile(file: CoreWSExternalFile, handler: CorePluginFileHandler, siteId?: string) | ||||
|             : Promise<CoreWSExternalFile> { | ||||
| 
 | ||||
|         if (handler && handler.canDownloadFile) { | ||||
|             return handler.canDownloadFile(file, siteId).then((newFile) => { | ||||
|                 return newFile || file; | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         return Promise.resolve(file); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the handler for a certain pluginfile url. | ||||
|      * | ||||
| @ -85,6 +165,99 @@ export class CorePluginFileDelegate { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Given an HTML element, get the URLs of the files that should be downloaded and weren't treated by | ||||
|      * CoreDomUtilsProvider.extractDownloadableFilesFromHtml. | ||||
|      * | ||||
|      * @param container Container where to get the URLs from. | ||||
|      * @return List of URLs. | ||||
|      */ | ||||
|     getDownloadableFiles(container: HTMLElement): string[] { | ||||
|         let files = []; | ||||
| 
 | ||||
|         for (const component in this.handlers) { | ||||
|             const handler = this.handlers[component]; | ||||
| 
 | ||||
|             if (handler && handler.getDownloadableFiles) { | ||||
|                 files = files.concat(handler.getDownloadableFiles(container)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return files; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Sum the filesizes from a list of files checking if the size will be partial or totally calculated. | ||||
|      * | ||||
|      * @param files List of files to sum its filesize. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with file size and a boolean to indicate if it is the total size or only partial. | ||||
|      */ | ||||
|     getFilesSize(files: CoreWSExternalFile[], siteId?: string): Promise<{ size: number, total: boolean }> { | ||||
|         const promises = [], | ||||
|             result = { | ||||
|                 size: 0, | ||||
|                 total: true | ||||
|             }; | ||||
| 
 | ||||
|         files.forEach((file) => { | ||||
|             promises.push(this.getFileSize(file, siteId).then((size) => { | ||||
|                 if (typeof size == 'undefined') { | ||||
|                     // We don't have the file size, cannot calculate its total size.
 | ||||
|                     result.total = false; | ||||
|                 } else { | ||||
|                     result.size += size; | ||||
|                 } | ||||
|             })); | ||||
|         }); | ||||
| 
 | ||||
|         return Promise.all(promises).then(() => { | ||||
|             return result; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a file size. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the size. | ||||
|      */ | ||||
|     getFileSize(file: CoreWSExternalFile, siteId?: string): Promise<number> { | ||||
|         const handler = this.getHandlerForFile(file); | ||||
| 
 | ||||
|         // First of all check if file can be downloaded.
 | ||||
|         return this.canHandlerDownloadFile(file, handler, siteId).then((canDownload) => { | ||||
|             if (!canDownload) { | ||||
|                 return 0; | ||||
|             } | ||||
| 
 | ||||
|             if (handler && handler.getFileSize) { | ||||
|                 return handler.getFileSize(file, siteId).catch(() => { | ||||
|                     return file.filesize; | ||||
|                 }); | ||||
|             } | ||||
| 
 | ||||
|             return Promise.resolve(file.filesize); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a handler to treat a certain file. | ||||
|      * | ||||
|      * @param file File data. | ||||
|      * @return Handler. | ||||
|      */ | ||||
|     protected getHandlerForFile(file: CoreWSExternalFile): CorePluginFileHandler { | ||||
|         for (const component in this.handlers) { | ||||
|             const handler = this.handlers[component]; | ||||
| 
 | ||||
|             if (handler && handler.shouldHandleFile && handler.shouldHandleFile(file)) { | ||||
|                 return handler; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Register a handler. | ||||
|      * | ||||
| @ -92,14 +265,14 @@ export class CorePluginFileDelegate { | ||||
|      * @return True if registered successfully, false otherwise. | ||||
|      */ | ||||
|     registerHandler(handler: CorePluginFileHandler): boolean { | ||||
|         if (typeof this.handlers[handler.component] !== 'undefined') { | ||||
|         if (typeof this.handlers[handler.component || handler.name] !== 'undefined') { | ||||
|             this.logger.log(`Handler '${handler.component}' already registered`); | ||||
| 
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         this.logger.log(`Registered handler '${handler.component}'`); | ||||
|         this.handlers[handler.component] = handler; | ||||
|         this.handlers[handler.component || handler.name] = handler; | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| @ -124,4 +297,22 @@ export class CorePluginFileDelegate { | ||||
| 
 | ||||
|         return url; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Treat a downloaded file. | ||||
|      * | ||||
|      * @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. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     treatDownloadedFile(fileUrl: string, file: FileEntry, siteId?: string): Promise<any> { | ||||
|         const handler = this.getHandlerForFile({fileurl: fileUrl}); | ||||
| 
 | ||||
|         if (handler && handler.getFileSize) { | ||||
|             return handler.treatDownloadedFile(fileUrl, file, siteId); | ||||
|         } | ||||
| 
 | ||||
|         return Promise.resolve(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -22,6 +22,7 @@ import { TranslateService } from '@ngx-translate/core'; | ||||
| import { CoreTextUtilsProvider } from './text'; | ||||
| import { CoreAppProvider } from '../app'; | ||||
| import { CoreConfigProvider } from '../config'; | ||||
| import { CorePluginFileDelegate } from '../plugin-file-delegate'; | ||||
| import { CoreUrlUtilsProvider } from './url'; | ||||
| import { CoreFileProvider } from '@providers/file'; | ||||
| import { CoreConstants } from '@core/constants'; | ||||
| @ -62,11 +63,20 @@ export class CoreDomUtilsProvider { | ||||
|     protected debugDisplay = false; // Whether to display debug messages. Store it in a variable to make it synchronous.
 | ||||
|     protected displayedAlerts = {}; // To prevent duplicated alerts.
 | ||||
| 
 | ||||
|     constructor(private translate: TranslateService, private loadingCtrl: LoadingController, private toastCtrl: ToastController, | ||||
|             private alertCtrl: AlertController, private textUtils: CoreTextUtilsProvider, private appProvider: CoreAppProvider, | ||||
|             private platform: Platform, private configProvider: CoreConfigProvider, private urlUtils: CoreUrlUtilsProvider, | ||||
|             private modalCtrl: ModalController, private sanitizer: DomSanitizer, private popoverCtrl: PopoverController, | ||||
|             private fileProvider: CoreFileProvider) { | ||||
|     constructor(private translate: TranslateService, | ||||
|             private loadingCtrl: LoadingController, | ||||
|             private toastCtrl: ToastController, | ||||
|             private alertCtrl: AlertController, | ||||
|             private textUtils: CoreTextUtilsProvider, | ||||
|             private appProvider: CoreAppProvider, | ||||
|             private platform: Platform, | ||||
|             private configProvider: CoreConfigProvider, | ||||
|             private urlUtils: CoreUrlUtilsProvider, | ||||
|             private modalCtrl: ModalController, | ||||
|             private sanitizer: DomSanitizer, | ||||
|             private popoverCtrl: PopoverController, | ||||
|             private fileProvider: CoreFileProvider, | ||||
|             private pluginFileDelegate: CorePluginFileDelegate) { | ||||
| 
 | ||||
|         // Check if debug messages should be displayed.
 | ||||
|         configProvider.get(CoreConstants.SETTINGS_DEBUG_DISPLAY, false).then((debugDisplay) => { | ||||
| @ -252,7 +262,7 @@ export class CoreDomUtilsProvider { | ||||
|      * @return List of file urls. | ||||
|      */ | ||||
|     extractDownloadableFilesFromHtml(html: string): string[] { | ||||
|         const urls = []; | ||||
|         let urls = []; | ||||
|         let elements; | ||||
| 
 | ||||
|         const element = this.convertToElement(html); | ||||
| @ -275,6 +285,9 @@ export class CoreDomUtilsProvider { | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Now get other files from plugin file handlers.
 | ||||
|         urls = urls.concat(this.pluginFileDelegate.getDownloadableFiles(element)); | ||||
| 
 | ||||
|         return urls; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -1287,6 +1287,7 @@ export class CoreUtilsProvider { | ||||
|      * | ||||
|      * @param files List of files to sum its filesize. | ||||
|      * @return File size and a boolean to indicate if it is the total size or only partial. | ||||
|      * @deprecated since 3.8.0. Use CorePluginFileDelegate.getFilesSize instead. | ||||
|      */ | ||||
|     sumFileSizes(files: any[]): { size: number, total: boolean } { | ||||
|         const result = { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user