MOBILE-2335 book: Implement provider and handlers
parent
602d375a53
commit
f8d71dd6ee
|
@ -0,0 +1,39 @@
|
|||
// (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 { NgModule } from '@angular/core';
|
||||
import { AddonModBookProvider } from './providers/book';
|
||||
import { AddonModBookModuleHandler } from './providers/module-handler';
|
||||
import { AddonModBookLinkHandler } from './providers/link-handler';
|
||||
import { CoreCourseModuleDelegate } from '../../../core/course/providers/module-delegate';
|
||||
import { CoreContentLinksDelegate } from '../../../core/contentlinks/providers/delegate';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
AddonModBookProvider,
|
||||
AddonModBookModuleHandler,
|
||||
AddonModBookLinkHandler
|
||||
]
|
||||
})
|
||||
export class AddonModBookModule {
|
||||
constructor(moduleDelegate: CoreCourseModuleDelegate, moduleHandler: AddonModBookModuleHandler,
|
||||
contentLinksDelegate: CoreContentLinksDelegate, linkHandler: AddonModBookLinkHandler) {
|
||||
moduleDelegate.registerHandler(moduleHandler);
|
||||
contentLinksDelegate.registerHandler(linkHandler);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"errorchapter": "Error reading chapter of book."
|
||||
}
|
|
@ -0,0 +1,399 @@
|
|||
// (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 { Http, Response } from '@angular/http';
|
||||
import { CoreFileProvider } from '../../../../providers/file';
|
||||
import { CoreFilepoolProvider } from '../../../../providers/filepool';
|
||||
import { CoreLoggerProvider } from '../../../../providers/logger';
|
||||
import { CoreSitesProvider } from '../../../../providers/sites';
|
||||
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
|
||||
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
|
||||
import { CoreUtilsProvider } from '../../../../providers/utils/utils';
|
||||
import { CoreCourseProvider } from '../../../../core/course/providers/course';
|
||||
|
||||
/**
|
||||
* A book chapter inside the toc list.
|
||||
*/
|
||||
export interface AddonModBookTocChapter {
|
||||
/**
|
||||
* ID to identify the chapter.
|
||||
* @type {string}
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Chapter's title.
|
||||
* @type {string}
|
||||
*/
|
||||
title: string;
|
||||
|
||||
/**
|
||||
* The chapter's level.
|
||||
* @type {number}
|
||||
*/
|
||||
level: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of book contents. For each chapter it has its index URL and the list of paths of the files the chapter has. Each path
|
||||
* is identified by the relative path in the book, and the value is the URL of the file.
|
||||
*/
|
||||
export type AddonModBookContentsMap = {[chapter: string]: {indexUrl?: string, paths: {[path: string]: string}}};
|
||||
|
||||
/**
|
||||
* Service that provides some features for books.
|
||||
*/
|
||||
@Injectable()
|
||||
export class AddonModBookProvider {
|
||||
static COMPONENT = 'mmaModBook';
|
||||
|
||||
protected ROOT_CACHE_KEY = 'mmaModBook:';
|
||||
protected logger;
|
||||
|
||||
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private textUtils: CoreTextUtilsProvider,
|
||||
private fileProvider: CoreFileProvider, private filepoolProvider: CoreFilepoolProvider, private http: Http,
|
||||
private utils: CoreUtilsProvider, private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider) {
|
||||
this.logger = logger.getInstance('AddonModBookProvider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a book by course module ID.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @param {number} cmId Course module ID.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Promise resolved when the book is retrieved.
|
||||
*/
|
||||
getBook(courseId: number, cmId: number, siteId?: string): Promise<any> {
|
||||
return this.getBookByField(courseId, 'coursemodule', cmId, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a book with key=value. If more than one is found, only the first will be returned.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @param {string} key Name of the property to check.
|
||||
* @param {any} value Value to search.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Promise resolved when the book is retrieved.
|
||||
*/
|
||||
protected getBookByField(courseId: number, key: string, value: any, siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const params = {
|
||||
courseids: [courseId]
|
||||
},
|
||||
preSets = {
|
||||
cacheKey: this.getBookDataCacheKey(courseId)
|
||||
};
|
||||
|
||||
return site.read('mod_book_get_books_by_courses', params, preSets).then((response) => {
|
||||
// Search the book.
|
||||
if (response && response.books) {
|
||||
for (const i in response.books) {
|
||||
const book = response.books[i];
|
||||
if (book[key] == value) {
|
||||
return book;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for get book data WS calls.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @return {string} Cache key.
|
||||
*/
|
||||
protected getBookDataCacheKey(courseId: number): string {
|
||||
return this.ROOT_CACHE_KEY + 'book:' + courseId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a chapter contents.
|
||||
*
|
||||
* @param {AddonModBookContentsMap} contentsMap Contents map returned by getContentsMap.
|
||||
* @param {string} chapterId Chapter to retrieve.
|
||||
* @param {number} moduleId The module ID.
|
||||
* @return {Promise<string>} Promise resolved with the contents.
|
||||
*/
|
||||
getChapterContent(contentsMap: AddonModBookContentsMap, chapterId: string, moduleId: number): Promise<string> {
|
||||
const indexUrl = contentsMap[chapterId] ? contentsMap[chapterId].indexUrl : undefined,
|
||||
siteId = this.sitesProvider.getCurrentSiteId();
|
||||
let promise;
|
||||
|
||||
if (!indexUrl) {
|
||||
// It shouldn't happen.
|
||||
this.logger.debug('Could not locate the index chapter');
|
||||
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
||||
if (this.fileProvider.isAvailable()) {
|
||||
promise = this.filepoolProvider.downloadUrl(siteId, indexUrl, false, AddonModBookProvider.COMPONENT, moduleId);
|
||||
} else {
|
||||
// We return the live URL.
|
||||
return Promise.resolve(this.sitesProvider.getCurrentSite().fixPluginfileURL(indexUrl));
|
||||
}
|
||||
|
||||
return promise.then((url) => {
|
||||
// Fetch the URL content.
|
||||
const observable = this.http.get(url);
|
||||
|
||||
return this.utils.observableToPromise(observable).then((response: Response): any => {
|
||||
const content = response.text();
|
||||
if (typeof content !== 'string') {
|
||||
return Promise.reject(null);
|
||||
} else {
|
||||
// Now that we have the content, we update the SRC to point back to the external resource.
|
||||
return this.domUtils.restoreSourcesInHtml(content, contentsMap[chapterId].paths);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array of book contents into an object where contents are organized in chapters.
|
||||
* Each chapter has an indexUrl and the list of contents in that chapter.
|
||||
*
|
||||
* @param {any[]} contents The module contents.
|
||||
* @return {AddonModBookContentsMap} Contents map.
|
||||
*/
|
||||
getContentsMap(contents: any[]): AddonModBookContentsMap {
|
||||
const map: AddonModBookContentsMap = {};
|
||||
|
||||
if (!contents) {
|
||||
return map;
|
||||
}
|
||||
|
||||
contents.forEach((content) => {
|
||||
if (this.isFileDownloadable(content)) {
|
||||
let chapter,
|
||||
matches,
|
||||
split,
|
||||
filepathIsChapter,
|
||||
key;
|
||||
|
||||
// Search the chapter number in the filepath.
|
||||
matches = content.filepath.match(/\/(\d+)\//);
|
||||
if (matches && matches[1]) {
|
||||
chapter = matches[1];
|
||||
filepathIsChapter = content.filepath == '/' + chapter + '/';
|
||||
|
||||
// Init the chapter if it's not defined yet.
|
||||
map[chapter] = map[chapter] || { paths: {} };
|
||||
|
||||
if (content.filename == 'index.html' && filepathIsChapter) {
|
||||
// Index of the chapter, set indexUrl of the chapter.
|
||||
map[chapter].indexUrl = content.fileurl;
|
||||
} else {
|
||||
if (filepathIsChapter) {
|
||||
// It's a file in the root folder OR the WS isn't returning the filepath as it should (MDL-53671).
|
||||
// Try to get the path to the file from the URL.
|
||||
split = content.fileurl.split('mod_book/chapter' + content.filepath);
|
||||
key = split[1] || content.filename; // Use filename if we couldn't find the path.
|
||||
} else {
|
||||
// Remove the chapter folder from the path and add the filename.
|
||||
key = content.filepath.replace('/' + chapter + '/', '') + content.filename;
|
||||
}
|
||||
|
||||
map[chapter].paths[this.textUtils.decodeURIComponent(key)] = content.fileurl;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first chapter of a book.
|
||||
*
|
||||
* @param {AddonModBookTocChapter[]} chapters The chapters list.
|
||||
* @return {string} The chapter id.
|
||||
*/
|
||||
getFirstChapter(chapters: AddonModBookTocChapter[]): string {
|
||||
if (!chapters || !chapters.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
return chapters[0].id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next chapter to the given one.
|
||||
*
|
||||
* @param {AddonModBookTocChapter[]} chapters The chapters list.
|
||||
* @param {string} chapterId The current chapter.
|
||||
* @return {string} The next chapter id.
|
||||
*/
|
||||
getNextChapter(chapters: AddonModBookTocChapter[], chapterId: string): string {
|
||||
let next = '0';
|
||||
|
||||
for (let i = 0; i < chapters.length; i++) {
|
||||
if (chapters[i].id == chapterId) {
|
||||
if (typeof chapters[i + 1] != 'undefined') {
|
||||
next = chapters[i + 1].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the previous chapter to the given one.
|
||||
*
|
||||
* @param {AddonModBookTocChapter[]} chapters The chapters list.
|
||||
* @param {string} chapterId The current chapter.
|
||||
* @return {string} The next chapter id.
|
||||
*/
|
||||
getPreviousChapter(chapters: AddonModBookTocChapter[], chapterId: string): string {
|
||||
let previous = '0';
|
||||
|
||||
for (let i = 0; i < chapters.length; i++) {
|
||||
if (chapters[i].id == chapterId) {
|
||||
break;
|
||||
}
|
||||
previous = chapters[i].id;
|
||||
}
|
||||
|
||||
return previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the book toc as an array.
|
||||
*
|
||||
* @param {any[]} contents The module contents.
|
||||
* @return {any[]} The toc.
|
||||
*/
|
||||
getToc(contents: any[]): any[] {
|
||||
if (!contents || !contents.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return JSON.parse(contents[0].content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the book toc as an array of chapters (not nested).
|
||||
*
|
||||
* @param {any[]} contents The module contents.
|
||||
* @return {AddonModBookTocChapter[]} The toc as a list.
|
||||
*/
|
||||
getTocList(contents: any[]): AddonModBookTocChapter[] {
|
||||
const chapters = [],
|
||||
toc = this.getToc(contents);
|
||||
|
||||
toc.forEach((chapter) => {
|
||||
// Add the chapter to the list.
|
||||
let chapterId = chapter.href.replace('/index.html', '');
|
||||
chapters.push({id: chapterId, title: chapter.title, level: chapter.level});
|
||||
|
||||
if (chapter.subitems) {
|
||||
// Add all the subchapters to the list.
|
||||
chapter.subitems.forEach((subChapter) => {
|
||||
chapterId = subChapter.href.replace('/index.html', '');
|
||||
chapters.push({id: chapterId, title: subChapter.title, level: subChapter.level});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return chapters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates book data.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Promise resolved when the data is invalidated.
|
||||
*/
|
||||
invalidateBookData(courseId: number, siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
return site.invalidateWsCacheForKey(this.getBookDataCacheKey(courseId));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the prefetched content.
|
||||
*
|
||||
* @param {number} moduleId The module ID.
|
||||
* @param {number} courseId Course ID of the module.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Promise resolved when the data is invalidated.
|
||||
*/
|
||||
invalidateContent(moduleId: number, courseId: number, siteId?: string): Promise<any> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
const promises = [];
|
||||
|
||||
promises.push(this.invalidateBookData(courseId, siteId));
|
||||
promises.push(this.filepoolProvider.invalidateFilesByComponent(siteId, AddonModBookProvider.COMPONENT, moduleId));
|
||||
promises.push(this.courseProvider.invalidateModule(moduleId, siteId));
|
||||
|
||||
return this.utils.allPromises(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a file is downloadable. The file param must have a 'type' attribute like in core_course_get_contents response.
|
||||
*
|
||||
* @param {any} file File to check.
|
||||
* @return {boolean} Whether it's downloadable.
|
||||
*/
|
||||
isFileDownloadable(file: any): boolean {
|
||||
return file.type === 'file';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether or not the plugin is enabled.
|
||||
*
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<boolean>} Promise resolved with true if plugin is enabled, rejected or resolved with false otherwise.
|
||||
*/
|
||||
isPluginEnabled(siteId?: string): Promise<boolean> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
return site.canDownloadFiles();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a book as being viewed.
|
||||
*
|
||||
* @param {number} id Module ID.
|
||||
* @param {string} chapterId Chapter ID.
|
||||
* @return {Promise<any>} Promise resolved when the WS call is successful.
|
||||
*/
|
||||
logView(id: number, chapterId: string): Promise<any> {
|
||||
if (id) {
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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 book.
|
||||
*/
|
||||
@Injectable()
|
||||
export class AddonModBookLinkHandler extends CoreContentLinksModuleIndexHandler {
|
||||
name = 'AddonModBookLinkHandler';
|
||||
|
||||
constructor(courseHelper: CoreCourseHelperProvider) {
|
||||
super(courseHelper, 'mmaModBook', 'book');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// (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 { NavController, NavOptions } from 'ionic-angular';
|
||||
import { AddonModBookProvider } from './book';
|
||||
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '../../../../core/course/providers/module-delegate';
|
||||
import { CoreCourseProvider } from '../../../../core/course/providers/course';
|
||||
|
||||
/**
|
||||
* Handler to support book modules.
|
||||
*/
|
||||
@Injectable()
|
||||
export class AddonModBookModuleHandler implements CoreCourseModuleHandler {
|
||||
name = 'book';
|
||||
|
||||
constructor(protected bookProvider: AddonModBookProvider, private courseProvider: CoreCourseProvider) { }
|
||||
|
||||
/**
|
||||
* Check if the handler is enabled on a site level.
|
||||
*
|
||||
* @return {boolean|Promise<boolean>} Whether or not the handler is enabled on a site level.
|
||||
*/
|
||||
isEnabled(): boolean | Promise<boolean> {
|
||||
return this.bookProvider.isPluginEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data required to display the module in the course contents view.
|
||||
*
|
||||
* @param {any} module The module object.
|
||||
* @param {number} courseId The course ID.
|
||||
* @param {number} sectionId The section ID.
|
||||
* @return {CoreCourseModuleHandlerData} Data to render the module.
|
||||
*/
|
||||
getData(module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData {
|
||||
return {
|
||||
icon: this.courseProvider.getModuleIconSrc('book'),
|
||||
title: module.name,
|
||||
class: 'addon-mod_book-handler',
|
||||
action(event: Event, navCtrl: NavController, module: any, courseId: number, options: NavOptions): void {
|
||||
// @todo
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the component to render the module. This is needed to support singleactivity course format.
|
||||
*
|
||||
* @param {any} course The course object.
|
||||
* @param {any} module The module object.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
*/
|
||||
getMainComponent(course: any, module: any): any {
|
||||
// @todo
|
||||
}
|
||||
}
|
|
@ -66,6 +66,7 @@ import { CoreUserModule } from '../core/user/user.module';
|
|||
import { AddonCalendarModule } from '../addon/calendar/calendar.module';
|
||||
import { AddonUserProfileFieldModule } from '../addon/userprofilefield/userprofilefield.module';
|
||||
import { AddonFilesModule } from '../addon/files/files.module';
|
||||
import { AddonModBookModule } from '../addon/mod/book/book.module';
|
||||
import { AddonModLabelModule } from '../addon/mod/label/label.module';
|
||||
|
||||
// For translate loader. AoT requires an exported function for factories.
|
||||
|
@ -105,6 +106,7 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
|||
AddonCalendarModule,
|
||||
AddonUserProfileFieldModule,
|
||||
AddonFilesModule,
|
||||
AddonModBookModule,
|
||||
AddonModLabelModule
|
||||
],
|
||||
bootstrap: [IonicApp],
|
||||
|
|
|
@ -21,6 +21,7 @@ import { CoreInitDelegate } from '../../../providers/init';
|
|||
import { CoreLoggerProvider } from '../../../providers/logger';
|
||||
import { CoreSitesProvider } from '../../../providers/sites';
|
||||
import { CoreDomUtilsProvider } from '../../../providers/utils/dom';
|
||||
import { CoreTextUtilsProvider } from '../../../providers/utils/text';
|
||||
import { CoreUrlUtilsProvider } from '../../../providers/utils/url';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreContentLinksDelegate, CoreContentLinksAction } from './delegate';
|
||||
|
@ -37,7 +38,7 @@ export class CoreContentLinksHelperProvider {
|
|||
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider,
|
||||
private contentLinksDelegate: CoreContentLinksDelegate, private appProvider: CoreAppProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private translate: TranslateService,
|
||||
private initDelegate: CoreInitDelegate, eventsProvider: CoreEventsProvider) {
|
||||
private initDelegate: CoreInitDelegate, eventsProvider: CoreEventsProvider, private textUtils: CoreTextUtilsProvider) {
|
||||
this.logger = logger.getInstance('CoreContentLinksHelperProvider');
|
||||
|
||||
// Listen for app launched URLs. If we receive one, check if it's a content link.
|
||||
|
@ -103,7 +104,7 @@ export class CoreContentLinksHelperProvider {
|
|||
const modal = this.domUtils.showModalLoading();
|
||||
let username;
|
||||
|
||||
url = decodeURIComponent(url);
|
||||
url = this.textUtils.decodeURIComponent(url);
|
||||
|
||||
// App opened using custom URL scheme.
|
||||
this.logger.debug('Treating custom URL scheme: ' + url);
|
||||
|
|
Loading…
Reference in New Issue