From 82033e05d074fa031820318cbf19c44f409776b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Mon, 13 Jun 2022 12:45:43 +0200 Subject: [PATCH] MOBILE-4061 core: Handle network changes on the network service --- src/addons/calendar/pages/day/day.page.ts | 4 +- src/addons/calendar/pages/event/event.page.ts | 4 +- src/addons/calendar/pages/index/index.page.ts | 4 +- src/addons/messages/messages.module.ts | 5 +- .../components/users-modal/users-modal.ts | 4 +- src/addons/mod/chat/pages/chat/chat.ts | 4 +- src/addons/mod/feedback/pages/form/form.ts | 4 +- .../forum/pages/discussion/discussion.page.ts | 4 +- .../mod/resource/components/index/index.ts | 4 +- src/addons/mod/wiki/components/index/index.ts | 4 +- src/app/app.component.ts | 6 +- .../comments/pages/viewer/viewer.page.ts | 4 +- .../module-summary/module-summary.ts | 4 +- src/core/features/emulator/emulator.module.ts | 8 +- .../features/emulator/services/network.ts | 81 ------------- .../settings/pages/deviceinfo/deviceinfo.ts | 9 +- src/core/initializers/watch-network.ts | 5 +- src/core/services/filepool.ts | 4 +- src/core/services/network.ts | 112 ++++++++++++++++-- src/core/services/utils/iframe.ts | 4 +- src/core/singletons/index.ts | 3 + src/testing/utils.ts | 5 +- 22 files changed, 151 insertions(+), 135 deletions(-) delete mode 100644 src/core/features/emulator/services/network.ts diff --git a/src/addons/calendar/pages/day/day.page.ts b/src/addons/calendar/pages/day/day.page.ts index 5efb9dfa2..b7d63ed0e 100644 --- a/src/addons/calendar/pages/day/day.page.ts +++ b/src/addons/calendar/pages/day/day.page.ts @@ -33,7 +33,7 @@ import { CoreCategoryData, CoreCourses, CoreEnrolledCourseData } from '@features import { CoreCoursesHelper } from '@features/courses/services/courses-helper'; import { AddonCalendarFilterComponent } from '../../components/filter/filter'; import moment from 'moment'; -import { Network, NgZone } from '@singletons'; +import { NgZone } from '@singletons'; import { CoreNavigator } from '@services/navigator'; import { Params } from '@angular/router'; import { Subscription } from 'rxjs'; @@ -180,7 +180,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy { ); // Refresh online status when changes. - this.onlineObserver = Network.onChange().subscribe(() => { + this.onlineObserver = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/addons/calendar/pages/event/event.page.ts b/src/addons/calendar/pages/event/event.page.ts index 95c35dccd..b448e9280 100644 --- a/src/addons/calendar/pages/event/event.page.ts +++ b/src/addons/calendar/pages/event/event.page.ts @@ -32,7 +32,7 @@ import { CoreLocalNotifications } from '@services/local-notifications'; import { CoreCourse } from '@features/course/services/course'; import { CoreTimeUtils } from '@services/utils/time'; import { CoreGroups } from '@services/groups'; -import { Network, NgZone, Translate } from '@singletons'; +import { NgZone, Translate } from '@singletons'; import { Subscription } from 'rxjs'; import { CoreNavigator } from '@services/navigator'; import { CoreUtils } from '@services/utils/utils'; @@ -123,7 +123,7 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy { ); // Refresh online status when changes. - this.onlineObserver = Network.onChange().subscribe(() => { + this.onlineObserver = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/addons/calendar/pages/index/index.page.ts b/src/addons/calendar/pages/index/index.page.ts index cac6d7fde..e35a44bcf 100644 --- a/src/addons/calendar/pages/index/index.page.ts +++ b/src/addons/calendar/pages/index/index.page.ts @@ -23,7 +23,7 @@ import { AddonCalendar, AddonCalendarProvider } from '../../services/calendar'; import { AddonCalendarOffline } from '../../services/calendar-offline'; import { AddonCalendarSync, AddonCalendarSyncProvider } from '../../services/calendar-sync'; import { AddonCalendarFilter, AddonCalendarHelper } from '../../services/calendar-helper'; -import { Network, NgZone } from '@singletons'; +import { NgZone } from '@singletons'; import { Subscription } from 'rxjs'; import { CoreEnrolledCourseData } from '@features/courses/services/courses'; import { ActivatedRoute, Params } from '@angular/router'; @@ -153,7 +153,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy { ); // Refresh online status when changes. - this.onlineObserver = Network.onChange().subscribe(() => { + this.onlineObserver = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/addons/messages/messages.module.ts b/src/addons/messages/messages.module.ts index 5616c65e6..80e3875d8 100644 --- a/src/addons/messages/messages.module.ts +++ b/src/addons/messages/messages.module.ts @@ -32,7 +32,8 @@ import { CorePushNotificationsDelegate } from '@features/pushnotifications/servi import { AddonMessagesPushClickHandler } from './services/handlers/push-click'; import { CoreUserDelegate } from '@features/user/services/user-delegate'; import { AddonMessagesSendMessageUserHandler } from './services/handlers/user-send-message'; -import { Network, NgZone } from '@singletons'; +import { NgZone } from '@singletons'; +import { CoreNetwork } from '@services/network'; import { AddonMessagesSync, AddonMessagesSyncProvider } from './services/messages-sync'; import { AddonMessagesSyncCronHandler } from './services/handlers/sync-cron'; import { CoreSitePreferencesRoutingModule } from '@features/settings/pages/site/site-routing'; @@ -86,7 +87,7 @@ const preferencesRoutes: Routes = [ CoreUserDelegate.registerHandler(AddonMessagesSendMessageUserHandler.instance); // Sync some discussions when device goes online. - Network.onConnect().subscribe(() => { + CoreNetwork.onConnect().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { AddonMessagesSync.syncAllDiscussions(undefined, true); diff --git a/src/addons/mod/chat/components/users-modal/users-modal.ts b/src/addons/mod/chat/components/users-modal/users-modal.ts index 73782e491..3a8e0b435 100644 --- a/src/addons/mod/chat/components/users-modal/users-modal.ts +++ b/src/addons/mod/chat/components/users-modal/users-modal.ts @@ -16,7 +16,7 @@ import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { CoreNetwork } from '@services/network'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; -import { ModalController, Network, NgZone } from '@singletons'; +import { ModalController, NgZone } from '@singletons'; import { Subscription } from 'rxjs'; import { AddonModChat, AddonModChatUser } from '../../services/chat'; @@ -42,7 +42,7 @@ export class AddonModChatUsersModalComponent implements OnInit, OnDestroy { constructor() { this.isOnline = CoreNetwork.isOnline(); this.currentUserId = CoreSites.getCurrentSiteUserId(); - this.onlineSubscription = Network.onChange().subscribe(() => { + this.onlineSubscription = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/addons/mod/chat/pages/chat/chat.ts b/src/addons/mod/chat/pages/chat/chat.ts index 47bde10f6..01cfcdb99 100644 --- a/src/addons/mod/chat/pages/chat/chat.ts +++ b/src/addons/mod/chat/pages/chat/chat.ts @@ -23,7 +23,7 @@ import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; -import { Network, NgZone, Translate } from '@singletons'; +import { NgZone, Translate } from '@singletons'; import { CoreEvents } from '@singletons/events'; import { Subscription } from 'rxjs'; import { AddonModChatUsersModalComponent, AddonModChatUsersModalResult } from '../../components/users-modal/users-modal'; @@ -67,7 +67,7 @@ export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave { constructor() { this.currentUserId = CoreSites.getCurrentSiteUserId(); this.isOnline = CoreNetwork.isOnline(); - this.onlineSubscription = Network.onChange().subscribe(() => { + this.onlineSubscription = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/addons/mod/feedback/pages/form/form.ts b/src/addons/mod/feedback/pages/form/form.ts index 7ef9df00a..6226940cc 100644 --- a/src/addons/mod/feedback/pages/form/form.ts +++ b/src/addons/mod/feedback/pages/form/form.ts @@ -24,7 +24,7 @@ import { CoreNavigator } from '@services/navigator'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; -import { Network, NgZone, Translate } from '@singletons'; +import { NgZone, Translate } from '@singletons'; import { CoreEvents } from '@singletons/events'; import { Subscription } from 'rxjs'; import { @@ -80,7 +80,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { this.currentSite = CoreSites.getRequiredCurrentSite(); // Refresh online status when changes. - this.onlineObserver = Network.onChange().subscribe(() => { + this.onlineObserver = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.offline = !CoreNetwork.isOnline(); diff --git a/src/addons/mod/forum/pages/discussion/discussion.page.ts b/src/addons/mod/forum/pages/discussion/discussion.page.ts index 39af8c389..6556402dd 100644 --- a/src/addons/mod/forum/pages/discussion/discussion.page.ts +++ b/src/addons/mod/forum/pages/discussion/discussion.page.ts @@ -30,7 +30,7 @@ import { CoreScreen } from '@services/screen'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; -import { Network, NgZone, Translate } from '@singletons'; +import { NgZone, Translate } from '@singletons'; import { CoreArray } from '@singletons/array'; import { CoreDom } from '@singletons/dom'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; @@ -166,7 +166,7 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes this.isOnline = CoreNetwork.isOnline(); this.externalUrl = CoreSites.getCurrentSite()?.createSiteUrl('/mod/forum/discuss.php', { d: this.discussionId.toString() }); - this.onlineObserver = Network.onChange().subscribe(() => { + this.onlineObserver = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/addons/mod/resource/components/index/index.ts b/src/addons/mod/resource/components/index/index.ts index e8ca58c9c..c13acb8fd 100644 --- a/src/addons/mod/resource/components/index/index.ts +++ b/src/addons/mod/resource/components/index/index.ts @@ -27,7 +27,7 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils, OpenFileAction } from '@services/utils/utils'; -import { Network, NgZone, Translate } from '@singletons'; +import { NgZone, Translate } from '@singletons'; import { Subscription } from 'rxjs'; import { AddonModResource, @@ -83,7 +83,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource this.isOnline = CoreNetwork.isOnline(); // Refresh online status when changes. - this.onlineObserver = Network.onChange().subscribe(() => { + this.onlineObserver = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/addons/mod/wiki/components/index/index.ts b/src/addons/mod/wiki/components/index/index.ts index 0a88f7cdb..73444595e 100644 --- a/src/addons/mod/wiki/components/index/index.ts +++ b/src/addons/mod/wiki/components/index/index.ts @@ -27,7 +27,7 @@ import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; -import { Network, Translate, NgZone } from '@singletons'; +import { Translate, NgZone } from '@singletons'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreText } from '@singletons/text'; import { Subscription } from 'rxjs'; @@ -119,7 +119,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp this.isOnline = CoreNetwork.isOnline(); // Refresh online status when changes. - this.onlineSubscription = Network.onChange().subscribe(() => { + this.onlineSubscription = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 594733fe0..25dbce527 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -19,7 +19,8 @@ import { BackButtonEvent, ScrollDetail } from '@ionic/core'; import { CoreLang } from '@services/lang'; import { CoreLoginHelper } from '@features/login/services/login-helper'; import { CoreEvents } from '@singletons/events'; -import { Network, NgZone, Platform, SplashScreen, Translate } from '@singletons'; +import { NgZone, Platform, SplashScreen, Translate } from '@singletons'; +import { CoreNetwork } from '@services/network'; import { CoreApp, CoreAppProvider } from '@services/app'; import { CoreSites } from '@services/sites'; import { CoreNavigator } from '@services/navigator'; @@ -32,7 +33,6 @@ import { CoreConstants } from '@/core/constants'; import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreDom } from '@singletons/dom'; -import { CoreNetwork } from '@services/network'; const MOODLE_VERSION_PREFIX = 'version-'; const MOODLEAPP_VERSION_PREFIX = 'moodleapp-'; @@ -308,7 +308,7 @@ export class AppComponent implements OnInit, AfterViewInit { await Platform.ready(); // Refresh online status when changes. - Network.onChange().subscribe(() => { + CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { const isOnline = CoreNetwork.isOnline(); diff --git a/src/core/features/comments/pages/viewer/viewer.page.ts b/src/core/features/comments/pages/viewer/viewer.page.ts index 6c92436e0..dc371bb13 100644 --- a/src/core/features/comments/pages/viewer/viewer.page.ts +++ b/src/core/features/comments/pages/viewer/viewer.page.ts @@ -30,7 +30,7 @@ import { import { IonContent, IonRefresher } from '@ionic/angular'; import { ContextLevel, CoreConstants } from '@/core/constants'; import { CoreNavigator } from '@services/navigator'; -import { Network, NgZone, Translate } from '@singletons'; +import { NgZone, Translate } from '@singletons'; import { CoreUtils } from '@services/utils/utils'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUser } from '@features/user/services/user'; @@ -110,7 +110,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { }, CoreSites.getCurrentSiteId()); this.isOnline = CoreNetwork.isOnline(); - this.onlineObserver = Network.onChange().subscribe(() => { + this.onlineObserver = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/core/features/course/components/module-summary/module-summary.ts b/src/core/features/course/components/module-summary/module-summary.ts index 1cc0e43db..dd3c6cbb6 100644 --- a/src/core/features/course/components/module-summary/module-summary.ts +++ b/src/core/features/course/components/module-summary/module-summary.ts @@ -30,7 +30,7 @@ import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; -import { ModalController, Network, NgZone } from '@singletons'; +import { ModalController, NgZone } from '@singletons'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { Subscription } from 'rxjs'; @@ -82,7 +82,7 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy { this.isOnline = CoreNetwork.isOnline(); // Refresh online status when changes. - this.onlineSubscription = Network.onChange().subscribe(() => { + this.onlineSubscription = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.isOnline = CoreNetwork.isOnline(); diff --git a/src/core/features/emulator/emulator.module.ts b/src/core/features/emulator/emulator.module.ts index 03d2e211f..17538020d 100644 --- a/src/core/features/emulator/emulator.module.ts +++ b/src/core/features/emulator/emulator.module.ts @@ -81,8 +81,8 @@ import { FileTransferMock } from './services/file-transfer'; import { GeolocationMock } from './services/geolocation'; import { InAppBrowserMock } from './services/inappbrowser'; import { MediaCaptureMock } from './services/media-capture'; -import { NetworkMock } from './services/network'; import { ZipMock } from './services/zip'; +import { CoreNetworkService } from '@services/network'; /** * This module handles the emulation of Cordova plugins in browser and desktop. @@ -152,11 +152,7 @@ import { ZipMock } from './services/zip'; deps: [Platform], useFactory: (platform: Platform): MediaCapture => platform.is('cordova') ? new MediaCapture() : new MediaCaptureMock(), }, - { - provide: Network, - deps: [Platform], - useFactory: (platform: Platform): Network => platform.is('cordova') ? new Network() : new NetworkMock(), - }, + CoreNetworkService, Push, QRScanner, SplashScreen, diff --git a/src/core/features/emulator/services/network.ts b/src/core/features/emulator/services/network.ts deleted file mode 100644 index cca7dab97..000000000 --- a/src/core/features/emulator/services/network.ts +++ /dev/null @@ -1,81 +0,0 @@ -// (C) Copyright 2015 Moodle Pty Ltd. -// -// 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 { Network } from '@ionic-native/network/ngx'; -import { Observable, Subject, merge } from 'rxjs'; - -/** - * Emulates the Cordova Network plugin in browser. - */ -@Injectable() -export class NetworkMock extends Network { - - type!: string; - - protected connectObservable = new Subject<'connected'>(); - protected disconnectObservable = new Subject<'disconnected'>(); - - constructor() { - super(); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ( window).Connection = { - UNKNOWN: 'unknown', // eslint-disable-line @typescript-eslint/naming-convention - ETHERNET: 'ethernet', // eslint-disable-line @typescript-eslint/naming-convention - WIFI: 'wifi', // eslint-disable-line @typescript-eslint/naming-convention - CELL_2G: '2g', // eslint-disable-line @typescript-eslint/naming-convention - CELL_3G: '3g', // eslint-disable-line @typescript-eslint/naming-convention - CELL_4G: '4g', // eslint-disable-line @typescript-eslint/naming-convention - CELL: 'cellular', // eslint-disable-line @typescript-eslint/naming-convention - NONE: 'none', // eslint-disable-line @typescript-eslint/naming-convention - }; - - window.addEventListener('online', () => { - this.connectObservable.next('connected'); - }, false); - - window.addEventListener('offline', () => { - this.disconnectObservable.next('disconnected'); - }, false); - } - - /** - * Returns an observable to watch connection changes. - * - * @return Observable. - */ - onChange(): Observable<'connected' | 'disconnected'> { - return merge(this.connectObservable, this.disconnectObservable); - } - - /** - * Returns an observable to notify when the app is connected. - * - * @return Observable. - */ - onConnect(): Observable<'connected'> { - return this.connectObservable; - } - - /** - * Returns an observable to notify when the app is disconnected. - * - * @return Observable. - */ - onDisconnect(): Observable<'disconnected'> { - return this.disconnectObservable; - } - -} diff --git a/src/core/features/settings/pages/deviceinfo/deviceinfo.ts b/src/core/features/settings/pages/deviceinfo/deviceinfo.ts index 397d8542c..cae87a52d 100644 --- a/src/core/features/settings/pages/deviceinfo/deviceinfo.ts +++ b/src/core/features/settings/pages/deviceinfo/deviceinfo.ts @@ -16,7 +16,7 @@ import { CoreApp } from '@services/app'; import { Component, OnDestroy } from '@angular/core'; import { CoreConstants } from '@/core/constants'; import { CoreLocalNotifications } from '@services/local-notifications'; -import { Device, Platform, Translate, Network, NgZone } from '@singletons'; +import { Device, Platform, Translate, NgZone } from '@singletons'; import { CoreLang } from '@services/lang'; import { CoreFile } from '@services/file'; import { CoreSites } from '@services/sites'; @@ -82,7 +82,6 @@ export class CoreSettingsDeviceInfoPage implements OnDestroy { protected onlineObserver?: Subscription; constructor() { - const appProvider = CoreApp.instance; const sitesProvider = CoreSites.instance; const device = Device.instance; const translate = Translate.instance; @@ -112,10 +111,10 @@ export class CoreSettingsDeviceInfoPage implements OnDestroy { if (CorePlatform.isMobile()) { this.deviceInfo.deviceType = Platform.is('tablet') ? 'tablet' : 'phone'; - if (appProvider.isAndroid()) { + if (CoreApp.isAndroid()) { this.deviceInfo.deviceOs = 'android'; this.deviceOsTranslated = 'Android'; - } else if (appProvider.isIOS()) { + } else if (CoreApp.isIOS()) { this.deviceInfo.deviceOs = 'ios'; this.deviceOsTranslated = 'iOS'; } else { @@ -177,7 +176,7 @@ export class CoreSettingsDeviceInfoPage implements OnDestroy { this.deviceInfo.siteVersion = currentSite?.getInfo()?.release; // Refresh online status when changes. - this.onlineObserver = Network.onChange().subscribe(() => { + this.onlineObserver = CoreNetwork.onChange().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { this.deviceInfo.networkStatus = CoreNetwork.isOnline() ? 'online' : 'offline'; diff --git a/src/core/initializers/watch-network.ts b/src/core/initializers/watch-network.ts index ee867a42e..9d8aabf5f 100644 --- a/src/core/initializers/watch-network.ts +++ b/src/core/initializers/watch-network.ts @@ -13,11 +13,12 @@ // limitations under the License. import { CoreCronDelegate } from '@services/cron'; -import { Network, NgZone } from '@singletons'; +import { NgZone } from '@singletons'; +import { CoreNetwork } from '@services/network'; export default function(): void { // When the app is re-connected, start network handlers that were stopped. - Network.onConnect().subscribe(() => { + CoreNetwork.onConnect().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => CoreCronDelegate.startNetworkHandlers()); }); diff --git a/src/core/services/filepool.ts b/src/core/services/filepool.ts index 3de5be814..d954aff62 100644 --- a/src/core/services/filepool.ts +++ b/src/core/services/filepool.ts @@ -31,7 +31,7 @@ import { CoreUtils, CoreUtilsOpenFileOptions } from '@services/utils/utils'; import { SQLiteDB } from '@classes/sqlitedb'; import { CoreError } from '@classes/errors/error'; import { CoreConstants } from '@/core/constants'; -import { ApplicationInit, makeSingleton, Network, NgZone, Translate } from '@singletons'; +import { ApplicationInit, makeSingleton, NgZone, Translate } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { APP_SCHEMA, @@ -150,7 +150,7 @@ export class CoreFilepoolProvider { this.checkQueueProcessing(); // Start queue when device goes online. - Network.onConnect().subscribe(() => { + CoreNetwork.onConnect().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => this.checkQueueProcessing()); }); diff --git a/src/core/services/network.ts b/src/core/services/network.ts index 7673e2007..d400f4fb0 100644 --- a/src/core/services/network.ts +++ b/src/core/services/network.ts @@ -14,15 +14,56 @@ import { Injectable } from '@angular/core'; import { CorePlatform } from '@services/platform'; -import { makeSingleton, Network } from '@singletons'; +import { Network as NetworkService } from '@ionic-native/network/ngx'; +import { makeSingleton } from '@singletons'; +import { Observable, Subject, merge } from 'rxjs'; + +const Network = makeSingleton(NetworkService); /** - * Service to manage network information. + * Service to manage network connections. */ @Injectable({ providedIn: 'root' }) -export class CoreNetworkService { +export class CoreNetworkService extends NetworkService { + type!: string; + + protected connectObservable = new Subject<'connected'>(); + protected disconnectObservable = new Subject<'disconnected'>(); protected forceOffline = false; + protected online = false; + + constructor() { + super(); + + this.checkOnline(); + + if (CorePlatform.isMobile()) { + Network.onChange().subscribe(() => { + this.fireObservable(); + }); + } else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ( window).Connection = { + UNKNOWN: 'unknown', // eslint-disable-line @typescript-eslint/naming-convention + ETHERNET: 'ethernet', // eslint-disable-line @typescript-eslint/naming-convention + WIFI: 'wifi', // eslint-disable-line @typescript-eslint/naming-convention + CELL_2G: '2g', // eslint-disable-line @typescript-eslint/naming-convention + CELL_3G: '3g', // eslint-disable-line @typescript-eslint/naming-convention + CELL_4G: '4g', // eslint-disable-line @typescript-eslint/naming-convention + CELL: 'cellular', // eslint-disable-line @typescript-eslint/naming-convention + NONE: 'none', // eslint-disable-line @typescript-eslint/naming-convention + }; + + window.addEventListener('online', () => { + this.fireObservable(); + }, false); + + window.addEventListener('offline', () => { + this.fireObservable(); + }, false); + } + } /** * Set value of forceOffline flag. If true, the app will think the device is offline. @@ -31,6 +72,7 @@ export class CoreNetworkService { */ setForceOffline(value: boolean): void { this.forceOffline = !!value; + this.fireObservable(); } /** @@ -39,23 +81,77 @@ export class CoreNetworkService { * @return Whether the app is online. */ isOnline(): boolean { + return this.online; + } + + /** + * Returns whether we are online. + * + * @return Whether the app is online. + */ + checkOnline(): void { if (this.forceOffline) { - return false; + this.online = false; + + return; } if (!CorePlatform.isMobile()) { - return navigator.onLine; + this.online = navigator.onLine; + + return; } - let online = Network.type !== null && Network.type != Network.Connection.NONE && - Network.type != Network.Connection.UNKNOWN; + let online = this.type !== null && this.type != this.Connection.NONE && + this.type != this.Connection.UNKNOWN; // Double check we are not online because we cannot rely 100% in Cordova APIs. if (!online && navigator.onLine) { online = true; } - return online; + this.online = online; + } + + /** + * Returns an observable to watch connection changes. + * + * @return Observable. + */ + onChange(): Observable<'connected' | 'disconnected'> { + return merge(this.connectObservable, this.disconnectObservable); + } + + /** + * Returns an observable to notify when the app is connected. + * + * @return Observable. + */ + onConnect(): Observable<'connected'> { + return this.connectObservable; + } + + /** + * Returns an observable to notify when the app is disconnected. + * + * @return Observable. + */ + onDisconnect(): Observable<'disconnected'> { + return this.disconnectObservable; + } + + /** + * Fires the correct observable depending on the connection status. + */ + protected fireObservable(): void { + const previousOnline = this.online; + + this.checkOnline(); + if (this.online && !previousOnline) { + this.connectObservable.next('connected'); + } else if (!this.online && previousOnline) { + this.disconnectObservable.next('disconnected'); + } } /** diff --git a/src/core/services/utils/iframe.ts b/src/core/services/utils/iframe.ts index 2cbd83068..5b46db3c9 100644 --- a/src/core/services/utils/iframe.ts +++ b/src/core/services/utils/iframe.ts @@ -25,7 +25,7 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreUtils } from '@services/utils/utils'; -import { makeSingleton, Network, NgZone, Translate, Diagnostic } from '@singletons'; +import { makeSingleton, NgZone, Translate, Diagnostic } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreUrl } from '@singletons/url'; import { CoreWindow } from '@singletons/window'; @@ -76,7 +76,7 @@ export class CoreIframeUtilsProvider { this.addOfflineWarning(element, src, isSubframe); // If the network changes, check it again. - const subscription = Network.onConnect().subscribe(() => { + const subscription = CoreNetwork.onConnect().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { if (!this.checkOnlineFrameInOffline(element, isSubframe)) { diff --git a/src/core/singletons/index.ts b/src/core/singletons/index.ts index 048dba0c6..695442589 100644 --- a/src/core/singletons/index.ts +++ b/src/core/singletons/index.ts @@ -187,6 +187,9 @@ export const LocalNotifications = makeSingleton(LocalNotificationsService); export const Media = makeSingleton(MediaService); export const MediaCapture = makeSingleton(MediaCaptureService); export const NativeHttp = makeSingleton(HTTP); +/** + * @deprecated on 4.1 use CoreNetwork instead. + */ export const Network = makeSingleton(NetworkService); export const Push = makeSingleton(PushService); export const QRScanner = makeSingleton(QRScannerService); diff --git a/src/testing/utils.ts b/src/testing/utils.ts index 4b9091735..3a097db93 100644 --- a/src/testing/utils.ts +++ b/src/testing/utils.ts @@ -19,11 +19,12 @@ import { Observable, Subject } from 'rxjs'; import { sep } from 'path'; import { CORE_SITE_SCHEMAS } from '@services/sites'; -import { CoreSingletonProxy, Network, Platform, Translate } from '@singletons'; +import { CoreSingletonProxy, Platform, Translate } from '@singletons'; import { CoreTextUtilsProvider } from '@services/utils/text'; import { TranslatePipeStub } from './stubs/pipes/translate'; import { CoreExternalContentDirectiveStub } from './stubs/directives/core-external-content'; +import { CoreNetwork } from '@services/network'; abstract class WrapperComponent { @@ -37,7 +38,7 @@ let testBedInitialized = false; const textUtils = new CoreTextUtilsProvider(); const DEFAULT_SERVICE_SINGLETON_MOCKS: [CoreSingletonProxy, Record][] = [ [Platform, mock({ is: () => false, ready: () => Promise.resolve(), resume: new Subject() })], - [Network, { onChange: () => new Observable() }], + [CoreNetwork, { onChange: () => new Observable() }], ]; async function renderAngularComponent(component: Type, config: RenderConfig): Promise> {