diff --git a/app/managers/websocket_manager.ts b/app/managers/websocket_manager.ts index 1a3538525..f26913595 100644 --- a/app/managers/websocket_manager.ts +++ b/app/managers/websocket_manager.ts @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import NetInfo, {type NetInfoState, type NetInfoSubscription} from '@react-native-community/netinfo'; +import NetInfo, {NetInfoStateType, type NetInfoState, type NetInfoSubscription} from '@react-native-community/netinfo'; import {AppState, type AppStateStatus, type NativeEventSubscription} from 'react-native'; import BackgroundTimer from 'react-native-background-timer'; import {BehaviorSubject} from 'rxjs'; @@ -30,6 +30,7 @@ class WebsocketManager { private connectionTimerIDs: Record = {}; private isBackgroundTimerRunning = false; private netConnected = false; + private netType: NetInfoStateType = NetInfoStateType.none; private previousActiveState: boolean; private statusUpdatesIntervalIDs: Record = {}; private backgroundIntervalId: number | undefined; @@ -43,7 +44,9 @@ class WebsocketManager { } public init = async (serverCredentials: ServerCredential[]) => { - this.netConnected = Boolean((await NetInfo.fetch()).isConnected); + const netInfo = await NetInfo.fetch(); + this.netConnected = Boolean(netInfo.isConnected); + this.netType = netInfo.type; serverCredentials.forEach( ({serverUrl, token}) => { try { @@ -101,6 +104,7 @@ class WebsocketManager { for (const url of Object.keys(this.clients)) { const client = this.clients[url]; client.close(true); + client.invalidate(); this.getConnectedSubject(url).next('not_connected'); } }; @@ -227,35 +231,40 @@ class WebsocketManager { } const isActive = appState === 'active'; - this.handleStateChange(this.netConnected, isActive); + this.handleStateChange(this.netConnected, this.netType, isActive); }; private onNetStateChange = (netState: NetInfoState) => { const newState = Boolean(netState.isConnected); - if (this.netConnected === newState) { - return; - } - - this.handleStateChange(newState, this.previousActiveState); + this.handleStateChange(newState, netState.type, this.previousActiveState); }; - private handleStateChange = (currentIsConnected: boolean, currentIsActive: boolean) => { - if (currentIsActive === this.previousActiveState && currentIsConnected === this.netConnected) { + private handleStateChange = (currentIsConnected: boolean, currentNetType: NetInfoStateType, currentIsActive: boolean) => { + if (currentIsActive === this.previousActiveState && currentIsConnected === this.netConnected && currentNetType === this.netType) { return; } this.cancelConnectTimers(); const wentBackground = this.previousActiveState && !currentIsActive; + const switchedNetworks = currentIsConnected && currentNetType !== this.netType && this.netType !== 'none'; this.previousActiveState = currentIsActive; this.netConnected = currentIsConnected; + this.netType = currentNetType; if (!currentIsConnected) { this.closeAll(); return; } + if (switchedNetworks) { + // Close all connections when we switch from (for example) vpn to wifi + // to ensure we are using the right network and doesn't get stuck on + // retries. + this.closeAll(); + } + if (currentIsActive) { if (this.isBackgroundTimerRunning) { BackgroundTimer.clearInterval(this.backgroundIntervalId!); diff --git a/patches/@mattermost+react-native-network-client+1.6.0.patch b/patches/@mattermost+react-native-network-client+1.6.0.patch new file mode 100644 index 000000000..c79deaac2 --- /dev/null +++ b/patches/@mattermost+react-native-network-client+1.6.0.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/@mattermost/react-native-network-client/android/src/main/java/com/mattermost/networkclient/WebSocketClientModuleImpl.kt b/node_modules/@mattermost/react-native-network-client/android/src/main/java/com/mattermost/networkclient/WebSocketClientModuleImpl.kt +index 42f620b..d03cf08 100644 +--- a/node_modules/@mattermost/react-native-network-client/android/src/main/java/com/mattermost/networkclient/WebSocketClientModuleImpl.kt ++++ b/node_modules/@mattermost/react-native-network-client/android/src/main/java/com/mattermost/networkclient/WebSocketClientModuleImpl.kt +@@ -113,7 +113,7 @@ class WebSocketClientModuleImpl(reactApplicationContext: ReactApplicationContext + } + + try { +- clients[wsUri]!!.webSocket!!.close(1000, "manual") ++ clients[wsUri]!!.webSocket!!.cancel() + } catch (error: Exception) { + promise.reject(error) + }