MOBILE-2431: Wrap Ionic Native callbacks with NgZone.run

main
Albert Gasset 2018-06-21 15:59:06 +02:00
parent cb18fd9112
commit 0020880c6a
12 changed files with 102 additions and 51 deletions

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { NgModule, NgZone } from '@angular/core';
import { Network } from '@ionic-native/network';
import { AddonMessagesProvider } from './providers/messages';
import { AddonMessagesOfflineProvider } from './providers/messages-offline';
@ -69,7 +69,7 @@ export class AddonMessagesModule {
contentLinksDelegate: CoreContentLinksDelegate, indexLinkHandler: AddonMessagesIndexLinkHandler,
discussionLinkHandler: AddonMessagesDiscussionLinkHandler, sendMessageHandler: AddonMessagesSendMessageUserHandler,
userDelegate: CoreUserDelegate, cronDelegate: CoreCronDelegate, syncHandler: AddonMessagesSyncCronHandler,
network: Network, messagesSync: AddonMessagesSyncProvider, appProvider: CoreAppProvider,
network: Network, zone: NgZone, messagesSync: AddonMessagesSyncProvider, appProvider: CoreAppProvider,
localNotifications: CoreLocalNotificationsProvider, messagesProvider: AddonMessagesProvider,
sitesProvider: CoreSitesProvider, linkHelper: CoreContentLinksHelperProvider, updateManager: CoreUpdateManagerProvider,
settingsHandler: AddonMessagesSettingsHandler, settingsDelegate: CoreSettingsDelegate,
@ -88,7 +88,10 @@ export class AddonMessagesModule {
// Sync some discussions when device goes online.
network.onConnect().subscribe(() => {
messagesSync.syncAllDiscussions(undefined, true);
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
messagesSync.syncAllDiscussions(undefined, true);
});
});
const notificationClicked = (notification: any): void => {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, ViewChild } from '@angular/core';
import { Component, ViewChild, NgZone } from '@angular/core';
import { Content, IonicPage, ModalController, NavController, NavParams } from 'ionic-angular';
import { CoreAppProvider } from '@providers/app';
import { CoreLoggerProvider } from '@providers/logger';
@ -52,7 +52,7 @@ export class AddonModChatChatPage {
protected viewDestroyed = false;
protected pollingRunning = false;
constructor(navParams: NavParams, logger: CoreLoggerProvider, network: Network, private navCtrl: NavController,
constructor(navParams: NavParams, logger: CoreLoggerProvider, network: Network, zone: NgZone, private navCtrl: NavController,
private chatProvider: AddonModChatProvider, private appProvider: CoreAppProvider, sitesProvider: CoreSitesProvider,
private modalCtrl: ModalController, private domUtils: CoreDomUtilsProvider, private textUtils: CoreTextUtilsProvider) {
@ -63,7 +63,10 @@ export class AddonModChatChatPage {
this.currentUserBeep = 'beep ' + sitesProvider.getCurrentSiteUserId();
this.isOnline = this.appProvider.isOnline();
this.onlineObserver = network.onchange().subscribe((online) => {
this.isOnline = this.appProvider.isOnline();
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
this.isOnline = this.appProvider.isOnline();
});
});
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component } from '@angular/core';
import { Component, NgZone } from '@angular/core';
import { IonicPage, NavParams, ViewController } from 'ionic-angular';
import { CoreAppProvider } from '@providers/app';
import { CoreSitesProvider } from '@providers/sites';
@ -38,14 +38,17 @@ export class AddonModChatUsersPage {
protected sessionId: number;
protected onlineObserver: any;
constructor(navParams: NavParams, network: Network, private appProvider: CoreAppProvider,
constructor(navParams: NavParams, network: Network, zone: NgZone, private appProvider: CoreAppProvider,
private sitesProvider: CoreSitesProvider, private viewCtrl: ViewController,
private domUtils: CoreDomUtilsProvider, private chatProvider: AddonModChatProvider) {
this.sessionId = navParams.get('sessionId');
this.isOnline = this.appProvider.isOnline();
this.currentUserId = this.sitesProvider.getCurrentSiteUserId();
this.onlineObserver = network.onchange().subscribe((online) => {
this.isOnline = this.appProvider.isOnline();
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
this.isOnline = this.appProvider.isOnline();
});
});
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, OnDestroy, Optional } from '@angular/core';
import { Component, OnDestroy, Optional, NgZone } from '@angular/core';
import { IonicPage, NavParams, NavController, Content } from 'ionic-angular';
import { Network } from '@ionic-native/network';
import { TranslateService } from '@ngx-translate/core';
@ -69,7 +69,7 @@ export class AddonModFeedbackFormPage implements OnDestroy {
protected eventsProvider: CoreEventsProvider, protected feedbackSync: AddonModFeedbackSyncProvider, network: Network,
protected translate: TranslateService, protected loginHelper: CoreLoginHelperProvider,
protected linkHelper: CoreContentLinksHelperProvider, sitesProvider: CoreSitesProvider,
@Optional() private content: Content) {
@Optional() private content: Content, zone: NgZone) {
this.module = navParams.get('module');
this.courseId = navParams.get('courseId');
@ -82,7 +82,10 @@ export class AddonModFeedbackFormPage implements OnDestroy {
// Refresh online status when changes.
this.onlineObserver = network.onchange().subscribe((online) => {
this.offline = !online;
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
this.offline = !online;
});
});
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Optional, OnDestroy, ViewChild } from '@angular/core';
import { Component, Optional, OnDestroy, ViewChild, NgZone } from '@angular/core';
import { IonicPage, NavParams, Content } from 'ionic-angular';
import { Network } from '@ionic-native/network';
import { TranslateService } from '@ngx-translate/core';
@ -78,6 +78,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
constructor(navParams: NavParams,
network: Network,
zone: NgZone,
private appProvider: CoreAppProvider,
private eventsProvider: CoreEventsProvider,
private sitesProvider: CoreSitesProvider,
@ -99,7 +100,10 @@ export class AddonModForumDiscussionPage implements OnDestroy {
this.isOnline = this.appProvider.isOnline();
this.onlineObserver = network.onchange().subscribe((online) => {
this.isOnline = this.appProvider.isOnline();
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
this.isOnline = this.appProvider.isOnline();
});
});
this.isSplitViewOn = this.svComponent && this.svComponent.isOn();

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Injectable, NgZone } from '@angular/core';
import { Platform } from 'ionic-angular';
import { Badge } from '@ionic-native/badge';
import { Push, PushObject, PushOptions } from '@ionic-native/push';
@ -65,7 +65,7 @@ export class AddonPushNotificationsProvider {
protected pushNotificationsDelegate: AddonPushNotificationsDelegate, protected sitesProvider: CoreSitesProvider,
private badge: Badge, private localNotificationsProvider: CoreLocalNotificationsProvider,
private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider, private push: Push,
private configProvider: CoreConfigProvider, private device: Device) {
private configProvider: CoreConfigProvider, private device: Device, private zone: NgZone) {
this.logger = logger.getInstance('AddonPushNotificationsProvider');
this.appDB = appProvider.getDB();
this.appDB.createTablesFromSchema(this.tablesSchema);
@ -326,19 +326,28 @@ export class AddonPushNotificationsProvider {
const pushObject: PushObject = this.push.init(options);
pushObject.on('notification').subscribe((notification: any) => {
this.logger.log('Received a notification', notification);
this.onMessageReceived(notification);
// Execute the callback in the Angular zone, so change detection doesn't stop working.
this.zone.run(() => {
this.logger.log('Received a notification', notification);
this.onMessageReceived(notification);
});
});
pushObject.on('registration').subscribe((data: any) => {
this.pushID = data.registrationId;
this.registerDeviceOnMoodle().catch((error) => {
this.logger.warn('Can\'t register device', error);
// Execute the callback in the Angular zone, so change detection doesn't stop working.
this.zone.run(() => {
this.pushID = data.registrationId;
this.registerDeviceOnMoodle().catch((error) => {
this.logger.warn('Can\'t register device', error);
});
});
});
pushObject.on('error').subscribe((error: any) => {
this.logger.warn('Error with Push plugin', error);
// Execute the callback in the Angular zone, so change detection doesn't stop working.
this.zone.run(() => {
this.logger.warn('Error with Push plugin', error);
});
});
});
} catch (ex) {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, NgZone } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { CoreAppProvider } from '@providers/app';
@ -33,7 +33,7 @@ export class MoodleMobileApp implements OnInit {
protected lastUrls = {};
constructor(private platform: Platform, statusBar: StatusBar, logger: CoreLoggerProvider,
private eventsProvider: CoreEventsProvider, private loginHelper: CoreLoginHelperProvider,
private eventsProvider: CoreEventsProvider, private loginHelper: CoreLoginHelperProvider, private zone: NgZone,
private appProvider: CoreAppProvider, private langProvider: CoreLangProvider, private sitesProvider: CoreSitesProvider) {
this.logger = logger.getInstance('AppComponent');
@ -101,17 +101,20 @@ export class MoodleMobileApp implements OnInit {
// Handle app launched with a certain URL (custom URL scheme).
(<any> window).handleOpenURL = (url: string): void => {
// First check that the URL hasn't been treated a few seconds ago. Sometimes this function is called more than once.
if (this.lastUrls[url] && Date.now() - this.lastUrls[url] < 3000) {
// Function called more than once, stop.
return;
}
// Execute the callback in the Angular zone, so change detection doesn't stop working.
this.zone.run(() => {
// First check that the URL hasn't been treated a few seconds ago. Sometimes this function is called more than once.
if (this.lastUrls[url] && Date.now() - this.lastUrls[url] < 3000) {
// Function called more than once, stop.
return;
}
this.logger.debug('App launched by URL ', url);
this.logger.debug('App launched by URL ', url);
this.lastUrls[url] = Date.now();
this.lastUrls[url] = Date.now();
this.eventsProvider.trigger(CoreEventsProvider.APP_LAUNCHED_URL, url);
this.eventsProvider.trigger(CoreEventsProvider.APP_LAUNCHED_URL, url);
});
};
// Listen for app launched URLs. If we receive one, check if it's a SSO authentication.

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injector, Input } from '@angular/core';
import { Injector, Input, NgZone } from '@angular/core';
import { Content } from 'ionic-angular';
import { CoreSitesProvider } from '@providers/sites';
import { CoreCourseProvider } from '@core/course/providers/course';
@ -60,10 +60,14 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
this.modulePrefetchDelegate = injector.get(CoreCourseModulePrefetchDelegate);
const network = injector.get(Network);
const zone = injector.get(NgZone);
// Refresh online status when changes.
this.onlineObserver = network.onchange().subscribe((online) => {
this.isOnline = online;
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
this.isOnline = online;
});
});
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, OnDestroy } from '@angular/core';
import { Component, OnDestroy, NgZone } from '@angular/core';
import { IonicPage, NavController, NavParams, Platform, ModalController, Modal } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';
import { CoreAppProvider } from '@providers/app';
@ -69,7 +69,8 @@ export class CoreCoursesCoursePreviewPage implements OnDestroy {
private coursesProvider: CoreCoursesProvider, private platform: Platform, private modalCtrl: ModalController,
private translate: TranslateService, private eventsProvider: CoreEventsProvider,
private courseOptionsDelegate: CoreCourseOptionsDelegate, private courseHelper: CoreCourseHelperProvider,
private courseProvider: CoreCourseProvider, private courseFormatDelegate: CoreCourseFormatDelegate) {
private courseProvider: CoreCourseProvider, private courseFormatDelegate: CoreCourseFormatDelegate,
private zone: NgZone) {
this.course = navParams.get('course');
this.avoidOpenCourse = navParams.get('avoidOpenCourse');
@ -292,9 +293,15 @@ export class CoreCoursesCoursePreviewPage implements OnDestroy {
if (this.isDesktop || this.isMobile) {
// Observe loaded pages in the InAppBrowser to check if the enrol process has ended.
inAppLoadSubscription = window.on('loadstart').subscribe(urlLoaded);
inAppLoadSubscription = window.on('loadstart').subscribe((event) => {
// Execute the callback in the Angular zone, so change detection doesn't stop working.
this.zone.run(() => urlLoaded(event));
});
// Observe window closed.
inAppExitSubscription = window.on('exit').subscribe(inAppClosed);
inAppExitSubscription = window.on('exit').subscribe(() => {
// Execute the callback in the Angular zone, so change detection doesn't stop working.
this.zone.run(inAppClosed);
});
}
if (this.isDesktop) {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Injectable, NgZone } from '@angular/core';
import { Platform, App, NavController } from 'ionic-angular';
import { Keyboard } from '@ionic-native/keyboard';
import { Network } from '@ionic-native/network';
@ -70,18 +70,23 @@ export class CoreAppProvider {
protected isKeyboardShown = false;
constructor(dbProvider: CoreDbProvider, private platform: Platform, private keyboard: Keyboard, private appCtrl: App,
private network: Network, logger: CoreLoggerProvider, events: CoreEventsProvider) {
private network: Network, logger: CoreLoggerProvider, events: CoreEventsProvider, zone: NgZone) {
this.logger = logger.getInstance('CoreAppProvider');
this.db = dbProvider.getDB(this.DBNAME);
this.keyboard.onKeyboardShow().subscribe((data) => {
this.isKeyboardShown = true;
events.trigger(CoreEventsProvider.KEYBOARD_CHANGE, this.isKeyboardShown);
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
this.isKeyboardShown = true;
events.trigger(CoreEventsProvider.KEYBOARD_CHANGE, this.isKeyboardShown);
});
});
this.keyboard.onKeyboardHide().subscribe((data) => {
this.isKeyboardShown = false;
events.trigger(CoreEventsProvider.KEYBOARD_CHANGE, this.isKeyboardShown);
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
this.isKeyboardShown = false;
events.trigger(CoreEventsProvider.KEYBOARD_CHANGE, this.isKeyboardShown);
});
});
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Injectable, NgZone } from '@angular/core';
import { Network } from '@ionic-native/network';
import { CoreAppProvider } from './app';
import { CoreConfigProvider } from './config';
@ -115,7 +115,7 @@ export class CoreCronDelegate {
protected queuePromise = Promise.resolve();
constructor(logger: CoreLoggerProvider, private appProvider: CoreAppProvider, private configProvider: CoreConfigProvider,
private utils: CoreUtilsProvider, network: Network) {
private utils: CoreUtilsProvider, network: Network, zone: NgZone) {
this.logger = logger.getInstance('CoreCronDelegate');
this.appDB = this.appProvider.getDB();
@ -123,7 +123,10 @@ export class CoreCronDelegate {
// When the app is re-connected, start network handlers that were stopped.
network.onConnect().subscribe(() => {
this.startNetworkHandlers();
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
this.startNetworkHandlers();
});
});
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Injectable, NgZone } from '@angular/core';
import { Network } from '@ionic-native/network';
import { CoreAppProvider } from './app';
import { CoreEventsProvider } from './events';
@ -436,7 +436,8 @@ export class CoreFilepoolProvider {
private sitesProvider: CoreSitesProvider, private wsProvider: CoreWSProvider, private textUtils: CoreTextUtilsProvider,
private utils: CoreUtilsProvider, private mimeUtils: CoreMimetypeUtilsProvider, private urlUtils: CoreUrlUtilsProvider,
private timeUtils: CoreTimeUtilsProvider, private eventsProvider: CoreEventsProvider, initDelegate: CoreInitDelegate,
network: Network, private pluginFileDelegate: CorePluginFileDelegate, private domUtils: CoreDomUtilsProvider) {
network: Network, private pluginFileDelegate: CorePluginFileDelegate, private domUtils: CoreDomUtilsProvider,
zone: NgZone) {
this.logger = logger.getInstance('CoreFilepoolProvider');
this.appDB = this.appProvider.getDB();
@ -450,7 +451,10 @@ export class CoreFilepoolProvider {
// Start queue when device goes online.
network.onConnect().subscribe(() => {
this.checkQueueProcessing();
// Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => {
this.checkQueueProcessing();
});
});
});
}