Merge pull request #1584 from albertgasset/MOBILE-2675

Mobile 2675
main
Juan Leyva 2018-11-06 16:15:27 +01:00 committed by GitHub
commit f651dc983b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 186 additions and 79 deletions

View File

@ -1631,6 +1631,7 @@
"core.view": "moodle", "core.view": "moodle",
"core.viewcode": "local_moodlemobileapp", "core.viewcode": "local_moodlemobileapp",
"core.vieweditor": "local_moodlemobileapp", "core.vieweditor": "local_moodlemobileapp",
"core.viewembeddedcontent": "local_moodlemobileapp",
"core.viewprofile": "moodle", "core.viewprofile": "moodle",
"core.warningofflinedatadeleted": "local_moodlemobileapp", "core.warningofflinedatadeleted": "local_moodlemobileapp",
"core.whatisyourage": "moodle", "core.whatisyourage": "moodle",

View File

@ -54,9 +54,14 @@ export class AddonCompetencyCompetencyPage {
ionViewDidLoad(): void { ionViewDidLoad(): void {
this.fetchCompetency().then(() => { this.fetchCompetency().then(() => {
if (this.planId) { if (this.planId) {
this.competencyProvider.logCompetencyInPlanView(this.planId, this.competencyId, this.planStatus, this.userId); this.competencyProvider.logCompetencyInPlanView(this.planId, this.competencyId, this.planStatus, this.userId)
.catch(() => {
// Ignore errors.
});
} else { } else {
this.competencyProvider.logCompetencyInCourseView(this.courseId, this.competencyId, this.userId); this.competencyProvider.logCompetencyInCourseView(this.courseId, this.competencyId, this.userId).catch(() => {
// Ignore errors.
});
} }
}).finally(() => { }).finally(() => {
this.competencyLoaded = true; this.competencyLoaded = true;

View File

@ -41,7 +41,9 @@ export class AddonCompetencyCompetencySummaryPage {
*/ */
ionViewDidLoad(): void { ionViewDidLoad(): void {
this.fetchCompetency().then(() => { this.fetchCompetency().then(() => {
this.competencyProvider.logCompetencyView(this.competencyId); this.competencyProvider.logCompetencyView(this.competencyId).catch(() => {
// Ignore errors.
});
}).finally(() => { }).finally(() => {
this.competencyLoaded = true; this.competencyLoaded = true;
}); });

View File

@ -230,8 +230,6 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
siteId = siteId || this.sitesProvider.getCurrentSiteId(); siteId = siteId || this.sitesProvider.getCurrentSiteId();
promises.push(this.courseProvider.getModuleBasicInfo(module.id, siteId));
// Get assignment to retrieve all its submissions. // Get assignment to retrieve all its submissions.
promises.push(this.assignProvider.getAssignment(courseId, module.id, siteId).then((assign) => { promises.push(this.assignProvider.getAssignment(courseId, module.id, siteId).then((assign) => {
const subPromises = [], const subPromises = [],

View File

@ -168,6 +168,8 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
if (!this.nextChapter) { if (!this.nextChapter) {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
} }
}).catch(() => {
// Ignore errors.
}); });
}).catch((error) => { }).catch((error) => {
this.domUtils.showErrorModalDefault(error, 'addon.mod_book.errorchapter', true); this.domUtils.showErrorModalDefault(error, 'addon.mod_book.errorchapter', true);

View File

@ -49,6 +49,8 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp
this.loadContent().then(() => { this.loadContent().then(() => {
this.chatProvider.logView(this.chat.id).then(() => { this.chatProvider.logView(this.chat.id).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}); });
} }

View File

@ -105,6 +105,8 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
this.dataProvider.logView(this.data.id).then(() => { this.dataProvider.logView(this.data.id).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}); });

View File

@ -97,7 +97,9 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
super.ngOnInit(); super.ngOnInit();
this.loadContent(false, true).then(() => { this.loadContent(false, true).then(() => {
this.feedbackProvider.logView(this.feedback.id); this.feedbackProvider.logView(this.feedback.id).catch(() => {
// Ignore errors.
});
}).finally(() => { }).finally(() => {
this.tabsReady = true; this.tabsReady = true;
}); });

View File

@ -96,6 +96,8 @@ export class AddonModFeedbackFormPage implements OnDestroy {
this.fetchData().then(() => { this.fetchData().then(() => {
this.feedbackProvider.logView(this.feedback.id, true).then(() => { this.feedbackProvider.logView(this.feedback.id, true).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}); });
} }

View File

@ -57,6 +57,8 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
this.loadContent().then(() => { this.loadContent().then(() => {
this.folderProvider.logView(this.module.instance).then(() => { this.folderProvider.logView(this.module.instance).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}).finally(() => { }).finally(() => {
this.loaded = true; this.loaded = true;

View File

@ -48,7 +48,9 @@ export class AddonModGlossaryEntryPage {
*/ */
ionViewDidLoad(): void { ionViewDidLoad(): void {
this.fetchEntry().then(() => { this.fetchEntry().then(() => {
this.glossaryProvider.logEntryView(this.entry.id); this.glossaryProvider.logEntryView(this.entry.id).catch(() => {
// Ignore errors.
});
}).finally(() => { }).finally(() => {
this.loaded = true; this.loaded = true;
}); });

View File

@ -54,6 +54,8 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
this.loadContent().then(() => { this.loadContent().then(() => {
this.imscpProvider.logView(this.module.instance).then(() => { this.imscpProvider.logView(this.module.instance).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}); });
} }

View File

@ -358,9 +358,6 @@ export class AddonModLessonPrefetchHandler extends CoreCourseActivityPrefetchHan
// Prefetch question attempts in last retake for offline calculations. // Prefetch question attempts in last retake for offline calculations.
promises.push(this.lessonProvider.getQuestionsAttemptsOnline(lesson.id, retake, false, undefined, false, true, siteId)); promises.push(this.lessonProvider.getQuestionsAttemptsOnline(lesson.id, retake, false, undefined, false, true, siteId));
// Get module info to be able to handle links.
promises.push(this.courseProvider.getModuleBasicInfo(module.id, siteId));
if (accessInfo.canviewreports) { if (accessInfo.canviewreports) {
// Prefetch reports data. // Prefetch reports data.
promises.push(this.groupsProvider.getActivityAllowedGroupsIfEnabled(module.id, undefined, siteId).then((groups) => { promises.push(this.groupsProvider.getActivityAllowedGroupsIfEnabled(module.id, undefined, siteId).then((groups) => {

View File

@ -55,6 +55,8 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
this.loadContent().then(() => { this.loadContent().then(() => {
this.pageProvider.logView(this.module.instance).then(() => { this.pageProvider.logView(this.module.instance).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}); });
} }

View File

@ -52,6 +52,8 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
this.loadContent().then(() => { this.loadContent().then(() => {
this.resourceProvider.logView(this.module.instance).then(() => { this.resourceProvider.logView(this.module.instance).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}); });
} }

View File

@ -154,6 +154,8 @@ export class AddonModResourceHelperProvider {
module.contents).then(() => { module.contents).then(() => {
this.resourceProvider.logView(module.instance).then(() => { this.resourceProvider.logView(module.instance).then(() => {
this.courseProvider.checkModuleCompletion(courseId, module.completionstatus); this.courseProvider.checkModuleCompletion(courseId, module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}).catch((error) => { }).catch((error) => {
this.domUtils.showErrorModalDefault(error, 'addon.mod_resource.errorwhileloadingthecontent', true); this.domUtils.showErrorModalDefault(error, 'addon.mod_resource.errorwhileloadingthecontent', true);

View File

@ -70,11 +70,6 @@ export class AddonModResourcePrefetchHandler extends CoreCourseResourcePrefetchH
promises.push(this.resourceProvider.getResourceData(courseId, module.id)); promises.push(this.resourceProvider.getResourceData(courseId, module.id));
} }
/* When prefetching we usually use ignoreCache=true. However, this WS call can return a lot of data, so if
a user downloads resources 1 by 1 we would be downloading the same data over and over again. Since
this data won't change often it's probably better to use ignoreCache=false. */
promises.push(this.courseProvider.getModule(module.id, courseId, undefined, false, false, undefined, this.modName));
return Promise.all(promises); return Promise.all(promises);
}); });
} }

View File

@ -55,6 +55,8 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
this.loadContent(false, true).then(() => { this.loadContent(false, true).then(() => {
this.surveyProvider.logView(this.survey.id).then(() => { this.surveyProvider.logView(this.survey.id).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}); });
} }

View File

@ -173,6 +173,8 @@ export class AddonModUrlIndexComponent extends CoreCourseModuleMainResourceCompo
go(): void { go(): void {
this.urlProvider.logView(this.module.instance).then(() => { this.urlProvider.logView(this.module.instance).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
this.urlHelper.open(this.url); this.urlHelper.open(this.url);
} }

View File

@ -140,6 +140,9 @@ export class AddonModUrlModuleHandler implements CoreCourseModuleHandler {
return this.courseProvider.loadModuleContents(module, courseId, undefined, false, false, undefined, this.modName) return this.courseProvider.loadModuleContents(module, courseId, undefined, false, false, undefined, this.modName)
.then(() => { .then(() => {
return !(module.contents && module.contents[0] && module.contents[0].fileurl); return !(module.contents && module.contents[0] && module.contents[0].fileurl);
}).catch(() => {
// Module contents could not be loaded, most probably device is offline.
return true;
}); });
} }
@ -164,6 +167,8 @@ export class AddonModUrlModuleHandler implements CoreCourseModuleHandler {
protected openUrl(module: any, courseId: number): void { protected openUrl(module: any, courseId: number): void {
this.urlProvider.logView(module.instance).then(() => { this.urlProvider.logView(module.instance).then(() => {
this.courseProvider.checkModuleCompletion(courseId, module.completionstatus); this.courseProvider.checkModuleCompletion(courseId, module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
this.urlHelper.open(module.contents[0].fileurl); this.urlHelper.open(module.contents[0].fileurl);
} }

View File

@ -341,7 +341,9 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
this.currentPage = data.pageId; this.currentPage = data.pageId;
this.showLoadingAndFetch(true, false).then(() => { this.showLoadingAndFetch(true, false).then(() => {
this.wikiProvider.logPageView(this.currentPage); this.wikiProvider.logPageView(this.currentPage).catch(() => {
// Ignore errors.
});
}); });
// Stop listening for new page events. // Stop listening for new page events.

View File

@ -201,7 +201,6 @@ export class AddonModWikiPrefetchHandler extends CoreCourseActivityPrefetchHandl
promises.push(this.wikiProvider.getWiki(courseId, module.id, false, siteId).then((wiki) => { promises.push(this.wikiProvider.getWiki(courseId, module.id, false, siteId).then((wiki) => {
return this.courseHelper.getModuleCourseIdByInstance(wiki.id, 'wiki', siteId); return this.courseHelper.getModuleCourseIdByInstance(wiki.id, 'wiki', siteId);
})); }));
promises.push(this.courseProvider.getModuleBasicInfo(module.id, siteId));
// Get related page files and fetch them. // Get related page files and fetch them.
promises.push(this.getFiles(module, courseId, single, siteId).then((files) => { promises.push(this.getFiles(module, courseId, single, siteId).then((files) => {

View File

@ -132,6 +132,8 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy {
this.fetchSubmissionData().then(() => { this.fetchSubmissionData().then(() => {
this.workshopProvider.logViewSubmission(this.submissionId).then(() => { this.workshopProvider.logViewSubmission(this.submissionId).then(() => {
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completionstatus);
}).catch(() => {
// Ignore errors.
}); });
}); });
} }

View File

@ -67,7 +67,9 @@ export class AddonNotesListComponent implements OnInit, OnDestroy {
*/ */
ngOnInit(): void { ngOnInit(): void {
this.fetchNotes(true).then(() => { this.fetchNotes(true).then(() => {
this.notesProvider.logView(this.courseId); this.notesProvider.logView(this.courseId).catch(() => {
// Ignore errors.
});
}); });
} }
@ -128,7 +130,9 @@ export class AddonNotesListComponent implements OnInit, OnDestroy {
this.refreshIcon = 'spinner'; this.refreshIcon = 'spinner';
this.syncIcon = 'spinner'; this.syncIcon = 'spinner';
this.fetchNotes(true).then(() => { this.fetchNotes(true).then(() => {
this.notesProvider.logView(this.courseId); this.notesProvider.logView(this.courseId).catch(() => {
// Ignore errors.
});
}); });
} }

View File

@ -1630,6 +1630,7 @@
"core.view": "View", "core.view": "View",
"core.viewcode": "View code", "core.viewcode": "View code",
"core.vieweditor": "View editor", "core.vieweditor": "View editor",
"core.viewembeddedcontent": "View embedded content",
"core.viewprofile": "View profile", "core.viewprofile": "View profile",
"core.warningofflinedatadeleted": "Offline data from {{component}} '{{name}}' has been deleted. {{error}}", "core.warningofflinedatadeleted": "Offline data from {{component}} '{{name}}' has been deleted. {{error}}",
"core.whatisyourage": "What is your age?", "core.whatisyourage": "What is your age?",

View File

@ -101,8 +101,13 @@ export class CoreCourseActivityPrefetchHandlerBase extends CoreCourseModulePrefe
} }
const prefetchPromise = this.setDownloading(module.id, siteId).then(() => { const prefetchPromise = this.setDownloading(module.id, siteId).then(() => {
// Package marked as downloading, call the download function. // Package marked as downloading, get module info to be able to handle links.
// Send all the params except downloadFn. This includes all params passed after siteId. return Promise.all([
this.courseProvider.getModuleBasicInfo(module.id, siteId),
this.courseProvider.getModule(module.id, courseId, undefined, false, true, siteId),
]);
}).then(() => {
// Call the download function, send all the params except downloadFn. This includes all params passed after siteId.
return downloadFn.apply(downloadFn, [module, courseId, single, siteId].concat(args)); return downloadFn.apply(downloadFn, [module, courseId, single, siteId].concat(args));
}).then((extra: any) => { }).then((extra: any) => {
// Only accept string types. // Only accept string types.

View File

@ -61,8 +61,11 @@ export class CoreCourseResourcePrefetchHandlerBase extends CoreCourseModulePrefe
return this.getOngoingDownload(module.id, siteId); return this.getOngoingDownload(module.id, siteId);
} }
// Load module contents (ignore cache so we always have the latest data). // Get module info to be able to handle links.
const prefetchPromise = this.loadContents(module, courseId, true).then(() => { const prefetchPromise = this.courseProvider.getModuleBasicInfo(module.id, siteId).then(() => {
// Load module contents (ignore cache so we always have the latest data).
return this.loadContents(module, courseId, true);
}).then(() => {
// Get the intro files. // Get the intro files.
return this.getIntroFiles(module, courseId); return this.getIntroFiles(module, courseId);
}).then((introFiles) => { }).then((introFiles) => {

View File

@ -303,35 +303,18 @@ export class CoreCourseProvider {
siteId?: string, modName?: string): Promise<any> { siteId?: string, modName?: string): Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId(); siteId = siteId || this.sitesProvider.getCurrentSiteId();
let promise; // Helper function to do the WS request without processing the result.
const doRequest = (site: CoreSite, moduleId: number, modName: string, includeStealth: boolean, preferCache: boolean):
if (!courseId) { Promise<any> => {
// No courseId passed, try to retrieve it.
promise = this.getModuleBasicInfo(moduleId, siteId).then((module) => {
return module.course;
});
} else {
promise = Promise.resolve(courseId);
}
return promise.then((cid) => {
courseId = cid;
// Get the site.
return this.sitesProvider.getSite(siteId);
}).then((site) => {
// We have courseId, we can use core_course_get_contents for compatibility.
this.logger.debug(`Getting module ${moduleId} in course ${courseId}`);
const params: any = { const params: any = {
courseid: courseId, courseid: courseId,
options: [] options: []
}, };
preSets: any = { const preSets: CoreSiteWSPreSets = {
omitExpires: preferCache omitExpires: preferCache
}; };
if (this.canRequestStealthModules(site)) { if (includeStealth) {
params.options.push({ params.options.push({
name: 'includestealthmodules', name: 'includestealthmodules',
value: 1 value: 1
@ -354,35 +337,72 @@ export class CoreCourseProvider {
} }
if (!preferCache && ignoreCache) { if (!preferCache && ignoreCache) {
preSets.getFromCache = 0; preSets.getFromCache = false;
preSets.emergencyCache = 0; preSets.emergencyCache = false;
}
if (sectionId) {
params.options.push({
name: 'sectionid',
value: sectionId
});
} }
return site.read('core_course_get_contents', params, preSets).catch(() => { return site.read('core_course_get_contents', params, preSets).catch(() => {
// Error getting the module. Try to get all contents (without filtering by module). // The module might still be cached by a request with different parameters.
return this.getSections(courseId, false, false, preSets, siteId); if (!ignoreCache && !this.appProvider.isOnline()) {
}).then((sections) => { if (includeStealth) {
for (let i = 0; i < sections.length; i++) { // Older versions didn't include the includestealthmodules option.
const section = sections[i]; return doRequest(site, moduleId, modName, false, true);
for (let j = 0; j < section.modules.length; j++) { } else if (modName) {
const module = section.modules[j]; // Falback to the request for the given moduleId only.
if (module.id == moduleId) { return doRequest(site, moduleId, undefined, this.canRequestStealthModules(site), true);
module.course = courseId;
return module;
}
} }
} }
return Promise.reject(null); return Promise.reject(null);
}); });
};
let promise;
if (!courseId) {
// No courseId passed, try to retrieve it.
promise = this.getModuleBasicInfo(moduleId, siteId).then((module) => {
courseId = module.course;
});
} else {
promise = Promise.resolve();
}
return promise.then(() => {
return this.sitesProvider.getSite(siteId);
}).then((site) => {
// We have courseId, we can use core_course_get_contents for compatibility.
this.logger.debug(`Getting module ${moduleId} in course ${courseId}`);
return doRequest(site, moduleId, modName, this.canRequestStealthModules(site), preferCache);
}).catch(() => {
// Error getting the module. Try to get all contents (without filtering by module).
const preSets: CoreSiteWSPreSets = {
omitExpires: preferCache
};
if (!preferCache && ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return this.getSections(courseId, false, false, preSets, siteId);
}).then((sections) => {
for (let i = 0; i < sections.length; i++) {
const section = sections[i];
if (sectionId != null && !isNaN(sectionId) && sectionId != section.id) {
continue;
}
for (let j = 0; j < section.modules.length; j++) {
const module = section.modules[j];
if (module.id == moduleId) {
module.course = courseId;
return module;
}
}
}
return Promise.reject(null);
}); });
} }

View File

@ -53,7 +53,9 @@ export class CoreGradesCourseComponent {
} }
// Add log in Moodle. // Add log in Moodle.
return this.gradesProvider.logCourseGradesView(this.courseId, this.userId); return this.gradesProvider.logCourseGradesView(this.courseId, this.userId).catch(() => {
// Ignore errors.
});
}).finally(() => { }).finally(() => {
this.gradesLoaded = true; this.gradesLoaded = true;
}); });

View File

@ -55,7 +55,9 @@ export class CoreGradesCoursesPage {
} }
// Add log in Moodle. // Add log in Moodle.
return this.gradesProvider.logCoursesGradesView(); return this.gradesProvider.logCoursesGradesView().catch(() => {
// Ignore errors.
});
}).finally(() => { }).finally(() => {
this.gradesLoaded = true; this.gradesLoaded = true;
}); });

View File

@ -240,6 +240,7 @@
"view": "View", "view": "View",
"viewcode": "View code", "viewcode": "View code",
"vieweditor": "View editor", "vieweditor": "View editor",
"viewembeddedcontent": "View embedded content",
"viewprofile": "View profile", "viewprofile": "View profile",
"warningofflinedatadeleted": "Offline data from {{component}} '{{name}}' has been deleted. {{error}}", "warningofflinedatadeleted": "Offline data from {{component}} '{{name}}' has been deleted. {{error}}",
"whatisyourage": "What is your age?", "whatisyourage": "What is your age?",

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
import { Injectable, NgZone } from '@angular/core'; import { Injectable, NgZone } from '@angular/core';
import { Platform } from 'ionic-angular'; import { Config, Platform } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { Network } from '@ionic-native/network'; import { Network } from '@ionic-native/network';
import { CoreAppProvider } from '../app'; import { CoreAppProvider } from '../app';
@ -24,6 +24,7 @@ import { CoreDomUtilsProvider } from './dom';
import { CoreTextUtilsProvider } from './text'; import { CoreTextUtilsProvider } from './text';
import { CoreUrlUtilsProvider } from './url'; import { CoreUrlUtilsProvider } from './url';
import { CoreUtilsProvider } from './utils'; import { CoreUtilsProvider } from './utils';
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
/* /*
* "Utils" service with helper functions for iframes, embed and similar. * "Utils" service with helper functions for iframes, embed and similar.
@ -37,7 +38,8 @@ export class CoreIframeUtilsProvider {
constructor(logger: CoreLoggerProvider, private fileProvider: CoreFileProvider, private sitesProvider: CoreSitesProvider, constructor(logger: CoreLoggerProvider, private fileProvider: CoreFileProvider, private sitesProvider: CoreSitesProvider,
private urlUtils: CoreUrlUtilsProvider, private textUtils: CoreTextUtilsProvider, private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private textUtils: CoreTextUtilsProvider, private utils: CoreUtilsProvider,
private domUtils: CoreDomUtilsProvider, private platform: Platform, private appProvider: CoreAppProvider, private domUtils: CoreDomUtilsProvider, private platform: Platform, private appProvider: CoreAppProvider,
private translate: TranslateService, private network: Network, private zone: NgZone) { private translate: TranslateService, private network: Network, private zone: NgZone, private config: Config,
private contentLinksHelper: CoreContentLinksHelperProvider) {
this.logger = logger.getInstance('CoreUtilsProvider'); this.logger = logger.getInstance('CoreUtilsProvider');
} }
@ -57,16 +59,51 @@ export class CoreIframeUtilsProvider {
return true; return true;
} }
// The frame has an online URL but the app is offline. Show a warning. // The frame has an online URL but the app is offline. Show a warning, or a link if the URL can be opened in the app.
const div = document.createElement('div'); const div = document.createElement('div');
div.setAttribute('text-center', ''); div.setAttribute('text-center', '');
div.setAttribute('padding', ''); div.setAttribute('padding', '');
div.classList.add('core-iframe-offline-warning'); div.classList.add('core-iframe-offline-warning');
div.innerHTML = (isSubframe ? '' : this.domUtils.getConnectionWarningIconHtml()) +
'<p>' + this.translate.instant('core.networkerroriframemsg') + '</p>';
element.parentElement.insertBefore(div, element); const site = this.sitesProvider.getCurrentSite();
const username = site ? site.getInfo().username : undefined;
this.contentLinksHelper.canHandleLink(src, undefined, username).then((canHandleLink) => {
if (canHandleLink) {
const link = document.createElement('a');
if (isSubframe) {
// Ionic styles are not available in subframes, adding some minimal inline styles.
link.style.display = 'block';
link.style.padding = '1em';
link.style.fontWeight = '500';
link.style.textAlign = 'center';
link.style.textTransform = 'uppercase';
link.style.cursor = 'pointer';
} else {
const mode = this.config.get('mode');
link.setAttribute('ion-button', '');
link.classList.add('button', 'button-' + mode,
'button-default', 'button-default-' + mode,
'button-block', 'button-block-' + mode);
}
const message = this.translate.instant('core.viewembeddedcontent');
link.innerHTML = isSubframe ? message : '<span class="button-inner">' + message + '</span>';
link.onclick = (event: Event): void => {
this.contentLinksHelper.handleLink(src, username);
event.preventDefault();
};
div.appendChild(link);
} else {
div.innerHTML = (isSubframe ? '' : this.domUtils.getConnectionWarningIconHtml()) +
'<p>' + this.translate.instant('core.networkerroriframemsg') + '</p>';
}
element.parentElement.insertBefore(div, element);
});
// Add a class to specify that the iframe is hidden. // Add a class to specify that the iframe is hidden.
element.classList.add('core-iframe-offline-disabled'); element.classList.add('core-iframe-offline-disabled');