210 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			210 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| // (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 { CorePlatform } from '@services/platform';
 | |
| import { Network } from '@ionic-native/network/ngx';
 | |
| import { makeSingleton } from '@singletons';
 | |
| import { Observable, Subject, merge } from 'rxjs';
 | |
| 
 | |
| export enum CoreNetworkConnection {
 | |
|     UNKNOWN = 'unknown',
 | |
|     ETHERNET = 'ethernet',
 | |
|     WIFI = 'wifi',
 | |
|     CELL_2G = '2g',
 | |
|     CELL_3G = '3g',
 | |
|     CELL_4G = '4g',
 | |
|     CELL = 'cellular',
 | |
|     NONE = 'none',
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Service to manage network connections.
 | |
|  */
 | |
| @Injectable({ providedIn: 'root' })
 | |
| export class CoreNetworkService extends Network {
 | |
| 
 | |
|     type!: string;
 | |
| 
 | |
|     protected connectObservable = new Subject<'connected'>();
 | |
|     protected disconnectObservable = new Subject<'disconnected'>();
 | |
|     protected forceConnectionMode?: CoreNetworkConnection;
 | |
|     protected online = false;
 | |
| 
 | |
|     get connectionType(): CoreNetworkConnection {
 | |
|         if (this.forceConnectionMode !== undefined) {
 | |
|             return this.forceConnectionMode;
 | |
|         }
 | |
| 
 | |
|         if (CorePlatform.isMobile()) {
 | |
|             return this.type as CoreNetworkConnection;
 | |
|         }
 | |
| 
 | |
|         return  this.online ? CoreNetworkConnection.WIFI : CoreNetworkConnection.NONE;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Initialize the service.
 | |
|      */
 | |
|     initialize(): void {
 | |
|         this.checkOnline();
 | |
| 
 | |
|         if (CorePlatform.isMobile()) {
 | |
|             // We cannot directly listen to onChange because it depends on
 | |
|             // onConnect and onDisconnect that have been already overriden.
 | |
|             super.onConnect().subscribe(() => {
 | |
|                 this.fireObservable();
 | |
|             });
 | |
|             super.onDisconnect().subscribe(() => {
 | |
|                 this.fireObservable();
 | |
|             });
 | |
|         } else {
 | |
|             // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | |
|             (<any> window).Connection = {
 | |
|                 UNKNOWN: CoreNetworkConnection.UNKNOWN, // eslint-disable-line @typescript-eslint/naming-convention
 | |
|                 ETHERNET: CoreNetworkConnection.ETHERNET, // eslint-disable-line @typescript-eslint/naming-convention
 | |
|                 WIFI: CoreNetworkConnection.WIFI, // eslint-disable-line @typescript-eslint/naming-convention
 | |
|                 CELL_2G: CoreNetworkConnection.CELL_2G, // eslint-disable-line @typescript-eslint/naming-convention
 | |
|                 CELL_3G: CoreNetworkConnection.CELL_3G, // eslint-disable-line @typescript-eslint/naming-convention
 | |
|                 CELL_4G: CoreNetworkConnection.CELL_4G, // eslint-disable-line @typescript-eslint/naming-convention
 | |
|                 CELL: CoreNetworkConnection.CELL, // eslint-disable-line @typescript-eslint/naming-convention
 | |
|                 NONE: CoreNetworkConnection.NONE, // eslint-disable-line @typescript-eslint/naming-convention
 | |
|             };
 | |
| 
 | |
|             window.addEventListener('online', () => {
 | |
|                 this.fireObservable();
 | |
|             }, false);
 | |
| 
 | |
|             window.addEventListener('offline', () => {
 | |
|                 this.fireObservable();
 | |
|             }, false);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set value of forceConnectionMode flag.
 | |
|      * The app will think the device is offline or limited connection.
 | |
|      *
 | |
|      * @param value Value to set.
 | |
|      */
 | |
|     setForceConnectionMode(value: CoreNetworkConnection): void {
 | |
|         this.forceConnectionMode = value;
 | |
|         this.fireObservable();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns whether we are online.
 | |
|      *
 | |
|      * @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.forceConnectionMode === CoreNetworkConnection.NONE) {
 | |
|             this.online = false;
 | |
| 
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         const type = this.connectionType;
 | |
| 
 | |
|         let online = type !== null && type !== CoreNetworkConnection.NONE && type !== CoreNetworkConnection.UNKNOWN;
 | |
| 
 | |
|         // Double check we are not online because we cannot rely 100% in Cordova APIs.
 | |
|         if (!online && navigator.onLine) {
 | |
|             online = true;
 | |
|         }
 | |
| 
 | |
|         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.
 | |
|      * It will also be fired when connection type changes.
 | |
|      *
 | |
|      * @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 {
 | |
|         this.checkOnline();
 | |
| 
 | |
|         if (this.online) {
 | |
|             this.connectObservable.next('connected');
 | |
|         } else {
 | |
|             this.disconnectObservable.next('disconnected');
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Check if device uses a limited connection.
 | |
|      *
 | |
|      * @return Whether the device uses a limited connection.
 | |
|      */
 | |
|     isNetworkAccessLimited(): boolean {
 | |
|         const limited: CoreNetworkConnection[] = [
 | |
|             CoreNetworkConnection.CELL_2G,
 | |
|             CoreNetworkConnection.CELL_3G,
 | |
|             CoreNetworkConnection.CELL_4G,
 | |
|             CoreNetworkConnection.CELL,
 | |
|         ];
 | |
| 
 | |
|         const type = this.connectionType;
 | |
| 
 | |
|         return limited.indexOf(type) > -1;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Check if device uses a wifi connection.
 | |
|      *
 | |
|      * @return Whether the device uses a wifi connection.
 | |
|      */
 | |
|     isWifi(): boolean {
 | |
|         return this.isOnline() && !this.isNetworkAccessLimited();
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| export const CoreNetwork = makeSingleton(CoreNetworkService);
 |