2022-07-12 16:01:51 +02:00

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);