forked from EVOgeek/Vmeda.Online
		
	
						commit
						e245e50c8e
					
				| @ -1619,6 +1619,7 @@ | ||||
|   "core.h5p.offlineDialogRetryButtonLabel": "h5p", | ||||
|   "core.h5p.offlineDialogRetryMessage": "h5p", | ||||
|   "core.h5p.offlineSuccessfulSubmit": "h5p", | ||||
|   "core.h5p.offlinedisabled": "local_moodlemobileapp", | ||||
|   "core.h5p.originator": "h5p", | ||||
|   "core.h5p.pd": "h5p", | ||||
|   "core.h5p.pddl": "h5p", | ||||
|  | ||||
| @ -119,6 +119,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp | ||||
|     protected fetchContent(refresh?: boolean): Promise<any> { | ||||
|         const promises = []; | ||||
|         let downloadFailed = false; | ||||
|         let downloadFailError; | ||||
| 
 | ||||
|         // Try to get the book data.
 | ||||
|         promises.push(this.bookProvider.getBook(this.courseId, this.module.id).then((book) => { | ||||
| @ -129,9 +130,10 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp | ||||
|         })); | ||||
| 
 | ||||
|         // Download content. This function also loads module contents if needed.
 | ||||
|         promises.push(this.prefetchDelegate.download(this.module, this.courseId).catch(() => { | ||||
|         promises.push(this.prefetchDelegate.download(this.module, this.courseId).catch((error) => { | ||||
|             // Mark download as failed but go on since the main files could have been downloaded.
 | ||||
|             downloadFailed = true; | ||||
|             downloadFailError = error; | ||||
| 
 | ||||
|             if (!this.module.contents.length) { | ||||
|                 // Try to load module contents for offline usage.
 | ||||
| @ -163,7 +165,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp | ||||
|             return this.loadChapter(this.currentChapter).then(() => { | ||||
|                 if (downloadFailed && this.appProvider.isOnline()) { | ||||
|                     // We could load the main file but the download failed. Show error message.
 | ||||
|                     this.domUtils.showErrorModal('core.errordownloadingsomefiles', true); | ||||
|                     this.showErrorDownloadingSomeFiles(downloadFailError); | ||||
|                 } | ||||
|             }).catch(() => { | ||||
|                 // Ignore errors, they're handled inside the loadChapter function.
 | ||||
|  | ||||
| @ -76,6 +76,7 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom | ||||
|      */ | ||||
|     protected fetchContent(refresh?: boolean): Promise<any> { | ||||
|         let downloadFailed = false; | ||||
|         let downloadFailError; | ||||
|         const promises = []; | ||||
| 
 | ||||
|         promises.push(this.imscpProvider.getImscp(this.courseId, this.module.id).then((imscp) => { | ||||
| @ -83,9 +84,10 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom | ||||
|             this.dataRetrieved.emit(imscp); | ||||
|         })); | ||||
| 
 | ||||
|         promises.push(this.imscpPrefetch.download(this.module, this.courseId).catch(() => { | ||||
|         promises.push(this.imscpPrefetch.download(this.module, this.courseId).catch((error) => { | ||||
|             // Mark download as failed but go on since the main files could have been downloaded.
 | ||||
|             downloadFailed = true; | ||||
|             downloadFailError = error; | ||||
| 
 | ||||
|             return this.courseProvider.loadModuleContents(this.module, this.courseId).catch((error) => { | ||||
|                 // Error getting module contents, fail.
 | ||||
| @ -109,7 +111,7 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom | ||||
|         }).then(() => { | ||||
|             if (downloadFailed && this.appProvider.isOnline()) { | ||||
|                 // We could load the main file but the download failed. Show error message.
 | ||||
|                 this.domUtils.showErrorModal('core.errordownloadingsomefiles', true); | ||||
|                 this.showErrorDownloadingSomeFiles(downloadFailError); | ||||
|             } | ||||
| 
 | ||||
|         }).finally(() => { | ||||
|  | ||||
| @ -78,11 +78,13 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp | ||||
|      */ | ||||
|     protected fetchContent(refresh?: boolean): Promise<any> { | ||||
|         let downloadFailed = false; | ||||
|         let downloadFailError; | ||||
| 
 | ||||
|         // Download content. This function also loads module contents if needed.
 | ||||
|         return this.pagePrefetch.download(this.module, this.courseId).catch(() => { | ||||
|         return this.pagePrefetch.download(this.module, this.courseId).catch((error) => { | ||||
|             // Mark download as failed but go on since the main files could have been downloaded.
 | ||||
|             downloadFailed = true; | ||||
|             downloadFailError = error; | ||||
|         }).then(() => { | ||||
|             if (!this.module.contents.length) { | ||||
|                 // Try to load module contents for offline usage.
 | ||||
| @ -132,7 +134,7 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp | ||||
| 
 | ||||
|                 if (downloadFailed && this.appProvider.isOnline()) { | ||||
|                     // We could load the main file but the download failed. Show error message.
 | ||||
|                     this.domUtils.showErrorModal('core.errordownloadingsomefiles', true); | ||||
|                     this.showErrorDownloadingSomeFiles(downloadFailError); | ||||
|                 } | ||||
|             })); | ||||
| 
 | ||||
|  | ||||
| @ -14,6 +14,7 @@ | ||||
| 
 | ||||
| import { Component, Injector } from '@angular/core'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CoreFilepoolProvider } from '@providers/filepool'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| @ -38,10 +39,15 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource | ||||
|     contentText: string; | ||||
|     displayDescription = true; | ||||
| 
 | ||||
|     constructor(injector: Injector, private resourceProvider: AddonModResourceProvider, private courseProvider: CoreCourseProvider, | ||||
|             private appProvider: CoreAppProvider, private prefetchHandler: AddonModResourcePrefetchHandler, | ||||
|             private resourceHelper: AddonModResourceHelperProvider, private sitesProvider: CoreSitesProvider, | ||||
|             private utils: CoreUtilsProvider) { | ||||
|     constructor(injector: Injector, | ||||
|             protected resourceProvider: AddonModResourceProvider, | ||||
|             protected courseProvider: CoreCourseProvider, | ||||
|             protected appProvider: CoreAppProvider, | ||||
|             protected prefetchHandler: AddonModResourcePrefetchHandler, | ||||
|             protected resourceHelper: AddonModResourceHelperProvider, | ||||
|             protected sitesProvider: CoreSitesProvider, | ||||
|             protected utils: CoreUtilsProvider, | ||||
|             protected filepoolProvider: CoreFilepoolProvider) { | ||||
|         super(injector); | ||||
|     } | ||||
| 
 | ||||
| @ -104,10 +110,12 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource | ||||
| 
 | ||||
|             if (this.resourceHelper.isDisplayedInIframe(this.module)) { | ||||
|                 let downloadFailed = false; | ||||
|                 let downloadFailError; | ||||
| 
 | ||||
|                 return this.prefetchHandler.download(this.module, this.courseId).catch(() => { | ||||
|                 return this.prefetchHandler.download(this.module, this.courseId).catch((error) => { | ||||
|                     // Mark download as failed but go on since the main files could have been downloaded.
 | ||||
|                     downloadFailed = true; | ||||
|                     downloadFailError = error; | ||||
|                 }).then(() => { | ||||
|                     return this.resourceHelper.getIframeSrc(this.module).then((src) => { | ||||
|                         this.mode = 'iframe'; | ||||
| @ -125,7 +133,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource | ||||
| 
 | ||||
|                         if (downloadFailed && this.appProvider.isOnline()) { | ||||
|                             // We could load the main file but the download failed. Show error message.
 | ||||
|                             this.domUtils.showErrorModal('core.errordownloadingsomefiles', true); | ||||
|                             this.showErrorDownloadingSomeFiles(downloadFailError); | ||||
|                         } | ||||
|                     }); | ||||
|                 }); | ||||
| @ -147,15 +155,23 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource | ||||
| 
 | ||||
|     /** | ||||
|      * Opens a file. | ||||
|      * | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     open(): void { | ||||
|         this.prefetchHandler.isDownloadable(this.module, this.courseId).then((downloadable) => { | ||||
|     async open(): Promise<void> { | ||||
|         let downloadable = await this.prefetchHandler.isDownloadable(this.module, this.courseId); | ||||
| 
 | ||||
|         if (downloadable) { | ||||
|             // Check if the main file is downloadle.
 | ||||
|             // This isn't done in "isDownloadable" to prevent extra WS calls in the course page.
 | ||||
|             downloadable = await this.resourceHelper.isMainFileDownloadable(this.module); | ||||
| 
 | ||||
|             if (downloadable) { | ||||
|                 this.resourceHelper.openModuleFile(this.module, this.courseId); | ||||
|             } else { | ||||
|                 // The resource cannot be downloaded, open the activity in browser.
 | ||||
|                 return this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(this.module.url); | ||||
|                 return this.resourceHelper.openModuleFile(this.module, this.courseId); | ||||
|             } | ||||
|         }); | ||||
|         } | ||||
| 
 | ||||
|         // The resource cannot be downloaded, open the activity in browser.
 | ||||
|         return this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(this.module.url); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -20,6 +20,7 @@ import { AddonModResourceProvider } from './resource'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreFilepoolProvider } from '@providers/filepool'; | ||||
| import { CoreFileProvider } from '@providers/file'; | ||||
| import { CoreFileHelperProvider } from '@providers/file-helper'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| @ -36,11 +37,17 @@ export class AddonModResourceHelperProvider { | ||||
|     // Display using object tag.
 | ||||
|     protected DISPLAY_EMBED = 1; | ||||
| 
 | ||||
|     constructor(private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider, | ||||
|             private resourceProvider: AddonModResourceProvider, private courseHelper: CoreCourseHelperProvider, | ||||
|             private textUtils: CoreTextUtilsProvider, private mimetypeUtils: CoreMimetypeUtilsProvider, | ||||
|             private fileProvider: CoreFileProvider, private appProvider: CoreAppProvider, | ||||
|             private filepoolProvider: CoreFilepoolProvider, private sitesProvider: CoreSitesProvider) { | ||||
|     constructor(protected courseProvider: CoreCourseProvider, | ||||
|             protected domUtils: CoreDomUtilsProvider, | ||||
|             protected resourceProvider: AddonModResourceProvider, | ||||
|             protected courseHelper: CoreCourseHelperProvider, | ||||
|             protected textUtils: CoreTextUtilsProvider, | ||||
|             protected mimetypeUtils: CoreMimetypeUtilsProvider, | ||||
|             protected fileProvider: CoreFileProvider, | ||||
|             protected appProvider: CoreAppProvider, | ||||
|             protected filepoolProvider: CoreFilepoolProvider, | ||||
|             protected sitesProvider: CoreSitesProvider, | ||||
|             protected fileHelper: CoreFileHelperProvider) { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -136,6 +143,23 @@ export class AddonModResourceHelperProvider { | ||||
|         return mimetype == 'text/html'; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if main file of resource is downloadable. | ||||
|      * | ||||
|      * @param module Module instance. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with boolean: whether main file is downloadable. | ||||
|      */ | ||||
|     isMainFileDownloadable(module: any, siteId?: string): Promise<boolean> { | ||||
|         siteId = siteId || this.sitesProvider.getCurrentSiteId(); | ||||
| 
 | ||||
|         const mainFile = module.contents[0]; | ||||
|         const fileUrl = this.fileHelper.getFileUrl(mainFile); | ||||
|         const timemodified = this.fileHelper.getFileTimemodified(mainFile); | ||||
| 
 | ||||
|         return this.filepoolProvider.isFileDownloadable(siteId, fileUrl, timemodified); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if the resource is a Nextcloud file. | ||||
|      * | ||||
|  | ||||
| @ -1619,6 +1619,7 @@ | ||||
|     "core.h5p.offlineDialogRetryButtonLabel": "Retry now", | ||||
|     "core.h5p.offlineDialogRetryMessage": "Retrying in :num....", | ||||
|     "core.h5p.offlineSuccessfulSubmit": "Successfully submitted results.", | ||||
|     "core.h5p.offlinedisabled": "The site doesn't allow downloading H5P packages.", | ||||
|     "core.h5p.originator": "Originator", | ||||
|     "core.h5p.pd": "Public Domain", | ||||
|     "core.h5p.pddl": "Public Domain Dedication and Licence", | ||||
|  | ||||
| @ -20,6 +20,7 @@ import { CoreFileHelperProvider } from '@providers/file-helper'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype'; | ||||
| import { CoreUrlUtilsProvider } from '@providers/utils/url'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| import { CoreConstants } from '@core/constants'; | ||||
| @ -57,16 +58,17 @@ 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, | ||||
|             private pluginFileDelegate: CorePluginFileDelegate) { | ||||
|     constructor(protected sitesProvider: CoreSitesProvider, | ||||
|             protected utils: CoreUtilsProvider, | ||||
|             protected domUtils: CoreDomUtilsProvider, | ||||
|             protected filepoolProvider: CoreFilepoolProvider, | ||||
|             protected appProvider: CoreAppProvider, | ||||
|             protected fileHelper: CoreFileHelperProvider, | ||||
|             protected mimeUtils: CoreMimetypeUtilsProvider, | ||||
|             protected eventsProvider: CoreEventsProvider, | ||||
|             protected textUtils: CoreTextUtilsProvider, | ||||
|             protected pluginFileDelegate: CorePluginFileDelegate, | ||||
|             protected urlUtils: CoreUrlUtilsProvider) { | ||||
|         this.onDelete = new EventEmitter(); | ||||
|     } | ||||
| 
 | ||||
| @ -104,6 +106,8 @@ export class CoreFileComponent implements OnInit, OnDestroy { | ||||
|                 this.observer = this.eventsProvider.on(eventName, () => { | ||||
|                     this.calculateState(); | ||||
|                 }); | ||||
|             }).catch(() => { | ||||
|                 // File not downloadable.
 | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| @ -152,14 +156,14 @@ export class CoreFileComponent implements OnInit, OnDestroy { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (!this.canDownload) { | ||||
|         if (!this.canDownload || !this.state || this.state == CoreConstants.NOT_DOWNLOADABLE) { | ||||
|             // File cannot be downloaded, just open it.
 | ||||
|             if (this.file.toURL) { | ||||
|                 // Local file.
 | ||||
|                 this.utils.openFile(this.file.toURL()); | ||||
|             } else if (this.fileUrl) { | ||||
|                 if (this.fileUrl.indexOf('http') === 0) { | ||||
|                     this.utils.openOnlineFile(this.fileUrl); | ||||
|                     this.utils.openOnlineFile(this.urlUtils.unfixPluginfileURL(this.fileUrl)); | ||||
|                 } else { | ||||
|                     this.utils.openFile(this.fileUrl); | ||||
|                 } | ||||
|  | ||||
| @ -17,7 +17,7 @@ import { NavController } from 'ionic-angular'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| import { CoreLoggerProvider } from '@providers/logger'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| import { CoreTextUtilsProvider, CoreTextErrorObject } from '@providers/utils/text'; | ||||
| import { CoreCourseHelperProvider } from '@core/course/providers/helper'; | ||||
| import { CoreCourseModuleMainComponent, CoreCourseModuleDelegate } from '@core/course/providers/module-delegate'; | ||||
| import { CoreCourseSectionPage } from '@core/course/pages/section/section.ts'; | ||||
| @ -265,6 +265,20 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, | ||||
|         this.courseHelper.confirmAndRemoveFiles(this.module, this.courseId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Show an error occurred while downloading files. | ||||
|      * | ||||
|      * @param error The specific error. | ||||
|      */ | ||||
|     protected showErrorDownloadingSomeFiles(error: string | CoreTextErrorObject): void { | ||||
|         const errorMessage = this.textUtils.buildSeveralParagraphsMessage([ | ||||
|             this.translate.instant('core.errordownloadingsomefiles'), | ||||
|             error, | ||||
|         ]); | ||||
| 
 | ||||
|         this.domUtils.showErrorModal(errorMessage); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Component being destroyed. | ||||
|      */ | ||||
|  | ||||
| @ -178,8 +178,9 @@ export class CoreCoursesCourseLinkHandler extends CoreContentLinksHandlerBase { | ||||
|                         error = this.translate.instant('core.courses.notenroled'); | ||||
|                     } | ||||
| 
 | ||||
|                     const body = this.translate.instant('core.twoparagraphs', | ||||
|                         { p1: error, p2: this.translate.instant('core.confirmopeninbrowser') }); | ||||
|                     const body = this.textUtils.buildSeveralParagraphsMessage( | ||||
|                             [error, this.translate.instant('core.confirmopeninbrowser')]); | ||||
| 
 | ||||
|                     this.domUtils.showConfirm(body).then(() => { | ||||
|                         this.sitesProvider.getCurrentSite().openInBrowserWithAutoLogin(url); | ||||
|                     }).catch(() => { | ||||
|  | ||||
| @ -73,7 +73,8 @@ export class CoreH5PPlayerComponent implements OnInit, OnChanges, OnDestroy { | ||||
|         this.logger = loggerProvider.getInstance('CoreH5PPlayerComponent'); | ||||
|         this.site = sitesProvider.getCurrentSite(); | ||||
|         this.siteId = this.site.getId(); | ||||
|         this.siteCanDownload = this.sitesProvider.getCurrentSite().canDownloadFiles(); | ||||
|         this.siteCanDownload = this.sitesProvider.getCurrentSite().canDownloadFiles() && | ||||
|                 !this.h5pProvider.isOfflineDisabledInSite(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -64,6 +64,7 @@ | ||||
|     "offlineDialogRetryButtonLabel": "Retry now", | ||||
|     "offlineDialogRetryMessage": "Retrying in :num....", | ||||
|     "offlineSuccessfulSubmit": "Successfully submitted results.", | ||||
|     "offlinedisabled": "The site doesn't allow downloading H5P packages.", | ||||
|     "originator": "Originator", | ||||
|     "pd": "Public Domain", | ||||
|     "pddl": "Public Domain Dedication and Licence", | ||||
|  | ||||
| @ -1876,6 +1876,30 @@ export class CoreH5PProvider { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether H5P offline is disabled. | ||||
|      * | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with boolean: whether is disabled. | ||||
|      */ | ||||
|     async isOfflineDisabled(siteId?: string): Promise<boolean> { | ||||
|         const site = await this.sitesProvider.getSite(siteId); | ||||
| 
 | ||||
|         return this.isOfflineDisabledInSite(site); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether H5P offline is disabled. | ||||
|      * | ||||
|      * @param site Site instance. If not defined, current site. | ||||
|      * @return Whether is disabled. | ||||
|      */ | ||||
|     isOfflineDisabledInSite(site?: CoreSite): boolean { | ||||
|         site = site || this.sitesProvider.getCurrentSite(); | ||||
| 
 | ||||
|         return site.isFeatureDisabled('NoDelegate_H5POffline'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Performs actions required when a library has been installed. | ||||
|      * | ||||
|  | ||||
| @ -22,6 +22,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreH5PProvider } from './h5p'; | ||||
| import { CoreWSExternalFile } from '@providers/ws'; | ||||
| import { FileEntry } from '@ionic-native/file'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| 
 | ||||
| /** | ||||
|  * Handler to treat H5P files. | ||||
| @ -35,7 +36,8 @@ export class CoreH5PPluginFileHandler implements CorePluginFileHandler { | ||||
|             protected textUtils: CoreTextUtilsProvider, | ||||
|             protected utils: CoreUtilsProvider, | ||||
|             protected fileProvider: CoreFileProvider, | ||||
|             protected h5pProvider: CoreH5PProvider) { } | ||||
|             protected h5pProvider: CoreH5PProvider, | ||||
|             protected translate: TranslateService) { } | ||||
| 
 | ||||
|     /** | ||||
|      * React to a file being deleted. | ||||
| @ -112,6 +114,28 @@ export class CoreH5PPluginFileHandler implements CorePluginFileHandler { | ||||
|         return this.h5pProvider.canGetTrustedH5PFileInSite(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if a file is downloadable. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with a boolean and a reason why it isn't downloadable if needed. | ||||
|      */ | ||||
|     async isFileDownloadable(file: CoreWSExternalFile, siteId?: string): Promise<{downloadable: boolean, reason?: string}> { | ||||
|         const offlineDisabled = await this.h5pProvider.isOfflineDisabled(siteId); | ||||
| 
 | ||||
|         if (offlineDisabled) { | ||||
|             return { | ||||
|                 downloadable: false, | ||||
|                 reason: this.translate.instant('core.h5p.offlinedisabled'), | ||||
|             }; | ||||
|         } else { | ||||
|             return { | ||||
|                 downloadable: true, | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether the file should be treated by this handler. It is used in functions where the component isn't used. | ||||
|      * | ||||
|  | ||||
| @ -2385,6 +2385,23 @@ export class CoreFilepoolProvider { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether a file is downloadable. | ||||
|      * | ||||
|      * @param siteId The site ID. | ||||
|      * @param fileUrl File URL. | ||||
|      * @param timemodified The time this file was modified. | ||||
|      * @param filePath Filepath to download the file to. If defined, no extension will be added. | ||||
|      * @param revision File revision. If not defined, it will be calculated using the URL. | ||||
|      * @return Promise resolved with a boolean: whether a file is downloadable. | ||||
|      */ | ||||
|     async isFileDownloadable(siteId: string, fileUrl: string, timemodified: number = 0, filePath?: string, revision?: number) | ||||
|             : Promise<boolean> { | ||||
|         const state = await this.getFileStateByUrl(siteId, fileUrl, timemodified, filePath, revision); | ||||
| 
 | ||||
|         return state != CoreConstants.NOT_DOWNLOADABLE; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if a file is downloading. | ||||
|      * | ||||
|  | ||||
| @ -84,6 +84,15 @@ export interface CorePluginFileHandler extends CoreDelegateHandler { | ||||
|      */ | ||||
|     getFileSize?(file: CoreWSExternalFile, siteId?: string): Promise<number>; | ||||
| 
 | ||||
|     /** | ||||
|      * Check if a file is downloadable. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with a boolean and a reason why it isn't downloadable if needed. | ||||
|      */ | ||||
|     isFileDownloadable?(file: CoreWSExternalFile, siteId?: string): Promise<CorePluginFileDownloadableResult>; | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether the file should be treated by this handler. It is used in functions where the component isn't used. | ||||
|      * | ||||
| @ -103,6 +112,21 @@ export interface CorePluginFileHandler extends CoreDelegateHandler { | ||||
|     treatDownloadedFile?(fileUrl: string, file: FileEntry, siteId?: string): Promise<any>; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Data about if a file is downloadable. | ||||
|  */ | ||||
| export type CorePluginFileDownloadableResult = { | ||||
|     /** | ||||
|      * Whether it's downloadable. | ||||
|      */ | ||||
|     downloadable: boolean; | ||||
| 
 | ||||
|     /** | ||||
|      * If not downloadable, the reason why it isn't. | ||||
|      */ | ||||
|     reason?: string; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Delegate to register pluginfile information handlers. | ||||
|  */ | ||||
| @ -155,16 +179,22 @@ export class CorePluginFileDelegate extends CoreDelegate { | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the file to use. Rejected if cannot download. | ||||
|      */ | ||||
|     protected getHandlerDownloadableFile(file: CoreWSExternalFile, handler: CorePluginFileHandler, siteId?: string) | ||||
|     protected async getHandlerDownloadableFile(file: CoreWSExternalFile, handler: CorePluginFileHandler, siteId?: string) | ||||
|             : Promise<CoreWSExternalFile> { | ||||
| 
 | ||||
|         if (handler && handler.getDownloadableFile) { | ||||
|             return handler.getDownloadableFile(file, siteId).then((newFile) => { | ||||
|                 return newFile || file; | ||||
|             }); | ||||
|         const isDownloadable = await this.isFileDownloadable(file, siteId); | ||||
| 
 | ||||
|         if (!isDownloadable.downloadable) { | ||||
|             throw isDownloadable.reason; | ||||
|         } | ||||
| 
 | ||||
|         return Promise.resolve(file); | ||||
|         if (handler && handler.getDownloadableFile) { | ||||
|             const newFile = await handler.getDownloadableFile(file, siteId); | ||||
| 
 | ||||
|             return newFile || file; | ||||
|         } | ||||
| 
 | ||||
|         return file; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -240,23 +270,32 @@ export class CorePluginFileDelegate extends CoreDelegate { | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved with the size. | ||||
|      */ | ||||
|     getFileSize(file: CoreWSExternalFile, siteId?: string): Promise<number> { | ||||
|     async getFileSize(file: CoreWSExternalFile, siteId?: string): Promise<number> { | ||||
|         const isDownloadable = await this.isFileDownloadable(file, siteId); | ||||
| 
 | ||||
|         if (!isDownloadable.downloadable) { | ||||
|             return 0; | ||||
|         } | ||||
| 
 | ||||
|         const handler = this.getHandlerForFile(file); | ||||
| 
 | ||||
|         // First of all check if file can be downloaded.
 | ||||
|         return this.getHandlerDownloadableFile(file, handler, siteId).then((file) => { | ||||
|             if (!file) { | ||||
|                 return 0; | ||||
|             } | ||||
|         const downloadableFile = await this.getHandlerDownloadableFile(file, handler, siteId); | ||||
|         if (!downloadableFile) { | ||||
|             return 0; | ||||
|         } | ||||
| 
 | ||||
|             if (handler && handler.getFileSize) { | ||||
|                 return handler.getFileSize(file, siteId).catch(() => { | ||||
|                     return file.filesize; | ||||
|                 }); | ||||
|             } | ||||
|         if (handler && handler.getFileSize) { | ||||
|             try { | ||||
|                 const size = handler.getFileSize(downloadableFile, siteId); | ||||
| 
 | ||||
|             return Promise.resolve(file.filesize); | ||||
|         }); | ||||
|                 return size; | ||||
|             } catch (error) { | ||||
|                 // Ignore errors.
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return downloadableFile.filesize; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -275,6 +314,24 @@ export class CorePluginFileDelegate extends CoreDelegate { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if a file is downloadable. | ||||
|      * | ||||
|      * @param file The file data. | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise with the data. | ||||
|      */ | ||||
|     isFileDownloadable(file: CoreWSExternalFile, siteId?: string): Promise<CorePluginFileDownloadableResult> { | ||||
|         const handler = this.getHandlerForFile(file); | ||||
| 
 | ||||
|         if (handler && handler.isFileDownloadable) { | ||||
|             return handler.isFileDownloadable(file, siteId); | ||||
|         } | ||||
| 
 | ||||
|         // Default to true.
 | ||||
|         return Promise.resolve({downloadable: true}); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Removes the revision number from a file URL. | ||||
|      * | ||||
|  | ||||
| @ -18,6 +18,16 @@ import { ModalController, Platform } from 'ionic-angular'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| import { CoreLangProvider } from '../lang'; | ||||
| 
 | ||||
| /** | ||||
|  * Different type of errors the app can treat. | ||||
|  */ | ||||
| export type CoreTextErrorObject = { | ||||
|     message?: string; | ||||
|     error?: string; | ||||
|     content?: string; | ||||
|     body?: string; | ||||
| }; | ||||
| 
 | ||||
| /* | ||||
|  * "Utils" service with helper functions for text. | ||||
| */ | ||||
| @ -122,6 +132,38 @@ export class CoreTextUtilsProvider { | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Build a message with several paragraphs. | ||||
|      * | ||||
|      * @param paragraphs List of paragraphs. | ||||
|      * @return Built message. | ||||
|      */ | ||||
|     buildSeveralParagraphsMessage(paragraphs: (string | CoreTextErrorObject)[]): string { | ||||
|         // Filter invalid messages, and convert them to messages in case they're errors.
 | ||||
|         const messages: string[] = []; | ||||
| 
 | ||||
|         paragraphs.forEach((paragraph) => { | ||||
|             // If it's an error, get its message.
 | ||||
|             const message = this.getErrorMessageFromError(paragraph); | ||||
| 
 | ||||
|             if (paragraph) { | ||||
|                 messages.push(message); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         if (messages.length < 2) { | ||||
|             return messages[0] || ''; | ||||
|         } | ||||
| 
 | ||||
|         let builtMessage = messages[0]; | ||||
| 
 | ||||
|         for (let i = 1; i < messages.length; i++) { | ||||
|             builtMessage = this.translate.instant('core.twoparagraphs', { p1: builtMessage, p2: messages[i] }); | ||||
|         } | ||||
| 
 | ||||
|         return builtMessage; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Convert size in bytes into human readable format | ||||
|      * | ||||
| @ -449,7 +491,7 @@ export class CoreTextUtilsProvider { | ||||
|      * @param error Error object. | ||||
|      * @return Error message, undefined if not found. | ||||
|      */ | ||||
|     getErrorMessageFromError(error: any): string { | ||||
|     getErrorMessageFromError(error: string | CoreTextErrorObject): string { | ||||
|         if (typeof error == 'string') { | ||||
|             return error; | ||||
|         } | ||||
|  | ||||
| @ -469,4 +469,32 @@ export class CoreUrlUtilsProvider { | ||||
| 
 | ||||
|         return matches && matches[0]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Modifies a pluginfile URL to use the default pluginfile script instead of the webservice one. | ||||
|      * | ||||
|      * @param url The url to be fixed. | ||||
|      * @param siteUrl The URL of the site the URL belongs to. | ||||
|      * @return Modified URL. | ||||
|      */ | ||||
|     unfixPluginfileURL(url: string, siteUrl?: string): string { | ||||
|         if (!url) { | ||||
|             return ''; | ||||
|         } | ||||
| 
 | ||||
|         url = url.replace(/&/g, '&'); | ||||
| 
 | ||||
|         // It site URL is supplied, check if the URL belongs to the site.
 | ||||
|         if (siteUrl && url.indexOf(this.textUtils.addEndingSlash(siteUrl)) !== 0) { | ||||
|             return url; | ||||
|         } | ||||
| 
 | ||||
|         // Not a pluginfile URL. Treat webservice/pluginfile case.
 | ||||
|         url = url.replace(/\/webservice\/pluginfile\.php\//, '/pluginfile.php/'); | ||||
| 
 | ||||
|         // Make sure the URL doesn't contain the token.
 | ||||
|         url.replace(/([?&])token=[^&]*&?/, '$1'); | ||||
| 
 | ||||
|         return url; | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user