From 3b8b44c23ac916ddea51b92361e00025ec97981d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Mon, 5 Mar 2018 15:19:39 +0100 Subject: [PATCH] MOBILE-2349 resource: Add link and plugin file handlers --- src/addon/mod/book/providers/book.ts | 18 +- .../resource/components/components.module.ts | 2 +- .../mod/resource/components/index/index.ts | 7 +- .../mod/resource/pages/index/index.module.ts | 2 +- src/addon/mod/resource/providers/helper.ts | 215 ++---------------- .../mod/resource/providers/link-handler.ts | 29 +++ .../mod/resource/providers/module-handler.ts | 56 ++++- .../resource/providers/pluginfile-handler.ts | 49 ++++ src/addon/mod/resource/providers/resource.ts | 21 +- src/addon/mod/resource/resource.module.ts | 14 +- src/core/course/components/module/module.ts | 3 + src/core/course/providers/helper.ts | 3 +- 12 files changed, 167 insertions(+), 252 deletions(-) create mode 100644 src/addon/mod/resource/providers/link-handler.ts create mode 100644 src/addon/mod/resource/providers/pluginfile-handler.ts diff --git a/src/addon/mod/book/providers/book.ts b/src/addon/mod/book/providers/book.ts index 808a77128..0078341d6 100644 --- a/src/addon/mod/book/providers/book.ts +++ b/src/addon/mod/book/providers/book.ts @@ -381,19 +381,11 @@ export class AddonModBookProvider { * @return {Promise} Promise resolved when the WS call is successful. */ logView(id: number, chapterId: string): Promise { - if (id) { - const params = { - bookid: id, - chapterid: chapterId - }; + const params = { + bookid: id, + chapterid: chapterId + }; - return this.sitesProvider.getCurrentSite().write('mod_book_view_book', params).then((response) => { - if (!response.status) { - return Promise.reject(null); - } - }); - } - - return Promise.reject(null); + return this.sitesProvider.getCurrentSite().write('mod_book_view_book', params); } } diff --git a/src/addon/mod/resource/components/components.module.ts b/src/addon/mod/resource/components/components.module.ts index 8e791eaec..1f2cdda66 100644 --- a/src/addon/mod/resource/components/components.module.ts +++ b/src/addon/mod/resource/components/components.module.ts @@ -17,7 +17,7 @@ import { CommonModule } from '@angular/common'; import { IonicModule } from 'ionic-angular'; import { TranslateModule } from '@ngx-translate/core'; import { CoreComponentsModule } from '@components/components.module'; -import { CoreDirectivesModule } from '@directives'; +import { CoreDirectivesModule } from '@directives/directives.module'; import { CoreCourseComponentsModule } from '@core/course/components/components.module'; import { AddonModResourceIndexComponent } from './index/index'; diff --git a/src/addon/mod/resource/components/index/index.ts b/src/addon/mod/resource/components/index/index.ts index 4278194f5..353ede9f9 100644 --- a/src/addon/mod/resource/components/index/index.ts +++ b/src/addon/mod/resource/components/index/index.ts @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy, Input, Output, EventEmitter, Optional } from '@angular/core'; -import { NavParams, NavController, Content } from 'ionic-angular'; +import { Component, OnInit, OnDestroy, Input, Output, EventEmitter } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '@providers/app'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; @@ -60,8 +59,7 @@ export class AddonModResourceIndexComponent implements OnInit, OnDestroy, CoreCo constructor(private resourceProvider: AddonModResourceProvider, private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider, private appProvider: CoreAppProvider, private textUtils: CoreTextUtilsProvider, private courseHelper: CoreCourseHelperProvider, private translate: TranslateService, - @Optional() private content: Content, private prefetchHandler: AddonModResourcePrefetchHandler, - private resourceHelper: AddonModResourceHelperProvider) { + private prefetchHandler: AddonModResourcePrefetchHandler, private resourceHelper: AddonModResourceHelperProvider) { this.resourceRetrieved = new EventEmitter(); } @@ -166,7 +164,6 @@ export class AddonModResourceIndexComponent implements OnInit, OnDestroy, CoreCo downloadFailed = true; }).then(() => { return this.resourceHelper.getIframeSrc(this.module).then((src) => { - console.error(src); this.mode = 'iframe'; if (this.src && src.toString() == this.src.toString()) { diff --git a/src/addon/mod/resource/pages/index/index.module.ts b/src/addon/mod/resource/pages/index/index.module.ts index 2e40a2c1e..6d6dc347d 100644 --- a/src/addon/mod/resource/pages/index/index.module.ts +++ b/src/addon/mod/resource/pages/index/index.module.ts @@ -15,7 +15,7 @@ import { NgModule } from '@angular/core'; import { IonicPageModule } from 'ionic-angular'; import { TranslateModule } from '@ngx-translate/core'; -import { CoreDirectivesModule } from '@directives'; +import { CoreDirectivesModule } from '@directives/directives.module'; import { AddonModResourceComponentsModule } from '../../components/components.module'; import { AddonModResourceIndexPage } from './index'; diff --git a/src/addon/mod/resource/providers/helper.ts b/src/addon/mod/resource/providers/helper.ts index 7ffb1377d..a9077b3d5 100644 --- a/src/addon/mod/resource/providers/helper.ts +++ b/src/addon/mod/resource/providers/helper.ts @@ -15,6 +15,7 @@ import { Injectable } from '@angular/core'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCourseHelperProvider } from '@core/course/providers/helper'; import { AddonModResourceProvider } from './resource'; import { TranslateService } from '@ngx-translate/core'; import { CoreSitesProvider } from '@providers/sites'; @@ -37,19 +38,9 @@ export class AddonModResourceHelperProvider { protected DISPLAY_AUTO = 0; // Display using object tag. protected DISPLAY_EMBED = 1; - // Display inside frame. - protected DISPLAY_FRAME = 2; - // Display normal link in new window. - protected DISPLAY_NEW = 3; - // Force download of file instead of display. - protected DISPLAY_DOWNLOAD = 4; - // Open directly. - protected DISPLAY_OPEN = 5; - // Open in "emulated" pop-up without navigation. - protected DISPLAY_POPUP = 6; constructor(private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider, - private resourceProvider: AddonModResourceProvider, + private resourceProvider: AddonModResourceProvider, private courseHelper: CoreCourseHelperProvider, private textUtils: CoreTextUtilsProvider, private mimetypeUtils: CoreMimetypeUtilsProvider, private fileProvider: CoreFileProvider, private appProvider: CoreAppProvider, private filepoolProvider: CoreFilepoolProvider, private utils: CoreUtilsProvider, @@ -61,17 +52,12 @@ export class AddonModResourceHelperProvider { * * @param {any} module The module object. * @return {Promise} Promise resolved with the iframe src. - * @since 3.3 */ getEmbeddedHtml(module: any): Promise { - if (!module.contents || !module.contents.length) { - return Promise.reject(null); - } - - const file = module.contents[0]; - - return this.treatResourceMainFile(file, module.id).then((result) => { - const ext = this.mimetypeUtils.getFileExtension(file.filename), + return this.courseHelper.downloadModuleWithMainFileIfNeeded(module, module.course, AddonModResourceProvider.COMPONENT, + module.id, module.contents).then((result) => { + const file = module.contents[0], + ext = this.mimetypeUtils.getFileExtension(file.filename), type = this.mimetypeUtils.getExtensionType(ext), mimeType = this.mimetypeUtils.getMimeType(ext); @@ -85,7 +71,7 @@ export class AddonModResourceHelperProvider { ''; } - // Shouldn't reach here, the user should have called $mmFS#canBeEmbedded. + // Shouldn't reach here, the user should have called CoreMimetypeUtilsProvider#canBeEmbedded. return ''; }); } @@ -94,9 +80,9 @@ export class AddonModResourceHelperProvider { * Download all the files needed and returns the src of the iframe. * * @param {any} module The module object. - * @return {Promise} Promise resolved with the iframe src. + * @return {Promise} Promise resolved with the iframe src. */ - getIframeSrc(module: any): Promise { + getIframeSrc(module: any): Promise { if (!module.contents.length) { return Promise.reject(null); } @@ -127,8 +113,7 @@ export class AddonModResourceHelperProvider { * * @param {any} module The module object. * @param {number} [display] The display mode (if available). - * @return {boolean} Whether the resource should be displayed in an iframe. - * @since 3.3 + * @return {boolean} Whether the resource should be displayed embeded. */ isDisplayedEmbedded(module: any, display: number): boolean { if (!module.contents.length || !this.fileProvider.isAvailable()) { @@ -167,7 +152,9 @@ export class AddonModResourceHelperProvider { openModuleFile(module: any, courseId: number): Promise { const modal = this.domUtils.showModalLoading(); - return this.openFile(module.contents, module.id).then(() => { + // Download and open the file from the resource contents. + return this.courseHelper.downloadModuleAndOpenFile(module, courseId, AddonModResourceProvider.COMPONENT, module.id, + module.contents).then(() => { this.resourceProvider.logView(module.instance).then(() => { this.courseProvider.checkModuleCompletion(courseId, module.completionstatus); }); @@ -177,180 +164,4 @@ export class AddonModResourceHelperProvider { modal.dismiss(); }); } - - /** - * Download and open the file from the resource. - * - * @param {any} contents Array of content objects. - * @param {number} moduleId The module ID. - * @return {Promise} - */ - protected openFile(contents: any, moduleId: number): Promise { - if (!contents || !contents.length) { - return Promise.reject(null); - } - - const siteId = this.sitesProvider.getCurrentSiteId(), - file = contents[0], - files = [file], - component = AddonModResourceProvider.COMPONENT; - - if (this.shouldOpenInBrowser(contents[0])) { - if (this.appProvider.isOnline()) { - // Open in browser. - let fixedUrl = this.sitesProvider.getCurrentSite().fixPluginfileURL(file.fileurl).replace('&offline=1', ''); - fixedUrl = fixedUrl.replace(/forcedownload=\d+&/, ''); // Remove forcedownload when followed by another param. - fixedUrl = fixedUrl.replace(/[\?|\&]forcedownload=\d+/, ''); // Remove forcedownload when not followed by any param. - this.utils.openInBrowser(fixedUrl); - - if (this.fileProvider.isAvailable()) { - // Download the file if needed (file outdated or not downloaded). - // Download will be in background, don't return the promise. - this.filepoolProvider.downloadPackage(siteId, files, component, moduleId); - } - - return Promise.resolve(); - } - - // Not online, get the offline file. It will fail if not found. - return this.filepoolProvider.getInternalUrlByUrl(siteId, file.fileurl).then((path) => { - return this.utils.openFile(path); - }).catch(() => { - return Promise.reject(this.translate.instant('core.networkerrormsg')); - }); - } - - return this.treatResourceMainFile(file, moduleId).then((result) => { - if (result.path.indexOf('http') === 0) { - return this.utils.openOnlineFile(result.path).catch((error) => { - // Error opening the file, some apps don't allow opening online files. - if (!this.fileProvider.isAvailable()) { - return Promise.reject(error); - } - - let subPromise; - if (result.status === CoreConstants.DOWNLOADING) { - subPromise = Promise.reject(this.translate.instant('core.erroropenfiledownloading')); - } else if (result.status === CoreConstants.NOT_DOWNLOADED) { - subPromise = this.filepoolProvider.downloadPackage(siteId, files, AddonModResourceProvider.COMPONENT, - moduleId).then(() => { - return this.filepoolProvider.getInternalUrlByUrl(siteId, file.fileurl); - }); - } else { - // File is outdated or stale and can't be opened in online, return the local URL. - subPromise = this.filepoolProvider.getInternalUrlByUrl(siteId, file.fileurl); - } - - return subPromise.then((path) => { - return this.utils.openFile(path); - }); - }); - } - - return this.utils.openFile(result.path); - }); - } - - /** - * Treat the main file of a resource, downloading it if needed and returning the URL to use and the status of the resource. - * - * @param {any} file Resource's main file. - * @param {number} moduleId The module ID. - * @return {Promise} Promise resolved with an object containing: - * * path: The URL to use; can be an online URL or an offline path. - * * status: The status of the resource. - */ - protected treatResourceMainFile(file: any, moduleId: number): Promise { - const files = [file], - url = file.fileurl, - fixedUrl = this.sitesProvider.getCurrentSite().fixPluginfileURL(url), - result = { - status: '', - path: fixedUrl - }; - - if (!this.fileProvider.isAvailable()) { - // We use the live URL. - return Promise.resolve(result); - } - - const siteId = this.sitesProvider.getCurrentSiteId(), - component = AddonModResourceProvider.COMPONENT; - - // The file system is available. - return this.filepoolProvider.getPackageStatus(siteId, component, moduleId).then((status) => { - result.status = status; - - const isWifi = !this.appProvider.isNetworkAccessLimited(), - isOnline = this.appProvider.isOnline(); - - if (status === CoreConstants.DOWNLOADED) { - // Get the local file URL. - return this.filepoolProvider.getInternalUrlByUrl(siteId, url); - } - - if (status === CoreConstants.DOWNLOADING && !this.appProvider.isDesktop()) { - // Return the online URL. - return fixedUrl; - } - - if (!isOnline && status === CoreConstants.NOT_DOWNLOADED) { - // Not downloaded and we're offline, reject. - return Promise.reject(null); - } - - return this.filepoolProvider.shouldDownloadBeforeOpen(fixedUrl, file.filesize).then(() => { - // Download and then return the local URL. - return this.filepoolProvider.downloadPackage(siteId, files, component, moduleId).then(() => { - return this.filepoolProvider.getInternalUrlByUrl(siteId, url); - }); - }).catch(() => { - // Start the download if in wifi, but return the URL right away so the file is opened. - if (isWifi && isOnline) { - this.filepoolProvider.downloadPackage(siteId, files, component, moduleId); - } - - if (status === CoreConstants.NOT_DOWNLOADED || isOnline) { - // Not downloaded or outdated and online, return the online URL. - return fixedUrl; - } - - const timeMod = this.filepoolProvider.getTimemodifiedFromFileList(files); - - // Outdated but offline, so we return the local URL. - return this.filepoolProvider.getUrlByUrl(siteId, url, component, moduleId, timeMod, false, false, file); - }); - }).then((path) => { - result.path = path; - - return result; - }); - } - - /** - * Whether the resource has to be opened in browser. - * - * @param {any} file Module's main file. - * @return {boolean} Whether the resource should be opened in browser. - * @since 3.3 - */ - shouldOpenInBrowser(file: any): boolean { - if (!file || !file.isexternalfile || !file.mimetype) { - return false; - } - - const mimetype = file.mimetype; - if (mimetype.indexOf('application/vnd.google-apps.') != -1) { - // Google Docs file, always open in browser. - return true; - } - - if (file.repositorytype == 'onedrive') { - // In OneDrive, open in browser the office docs - return mimetype.indexOf('application/vnd.openxmlformats-officedocument') != -1 || - mimetype == 'text/plain' || mimetype == 'document/unknown'; - } - - return false; - } } diff --git a/src/addon/mod/resource/providers/link-handler.ts b/src/addon/mod/resource/providers/link-handler.ts new file mode 100644 index 000000000..267174f97 --- /dev/null +++ b/src/addon/mod/resource/providers/link-handler.ts @@ -0,0 +1,29 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { CoreContentLinksModuleIndexHandler } from '@core/contentlinks/classes/module-index-handler'; +import { CoreCourseHelperProvider } from '@core/course/providers/helper'; + +/** + * Handler to treat links to resource. + */ +@Injectable() +export class AddonModResourceLinkHandler extends CoreContentLinksModuleIndexHandler { + name = 'AddonModResourceLinkHandler'; + + constructor(courseHelper: CoreCourseHelperProvider) { + super(courseHelper, AddonModResourceLinkHandler.name, 'resource'); + } +} diff --git a/src/addon/mod/resource/providers/module-handler.ts b/src/addon/mod/resource/providers/module-handler.ts index 358e25fea..f952695a0 100644 --- a/src/addon/mod/resource/providers/module-handler.ts +++ b/src/addon/mod/resource/providers/module-handler.ts @@ -15,6 +15,7 @@ import { Injectable } from '@angular/core'; import { NavController, NavOptions } from 'ionic-angular'; import { AddonModResourceProvider } from './resource'; +import { AddonModResourceHelperProvider } from './helper'; import { AddonModResourceIndexComponent } from '../components/index/index'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate'; import { CoreCourseProvider } from '@core/course/providers/course'; @@ -28,7 +29,7 @@ export class AddonModResourceModuleHandler implements CoreCourseModuleHandler { name = 'resource'; constructor(protected resourceProvider: AddonModResourceProvider, private courseProvider: CoreCourseProvider, - protected mimetypeUtils: CoreMimetypeUtilsProvider) { } + protected mimetypeUtils: CoreMimetypeUtilsProvider, private resourceHelper: AddonModResourceHelperProvider) { } /** * Check if the handler is enabled on a site level. @@ -48,28 +49,61 @@ export class AddonModResourceModuleHandler implements CoreCourseModuleHandler { * @return {CoreCourseModuleHandlerData} Data to render the module. */ getData(module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData { - this.getIcon(module, courseId); - - return { + const handlerData = { icon: this.courseProvider.getModuleIconSrc('resource'), title: module.name, class: 'addon-mod_resource-handler', showDownloadButton: true, action(event: Event, navCtrl: NavController, module: any, courseId: number, options: NavOptions): void { navCtrl.push('AddonModResourceIndexPage', {module: module, courseId: courseId}, options); - } + }, + buttons: [ { + hidden: !this.resourceHelper.isDisplayedInIframe(module), + icon: 'document', + label: 'addon.mod_resource.openthefile', + action: (event: Event, navCtrl: NavController, module: any, courseId: number): void => { + this.hideOpenButton(module, courseId).then((hide) => { + if (!hide) { + this.resourceHelper.openModuleFile(module, courseId); + } + }); + } + } ] }; + + this.getIcon(module, courseId).then((icon) => { + handlerData.icon = icon; + }); + + this.hideOpenButton(module, courseId).then((hideOpenButton) => { + handlerData.buttons[0].hidden = hideOpenButton; + }); + + return handlerData; + } + + /** + * Returns if contents are loaded to show open button. + * + * @param {any} module The module object. + * @param {number} courseId The course ID. + * @return {Promise} Resolved when done. + */ + protected hideOpenButton(module: any, courseId: number): Promise { + return this.courseProvider.loadModuleContents(module, courseId).then(() => { + return this.resourceHelper.isDisplayedInIframe(module); + }); } /** * Returns the activity icon. * - * @param {any} module The module object. - * @param {number} courseId The course ID. - * @return {string} Icon URL. + * @param {any} module The module object. + * @param {number} courseId The course ID. + * @return {Promise} Icon URL. */ - protected getIcon(module: any, courseId: number): string { - this.courseProvider.loadModuleContents(module, courseId).then(() => { + protected getIcon(module: any, courseId: number): Promise { + return this.courseProvider.loadModuleContents(module, courseId).then(() => { if (module.contents.length) { const filename = module.contents[0].filename, extension = this.mimetypeUtils.getFileExtension(filename); @@ -80,8 +114,6 @@ export class AddonModResourceModuleHandler implements CoreCourseModuleHandler { return this.courseProvider.getModuleIconSrc('resource'); }); - - return this.courseProvider.getModuleIconSrc('resource'); } /** diff --git a/src/addon/mod/resource/providers/pluginfile-handler.ts b/src/addon/mod/resource/providers/pluginfile-handler.ts new file mode 100644 index 000000000..daa3da78b --- /dev/null +++ b/src/addon/mod/resource/providers/pluginfile-handler.ts @@ -0,0 +1,49 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { CorePluginFileHandler } from '@providers/plugin-file-delegate'; + +/** + * Handler to treat links to resource. + */ +@Injectable() +export class AddonModResourcePluginFileHandler implements CorePluginFileHandler { + name = 'AddonModResourcePluginFileHandler'; + + /** + * Return the RegExp to match the revision on pluginfile URLs. + * + * @param {string[]} args Arguments of the pluginfile URL defining component and filearea at least. + * @return {RegExp} RegExp to match the revision on pluginfile URLs. + */ + getComponentRevisionRegExp(args: string[]): RegExp { + // Check filearea. + if (args[2] == 'content') { + // Component + Filearea + Revision + return new RegExp('/mod_resource/content/([0-9]+)/'); + } + } + + /** + * Should return the string to remove the revision on pluginfile url. + * + * @param {string[]} args Arguments of the pluginfile URL defining component and filearea at least. + * @return {string} String to remove the revision on pluginfile url. + */ + getComponentRevisionReplace(args: string[]): string { + // Component + Filearea + Revision + return '/mod_resource/content/0/'; + } +} diff --git a/src/addon/mod/resource/providers/resource.ts b/src/addon/mod/resource/providers/resource.ts index 485ad3572..99559bb42 100644 --- a/src/addon/mod/resource/providers/resource.ts +++ b/src/addon/mod/resource/providers/resource.ts @@ -41,7 +41,7 @@ export class AddonModResourceProvider { * @return {string} Cache key. */ protected getResourceCacheKey(courseId: number): string { - return this.ROOT_CACHE_KEY + ':resource:' + courseId; + return this.ROOT_CACHE_KEY + 'resource:' + courseId; } /** @@ -64,11 +64,8 @@ export class AddonModResourceProvider { return site.read('mod_resource_get_resources_by_courses', params, preSets).then((response) => { if (response && response.resources) { - let currentResource; - response.resources.forEach((resource) => { - if (!currentResource && resource[key] == value) { - currentResource = resource; - } + const currentResource = response.resources.find((resource) => { + return resource[key] == value; }); if (currentResource) { return currentResource; @@ -154,14 +151,10 @@ export class AddonModResourceProvider { * @return {Promise} Promise resolved when the WS call is successful. */ logView(id: number): Promise { - if (id) { - const params = { - resourceid: id - }; + const params = { + resourceid: id + }; - return this.sitesProvider.getCurrentSite().write('mod_resource_view_resource', params); - } - - return Promise.reject(null); + return this.sitesProvider.getCurrentSite().write('mod_resource_view_resource', params); } } diff --git a/src/addon/mod/resource/resource.module.ts b/src/addon/mod/resource/resource.module.ts index e95a37aa8..5b738513e 100644 --- a/src/addon/mod/resource/resource.module.ts +++ b/src/addon/mod/resource/resource.module.ts @@ -17,9 +17,13 @@ import { AddonModResourceComponentsModule } from './components/components.module import { AddonModResourceModuleHandler } from './providers/module-handler'; import { AddonModResourceProvider } from './providers/resource'; import { AddonModResourcePrefetchHandler } from './providers/prefetch-handler'; +import { AddonModResourceLinkHandler } from './providers/link-handler'; +import { AddonModResourcePluginFileHandler } from './providers/pluginfile-handler'; import { AddonModResourceHelperProvider } from './providers/helper'; +import { CoreContentLinksDelegate } from '@core/contentlinks/providers/delegate'; import { CoreCourseModuleDelegate } from '@core/course/providers/module-delegate'; import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; +import { CorePluginFileDelegate } from '@providers/plugin-file-delegate'; @NgModule({ declarations: [ @@ -31,13 +35,19 @@ import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module- AddonModResourceProvider, AddonModResourceModuleHandler, AddonModResourceHelperProvider, - AddonModResourcePrefetchHandler + AddonModResourcePrefetchHandler, + AddonModResourceLinkHandler, + AddonModResourcePluginFileHandler ] }) export class AddonModResourceModule { constructor(moduleDelegate: CoreCourseModuleDelegate, moduleHandler: AddonModResourceModuleHandler, - prefetchDelegate: CoreCourseModulePrefetchDelegate, prefetchHandler: AddonModResourcePrefetchHandler) { + prefetchDelegate: CoreCourseModulePrefetchDelegate, prefetchHandler: AddonModResourcePrefetchHandler, + contentLinksDelegate: CoreContentLinksDelegate, linkHandler: AddonModResourceLinkHandler, + pluginfileDelegate: CorePluginFileDelegate, pluginfileHandler: AddonModResourcePluginFileHandler) { moduleDelegate.registerHandler(moduleHandler); prefetchDelegate.registerHandler(prefetchHandler); + contentLinksDelegate.registerHandler(linkHandler); + pluginfileDelegate.registerHandler(pluginfileHandler); } } diff --git a/src/core/course/components/module/module.ts b/src/core/course/components/module/module.ts index fef73a640..aaee9cb5c 100644 --- a/src/core/course/components/module/module.ts +++ b/src/core/course/components/module/module.ts @@ -102,6 +102,9 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { */ buttonClicked(event: Event, button: CoreCourseModuleHandlerButton): void { if (button && button.action) { + event.preventDefault(); + event.stopPropagation(); + button.action(event, this.navCtrl, this.module, this.courseId); } } diff --git a/src/core/course/providers/helper.ts b/src/core/course/providers/helper.ts index 236b227dd..9457b4ff3 100644 --- a/src/core/course/providers/helper.ts +++ b/src/core/course/providers/helper.ts @@ -585,7 +585,7 @@ export class CoreCourseHelperProvider { * @param {string} [siteId] The site ID. If not defined, current site. * @return {Promise<{fixedUrl: string, path: string, status: string}>} Promise resolved when done. */ - protected downloadModuleWithMainFileIfNeeded(module: any, courseId: number, component?: string, componentId?: string | number, + downloadModuleWithMainFileIfNeeded(module: any, courseId: number, component?: string, componentId?: string | number, files?: any[], siteId?: string): Promise<{fixedUrl: string, path: string, status: string}> { siteId = siteId || this.sitesProvider.getCurrentSiteId(); @@ -598,7 +598,6 @@ export class CoreCourseHelperProvider { const mainFile = files[0], fileUrl = this.fileHelper.getFileUrl(mainFile), timemodified = this.fileHelper.getFileTimemodified(mainFile), - prefetchHandler = this.prefetchDelegate.getPrefetchHandlerFor(module), result = { fixedUrl: undefined, path: undefined,