From d469470592f9d648d66672d52dd84b05ef0465df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Espino=20Garc=C3=ADa?= Date: Mon, 4 Dec 2023 17:01:08 +0100 Subject: [PATCH] Make app init more idempotent (#7676) * Make app init more idempotent * Remove previous subscriptions --- app/init/app.ts | 26 ++++++++------------------ app/init/push_notifications.ts | 14 +++++++++----- app/managers/websocket_manager.ts | 4 ++++ app/screens/navigation.ts | 14 +++++++++----- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/app/init/app.ts b/app/init/app.ts index e04fc54c6..9f690b5b1 100644 --- a/app/init/app.ts +++ b/app/init/app.ts @@ -19,10 +19,6 @@ import NavigationStore from '@store/navigation_store'; // or on the Share Extension, for example. let baseAppInitialized = false; -// Controls whether the app initialization (websockets, screen listeners, etc...) is done, mainly -// on app launch -let mainAppInitialized = false; - let serverCredentials: ServerCredential[]; // Fallback Polyfill for Promise.allSettle @@ -55,25 +51,19 @@ export async function initialize() { } export async function start() { - if (baseAppInitialized) { - // Clean relevant information on ephemeral stores - NavigationStore.reset(); - EphemeralStore.setCurrentThreadId(''); - EphemeralStore.setProcessingNotification(''); - } + // Clean relevant information on ephemeral stores + NavigationStore.reset(); + EphemeralStore.setCurrentThreadId(''); + EphemeralStore.setProcessingNotification(''); await initialize(); - if (!mainAppInitialized) { - mainAppInitialized = true; + PushNotifications.init(serverCredentials.length > 0); - PushNotifications.init(serverCredentials.length > 0); + registerNavigationListeners(); + registerScreens(); - registerNavigationListeners(); - registerScreens(); - - await WebsocketManager.init(serverCredentials); - } + await WebsocketManager.init(serverCredentials); initialLaunch(); } diff --git a/app/init/push_notifications.ts b/app/init/push_notifications.ts index f713d4f47..1dcc332d7 100644 --- a/app/init/push_notifications.ts +++ b/app/init/push_notifications.ts @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {AppState, DeviceEventEmitter, Platform} from 'react-native'; +import {AppState, DeviceEventEmitter, Platform, type EmitterSubscription} from 'react-native'; import { Notification, NotificationAction, @@ -36,12 +36,16 @@ import {convertToNotificationData} from '@utils/notification'; class PushNotifications { configured = false; + subscriptions?: EmitterSubscription[]; init(register: boolean) { - Notifications.events().registerNotificationOpened(this.onNotificationOpened); - Notifications.events().registerRemoteNotificationsRegistered(this.onRemoteNotificationsRegistered); - Notifications.events().registerNotificationReceivedBackground(this.onNotificationReceivedBackground); - Notifications.events().registerNotificationReceivedForeground(this.onNotificationReceivedForeground); + this.subscriptions?.forEach((v) => v.remove()); + this.subscriptions = [ + Notifications.events().registerNotificationOpened(this.onNotificationOpened), + Notifications.events().registerRemoteNotificationsRegistered(this.onRemoteNotificationsRegistered), + Notifications.events().registerNotificationReceivedBackground(this.onNotificationReceivedBackground), + Notifications.events().registerNotificationReceivedForeground(this.onNotificationReceivedForeground), + ]; if (register) { this.registerIfNeeded(); diff --git a/app/managers/websocket_manager.ts b/app/managers/websocket_manager.ts index f499468f6..c86f5ddb9 100644 --- a/app/managers/websocket_manager.ts +++ b/app/managers/websocket_manager.ts @@ -70,6 +70,10 @@ class WebsocketManager { }; public createClient = (serverUrl: string, bearerToken: string, storedLastDisconnect = 0) => { + if (this.clients[serverUrl]) { + this.invalidateClient(serverUrl); + } + const client = new WebSocketClient(serverUrl, bearerToken, storedLastDisconnect); client.setFirstConnectCallback(() => this.onFirstConnect(serverUrl)); diff --git a/app/screens/navigation.ts b/app/screens/navigation.ts index 17d113645..eabfdc751 100644 --- a/app/screens/navigation.ts +++ b/app/screens/navigation.ts @@ -4,8 +4,8 @@ /* eslint-disable max-lines */ import merge from 'deepmerge'; -import {Appearance, DeviceEventEmitter, NativeModules, StatusBar, Platform, Alert} from 'react-native'; -import {type ComponentWillAppearEvent, type ImageResource, type LayoutOrientation, Navigation, type Options, OptionsModalPresentationStyle, type OptionsTopBarButton, type ScreenPoppedEvent} from 'react-native-navigation'; +import {Appearance, DeviceEventEmitter, NativeModules, StatusBar, Platform, Alert, type EmitterSubscription} from 'react-native'; +import {type ComponentWillAppearEvent, type ImageResource, type LayoutOrientation, Navigation, type Options, OptionsModalPresentationStyle, type OptionsTopBarButton, type ScreenPoppedEvent, type EventSubscription} from 'react-native-navigation'; import tinyColor from 'tinycolor2'; import CompassIcon from '@components/compass_icon'; @@ -30,14 +30,18 @@ const alpha = { to: 1, duration: 150, }; +let subscriptions: Array | undefined; export const allOrientations: LayoutOrientation[] = ['sensor', 'sensorLandscape', 'sensorPortrait', 'landscape', 'portrait']; export const portraitOrientation: LayoutOrientation[] = ['portrait']; export function registerNavigationListeners() { - Navigation.events().registerScreenPoppedListener(onPoppedListener); - Navigation.events().registerCommandListener(onCommandListener); - Navigation.events().registerComponentWillAppearListener(onScreenWillAppear); + subscriptions?.forEach((v) => v.remove()); + subscriptions = [ + Navigation.events().registerScreenPoppedListener(onPoppedListener), + Navigation.events().registerCommandListener(onCommandListener), + Navigation.events().registerComponentWillAppearListener(onScreenWillAppear), + ]; } function onCommandListener(name: string, params: any) {