Merge pull request #1726 from dpalou/MOBILE-2800_master
MOBILE-2800 course: Wait for format before opening coursemain
commit
f19b436d15
|
@ -36,6 +36,8 @@ import { CoreLoginHelperProvider } from '@core/login/providers/helper';
|
||||||
import { CoreConstants } from '@core/constants';
|
import { CoreConstants } from '@core/constants';
|
||||||
import { CoreSite } from '@classes/site';
|
import { CoreSite } from '@classes/site';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
|
import { CoreSitePluginsProvider } from '@core/siteplugins/providers/siteplugins';
|
||||||
|
import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefetch info of a module.
|
* Prefetch info of a module.
|
||||||
|
@ -123,7 +125,8 @@ export class CoreCourseHelperProvider {
|
||||||
private courseOptionsDelegate: CoreCourseOptionsDelegate, private siteHomeProvider: CoreSiteHomeProvider,
|
private courseOptionsDelegate: CoreCourseOptionsDelegate, private siteHomeProvider: CoreSiteHomeProvider,
|
||||||
private eventsProvider: CoreEventsProvider, private fileHelper: CoreFileHelperProvider,
|
private eventsProvider: CoreEventsProvider, private fileHelper: CoreFileHelperProvider,
|
||||||
private appProvider: CoreAppProvider, private fileProvider: CoreFileProvider, private injector: Injector,
|
private appProvider: CoreAppProvider, private fileProvider: CoreFileProvider, private injector: Injector,
|
||||||
private coursesProvider: CoreCoursesProvider, private courseOffline: CoreCourseOfflineProvider) { }
|
private coursesProvider: CoreCoursesProvider, private courseOffline: CoreCourseOfflineProvider,
|
||||||
|
private courseFormatDelegate: CoreCourseFormatDelegate, private sitePluginsProvider: CoreSitePluginsProvider) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function treats every module on the sections provided to load the handler data, treat completion
|
* This function treats every module on the sections provided to load the handler data, treat completion
|
||||||
|
@ -1309,4 +1312,42 @@ export class CoreCourseHelperProvider {
|
||||||
return (typeof section.availabilityinfo != 'undefined' && section.availabilityinfo != '') ||
|
return (typeof section.availabilityinfo != 'undefined' && section.availabilityinfo != '') ||
|
||||||
section.summary != '' || (section.modules && section.modules.length > 0);
|
section.summary != '' || (section.modules && section.modules.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for any course format plugin to load, and open the course page.
|
||||||
|
*
|
||||||
|
* If the plugin's promise is resolved, the course page will be opened. If it is rejected, they will see an error.
|
||||||
|
* If the promise for the plugin is still in progress when the user tries to open the course, a loader
|
||||||
|
* will be displayed until it is complete, before the course page is opened. If the promise is already complete,
|
||||||
|
* they will see the result immediately.
|
||||||
|
*
|
||||||
|
* @param {NavController} navCtrl The nav controller to use.
|
||||||
|
* @param {any} course Course to open
|
||||||
|
*/
|
||||||
|
openCourse(navCtrl: NavController, course: any): void {
|
||||||
|
if (this.sitePluginsProvider.sitePluginPromiseExists('format_' + course.format)) {
|
||||||
|
// This course uses a custom format plugin, wait for the format plugin to finish loading.
|
||||||
|
const loading = this.domUtils.showModalLoading();
|
||||||
|
this.sitePluginsProvider.sitePluginLoaded('format_' + course.format).then(() => {
|
||||||
|
// The format loaded successfully, but the handlers wont be registered until all site plugins have loaded.
|
||||||
|
if (this.sitePluginsProvider.sitePluginsFinishedLoading) {
|
||||||
|
loading.dismiss();
|
||||||
|
this.courseFormatDelegate.openCourse(navCtrl, course);
|
||||||
|
} else {
|
||||||
|
const observer = this.eventsProvider.on(CoreEventsProvider.SITE_PLUGINS_LOADED, () => {
|
||||||
|
loading.dismiss();
|
||||||
|
this.courseFormatDelegate.openCourse(navCtrl, course);
|
||||||
|
observer && observer.off();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
// The site plugin failed to load. The user needs to restart the app to try loading it again.
|
||||||
|
loading.dismiss();
|
||||||
|
this.domUtils.showErrorModal('core.courses.errorloadplugins', true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// No custom format plugin. We don't need to wait for anything.
|
||||||
|
this.courseFormatDelegate.openCourse(navCtrl, course);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { Component, Input, OnInit, Optional } from '@angular/core';
|
||||||
import { NavController } from 'ionic-angular';
|
import { NavController } from 'ionic-angular';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreCoursesProvider } from '../../providers/courses';
|
import { CoreCoursesProvider } from '../../providers/courses';
|
||||||
import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate';
|
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This directive is meant to display an item for a list of courses.
|
* This directive is meant to display an item for a list of courses.
|
||||||
|
@ -33,7 +33,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit {
|
||||||
@Input() course: any; // The course to render.
|
@Input() course: any; // The course to render.
|
||||||
|
|
||||||
constructor(@Optional() private navCtrl: NavController, private translate: TranslateService,
|
constructor(@Optional() private navCtrl: NavController, private translate: TranslateService,
|
||||||
private coursesProvider: CoreCoursesProvider, private courseFormatDelegate: CoreCourseFormatDelegate) {
|
private coursesProvider: CoreCoursesProvider, private courseHelper: CoreCourseHelperProvider) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,7 +82,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit {
|
||||||
*/
|
*/
|
||||||
openCourse(course: any): void {
|
openCourse(course: any): void {
|
||||||
if (course.isEnrolled) {
|
if (course.isEnrolled) {
|
||||||
this.courseFormatDelegate.openCourse(this.navCtrl, course);
|
this.courseHelper.openCourse(this.navCtrl, course);
|
||||||
} else {
|
} else {
|
||||||
this.navCtrl.push('CoreCoursesCoursePreviewPage', {course: course});
|
this.navCtrl.push('CoreCoursesCoursePreviewPage', {course: course});
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
import { CoreUserProvider } from '@core/user/providers/user';
|
import { CoreUserProvider } from '@core/user/providers/user';
|
||||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||||
import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate';
|
|
||||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||||
import { CoreCoursesCourseOptionsMenuComponent } from '../course-options-menu/course-options-menu';
|
import { CoreCoursesCourseOptionsMenuComponent } from '../course-options-menu/course-options-menu';
|
||||||
|
@ -55,7 +54,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
||||||
protected siteUpdatedObserver;
|
protected siteUpdatedObserver;
|
||||||
|
|
||||||
constructor(@Optional() private navCtrl: NavController, private courseHelper: CoreCourseHelperProvider,
|
constructor(@Optional() private navCtrl: NavController, private courseHelper: CoreCourseHelperProvider,
|
||||||
private courseFormatDelegate: CoreCourseFormatDelegate, private domUtils: CoreDomUtilsProvider,
|
private domUtils: CoreDomUtilsProvider,
|
||||||
private courseProvider: CoreCourseProvider, private eventsProvider: CoreEventsProvider,
|
private courseProvider: CoreCourseProvider, private eventsProvider: CoreEventsProvider,
|
||||||
private sitesProvider: CoreSitesProvider, private coursesProvider: CoreCoursesProvider,
|
private sitesProvider: CoreSitesProvider, private coursesProvider: CoreCoursesProvider,
|
||||||
private popoverCtrl: PopoverController, private userProvider: CoreUserProvider) { }
|
private popoverCtrl: PopoverController, private userProvider: CoreUserProvider) { }
|
||||||
|
@ -64,6 +63,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
||||||
* Component being initialized.
|
* Component being initialized.
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
||||||
this.downloadCourseEnabled = !this.coursesProvider.isDownloadCourseDisabledInSite();
|
this.downloadCourseEnabled = !this.coursesProvider.isDownloadCourseDisabledInSite();
|
||||||
|
|
||||||
if (this.downloadCourseEnabled) {
|
if (this.downloadCourseEnabled) {
|
||||||
|
@ -132,7 +132,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
||||||
* @param {any} course The course to open.
|
* @param {any} course The course to open.
|
||||||
*/
|
*/
|
||||||
openCourse(course: any): void {
|
openCourse(course: any): void {
|
||||||
this.courseFormatDelegate.openCourse(this.navCtrl, course);
|
this.courseHelper.openCourse(this.navCtrl, course);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"enrolme": "Enrol me",
|
"enrolme": "Enrol me",
|
||||||
"errorloadcategories": "An error occurred while loading categories.",
|
"errorloadcategories": "An error occurred while loading categories.",
|
||||||
"errorloadcourses": "An error occurred while loading courses.",
|
"errorloadcourses": "An error occurred while loading courses.",
|
||||||
|
"errorloadplugins": "The plugins required by this course could not be loaded correctly. Please restart the app to try again.",
|
||||||
"errorsearching": "An error occurred while searching.",
|
"errorsearching": "An error occurred while searching.",
|
||||||
"errorselfenrol": "An error occurred while self enrolling.",
|
"errorselfenrol": "An error occurred while self enrolling.",
|
||||||
"filtermycourses": "Filter my courses",
|
"filtermycourses": "Filter my courses",
|
||||||
|
|
|
@ -102,7 +102,9 @@ export class CoreSitePluginsHelperProvider {
|
||||||
// Plugins fetched, check that site hasn't changed.
|
// Plugins fetched, check that site hasn't changed.
|
||||||
if (data.siteId == this.sitesProvider.getCurrentSiteId() && plugins.length) {
|
if (data.siteId == this.sitesProvider.getCurrentSiteId() && plugins.length) {
|
||||||
// Site is still the same. Load the plugins and trigger the event.
|
// Site is still the same. Load the plugins and trigger the event.
|
||||||
this.loadSitePlugins(plugins).then(() => {
|
this.loadSitePlugins(plugins).catch((error) => {
|
||||||
|
this.logger.error(error);
|
||||||
|
}).finally(() => {
|
||||||
eventsProvider.trigger(CoreEventsProvider.SITE_PLUGINS_LOADED, {}, data.siteId);
|
eventsProvider.trigger(CoreEventsProvider.SITE_PLUGINS_LOADED, {}, data.siteId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -367,7 +369,9 @@ export class CoreSitePluginsHelperProvider {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
plugins.forEach((plugin) => {
|
plugins.forEach((plugin) => {
|
||||||
promises.push(this.loadSitePlugin(plugin));
|
const pluginPromise = this.loadSitePlugin(plugin);
|
||||||
|
promises.push(pluginPromise);
|
||||||
|
this.sitePluginsProvider.registerSitePluginPromise(plugin.component, pluginPromise);
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.utils.allPromises(promises);
|
return this.utils.allPromises(promises);
|
||||||
|
@ -510,7 +514,7 @@ export class CoreSitePluginsHelperProvider {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
this.logger.error('Error executing init method', handlerSchema.init, err);
|
return Promise.reject('Error executing init method ' + handlerSchema.init + ': ' + err.message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreConfigConstants } from '../../../configconstants';
|
import { CoreConfigConstants } from '../../../configconstants';
|
||||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||||
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler of a site plugin.
|
* Handler of a site plugin.
|
||||||
|
@ -65,13 +66,19 @@ export class CoreSitePluginsProvider {
|
||||||
|
|
||||||
protected logger;
|
protected logger;
|
||||||
protected sitePlugins: {[name: string]: CoreSitePluginsHandler} = {}; // Site plugins registered.
|
protected sitePlugins: {[name: string]: CoreSitePluginsHandler} = {}; // Site plugins registered.
|
||||||
|
protected sitePluginPromises: {[name: string]: Promise<any>} = {}; // Promises of loading plugins.
|
||||||
hasSitePluginsLoaded = false;
|
hasSitePluginsLoaded = false;
|
||||||
|
sitePluginsFinishedLoading = false;
|
||||||
|
|
||||||
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider,
|
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider,
|
||||||
private langProvider: CoreLangProvider, private appProvider: CoreAppProvider, private platform: Platform,
|
private langProvider: CoreLangProvider, private appProvider: CoreAppProvider, private platform: Platform,
|
||||||
private filepoolProvider: CoreFilepoolProvider, private coursesProvider: CoreCoursesProvider,
|
private filepoolProvider: CoreFilepoolProvider, private coursesProvider: CoreCoursesProvider,
|
||||||
private textUtils: CoreTextUtilsProvider) {
|
private textUtils: CoreTextUtilsProvider, private eventsProvider: CoreEventsProvider) {
|
||||||
this.logger = logger.getInstance('CoreUserProvider');
|
this.logger = logger.getInstance('CoreUserProvider');
|
||||||
|
const observer = this.eventsProvider.on(CoreEventsProvider.SITE_PLUGINS_LOADED, () => {
|
||||||
|
this.sitePluginsFinishedLoading = true;
|
||||||
|
observer && observer.off();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -513,4 +520,34 @@ export class CoreSitePluginsProvider {
|
||||||
setSitePluginHandler(name: string, handler: CoreSitePluginsHandler): void {
|
setSitePluginHandler(name: string, handler: CoreSitePluginsHandler): void {
|
||||||
this.sitePlugins[name] = handler;
|
this.sitePlugins[name] = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the promise for a plugin that is being initialised.
|
||||||
|
*
|
||||||
|
* @param {String} component
|
||||||
|
* @param {Promise<any>} promise
|
||||||
|
*/
|
||||||
|
registerSitePluginPromise(component: string, promise: Promise<any>): void {
|
||||||
|
this.sitePluginPromises[component] = promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a plugin being initialised for the specified component?
|
||||||
|
*
|
||||||
|
* @param {String} component
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
sitePluginPromiseExists(component: string): boolean {
|
||||||
|
return this.sitePluginPromises.hasOwnProperty(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the promise for a plugin that is being initialised.
|
||||||
|
*
|
||||||
|
* @param {String} component
|
||||||
|
* @return {Promise<any>}
|
||||||
|
*/
|
||||||
|
sitePluginLoaded(component: string): Promise<any> {
|
||||||
|
return this.sitePluginPromises[component];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue