mirror of
https://github.com/mattermost/mattermost-mobile.git
synced 2026-11-05 02:18:56 +00:00
* perf: skip Android Keystore listing on cold start Open the app DB first and decrypt credentials only for known server URLs so logged-in launches no longer enumerate every generic-password service. Co-authored-by: Cursor <cursoragent@cursor.com> * perf: load server credentials in one parallel pass Drop the extra preauth Set and second keystore probe so cold start decrypts each known URL once, and read active servers from the existing query. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: retry failed startup and cache credentials only after Keychain writes Reset base initialization so a rejected launch can retry, and keep the in-memory credential cache aligned with successful secure-storage writes. Co-authored-by: Cursor <cursoragent@cursor.com> * test: drop mock-harness init tests and unused session cache The initialize() retry test only asserted mock wiring. Remove leftover hasCachedCredentials/session_cache APIs from closed stack floors, and keep credential tests that lock listing-skip and cache behavior. Co-authored-by: Cursor <cursoragent@cursor.com> * chore: drop leftover launch profiler instrumentation Cold-start timing marks were debug logInfo breadcrumbs, not part of the Keystore skip. Co-authored-by: Cursor <cursoragent@cursor.com> * test: assert empty known-URL fallback still returns credentials Listing-called alone would miss a path that enumerates Keystore then drops the results. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
90 lines
3.2 KiB
TypeScript
90 lines
3.2 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import {CallsManager} from '@calls/calls_manager';
|
|
import DatabaseManager from '@database/manager';
|
|
import CallsNative from '@init/calls_native';
|
|
import {getAllServerCredentials} from '@init/credentials';
|
|
import ManagedApp from '@init/managed_app';
|
|
import PushNotifications from '@init/push_notifications';
|
|
import EphemeralModeManager from '@managers/ephemeral_mode_manager';
|
|
import GlobalEventHandler from '@managers/global_event_handler';
|
|
import NetworkManager from '@managers/network_manager';
|
|
import SecurityManager from '@managers/security_manager';
|
|
import SessionAttributesManager from '@managers/session_attributes_manager';
|
|
import SessionManager from '@managers/session_manager';
|
|
import WebsocketManager from '@managers/websocket_manager';
|
|
import {queryAllActiveServers} from '@queries/app/servers';
|
|
import EphemeralStore from '@store/ephemeral_store';
|
|
import {NavigationStore} from '@store/navigation_store';
|
|
|
|
// Controls whether the main initialization (database, etc...) is done, either on app launch
|
|
// or on the Share Extension, for example.
|
|
let baseAppInitialized = false;
|
|
let serverCredentials: ServerCredential[] = [];
|
|
|
|
// Fallback Polyfill for Promise.allSettle
|
|
Promise.allSettled = Promise.allSettled || (<T>(promises: Array<Promise<T>>) => Promise.all(
|
|
promises.map((p) => p.
|
|
then((value) => ({
|
|
status: 'fulfilled',
|
|
value,
|
|
})).
|
|
catch((reason) => ({
|
|
status: 'rejected',
|
|
reason,
|
|
})),
|
|
),
|
|
));
|
|
|
|
export async function initialize() {
|
|
if (!baseAppInitialized) {
|
|
baseAppInitialized = true;
|
|
try {
|
|
await DatabaseManager.initAppDatabase();
|
|
|
|
// Keystore entries with no matching active DB row are skipped (accepted vs listing every service).
|
|
const activeUrls = (await queryAllActiveServers()?.fetch() ?? []).map((s) => s.url);
|
|
serverCredentials = await getAllServerCredentials(activeUrls);
|
|
|
|
await DatabaseManager.initServerDatabases(serverCredentials.map((c) => c.serverUrl));
|
|
await NetworkManager.init(serverCredentials);
|
|
|
|
// EphemeralModeManager init runs before WS init so any pending wipes
|
|
// complete before WebSocket clients start populating server databases.
|
|
await EphemeralModeManager.init(serverCredentials);
|
|
await WebsocketManager.init(serverCredentials);
|
|
} catch (error) {
|
|
baseAppInitialized = false;
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
NavigationStore.reset();
|
|
EphemeralStore.setCurrentThreadId('');
|
|
EphemeralStore.setProcessingNotification('');
|
|
|
|
await SecurityManager.init();
|
|
|
|
await SessionAttributesManager.syncStaticValues();
|
|
|
|
GlobalEventHandler.init();
|
|
ManagedApp.init();
|
|
SessionManager.init();
|
|
CallsManager.initialize();
|
|
CallsNative.init();
|
|
|
|
PushNotifications.init(serverCredentials.length > 0);
|
|
}
|
|
|
|
export function cleanup() {
|
|
ManagedApp.cleanup();
|
|
GlobalEventHandler.cleanup();
|
|
SecurityManager.cleanup();
|
|
SessionManager.cleanup();
|
|
CallsManager.cleanup();
|
|
CallsNative.cleanup();
|
|
PushNotifications.cleanup();
|
|
EphemeralModeManager.cleanup();
|
|
}
|