From 1f3d72cfbb797652d0807b899f49ee8aad9f6343 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 9 May 2023 16:24:31 +0200 Subject: [PATCH] MOBILE-4270 messages: Decrease chances of offline messages duplicated This is because Android seems to duplicate the request if the type of connection changes while the request is done. E.g. when leaving flight mode the device could connect to mobile data first and then to WiFi. --- src/addons/messages/messages.module.ts | 2 +- src/core/initializers/watch-network.ts | 5 ++++- src/core/services/filepool.ts | 2 +- src/core/services/network.ts | 19 +++++++++++++++++++ src/core/services/utils/iframe.ts | 2 +- 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/addons/messages/messages.module.ts b/src/addons/messages/messages.module.ts index c6579af46..9f7748ff0 100644 --- a/src/addons/messages/messages.module.ts +++ b/src/addons/messages/messages.module.ts @@ -87,7 +87,7 @@ const preferencesRoutes: Routes = [ CoreUserDelegate.registerHandler(AddonMessagesSendMessageUserHandler.instance); // Sync some discussions when device goes online. - CoreNetwork.onConnect().subscribe(() => { + CoreNetwork.onConnectShouldBeStable().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/core/initializers/watch-network.ts b/src/core/initializers/watch-network.ts index 9d8aabf5f..74c6a0261 100644 --- a/src/core/initializers/watch-network.ts +++ b/src/core/initializers/watch-network.ts @@ -16,9 +16,12 @@ import { CoreCronDelegate } from '@services/cron'; import { NgZone } from '@singletons'; import { CoreNetwork } from '@services/network'; +/** + * Initializer function. + */ export default function(): void { // When the app is re-connected, start network handlers that were stopped. - CoreNetwork.onConnect().subscribe(() => { + CoreNetwork.onConnectShouldBeStable().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 1751636f0..3c633823a 100644 --- a/src/core/services/filepool.ts +++ b/src/core/services/filepool.ts @@ -150,7 +150,7 @@ export class CoreFilepoolProvider { this.checkQueueProcessing(); // Start queue when device goes online. - CoreNetwork.onConnect().subscribe(() => { + CoreNetwork.onConnectShouldBeStable().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 aeb49a4ae..b50a87601 100644 --- a/src/core/services/network.ts +++ b/src/core/services/network.ts @@ -38,9 +38,11 @@ export class CoreNetworkService extends Network { type!: string; protected connectObservable = new Subject<'connected'>(); + protected connectStableObservable = new Subject<'connected'>(); protected disconnectObservable = new Subject<'disconnected'>(); protected forceConnectionMode?: CoreNetworkConnection; protected online = false; + protected connectStableTimeout?: number; get connectionType(): CoreNetworkConnection { if (this.forceConnectionMode !== undefined) { @@ -146,6 +148,7 @@ export class CoreNetworkService extends Network { /** * Returns an observable to notify when the app is connected. * It will also be fired when connection type changes. + * If you're going to perform network requests once the device is connected, please use onConnectShouldBeStable instead. * * @returns Observable. */ @@ -153,6 +156,18 @@ export class CoreNetworkService extends Network { return this.connectObservable; } + /** + * Returns an observable to notify when the app is connected and it should already be a stable a connection. + * E.g. when leaving flight mode the device could connect to mobile network first and then to WiFi. + * If you're going to perform network requests once the device is connected, it's recommended to use this function instead of + * onConnect because some OS (e.g. Android) duplicate a request if the type of connection changes while the request is done. + * + * @returns Observable. + */ + onConnectShouldBeStable(): Observable<'connected'> { + return this.connectStableObservable; + } + /** * Returns an observable to notify when the app is disconnected. * @@ -166,10 +181,14 @@ export class CoreNetworkService extends Network { * Fires the correct observable depending on the connection status. */ protected fireObservable(): void { + clearTimeout(this.connectStableTimeout); this.checkOnline(); if (this.online) { this.connectObservable.next('connected'); + this.connectStableTimeout = window.setTimeout(() => { + this.connectStableObservable.next('connected'); + }, 5000); } else { this.disconnectObservable.next('disconnected'); } diff --git a/src/core/services/utils/iframe.ts b/src/core/services/utils/iframe.ts index 3314fc8dc..a35d72194 100644 --- a/src/core/services/utils/iframe.ts +++ b/src/core/services/utils/iframe.ts @@ -76,7 +76,7 @@ export class CoreIframeUtilsProvider { this.addOfflineWarning(element, src, isSubframe); // If the network changes, check it again. - const subscription = CoreNetwork.onConnect().subscribe(() => { + const subscription = CoreNetwork.onConnectShouldBeStable().subscribe(() => { // Execute the callback in the Angular zone, so change detection doesn't stop working. NgZone.run(() => { if (!this.checkOnlineFrameInOffline(element, isSubframe)) {