Skip to content

Commit 1d7af8b

Browse files
committed
Fix iOS cold-launch splash stall
Remove initData() from the critical startup path — it only spawns background price/fee fetches and is not needed for first render. Fire it in a detached Task instead so app/auth are set immediately after bootstrap, preventing the splash from getting stuck if the FFI async boundary stalls. Add slow-startup feedback ("Taking longer than expected...") to the splash screen after 10 seconds. Add granular info!() logging to Rust bootstrap steps for diagnostics.
1 parent 0366f4d commit 1d7af8b

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

ios/Cove/CoveApp.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,14 @@ struct CoveApp: App {
6060
.task {
6161
do {
6262
let warning = try await bootstrap()
63-
self.app = AppManager.shared
64-
await self.app?.rust.initData()
65-
self.app?.asyncRuntimeReady = true
63+
64+
let appManager = AppManager.shared
65+
appManager.asyncRuntimeReady = true
66+
self.app = appManager
6667
self.auth = AuthManager.shared
6768
self.bdkMigrationWarning = warning
69+
70+
Task { await appManager.rust.initData() }
6871
} catch {
6972
bootstrapError = error.localizedDescription
7073
}

ios/Cove/CoverView.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ private struct StorageErrorView: View {
5050

5151
private struct SplashLoadingView: View {
5252
@State private var showSpinner = false
53+
@State private var showSlowMessage = false
5354

5455
var body: some View {
5556
VStack(spacing: 24) {
@@ -63,11 +64,22 @@ private struct SplashLoadingView: View {
6364
ProgressView()
6465
.tint(.white)
6566
}
67+
68+
if showSlowMessage {
69+
Text("Taking longer than expected...")
70+
.font(.subheadline)
71+
.foregroundColor(.white.opacity(0.6))
72+
.transition(.opacity)
73+
}
6674
}
6775
.task {
6876
try? await Task.sleep(for: .milliseconds(CoverView.spinnerDelayMs))
6977
showSpinner = true
7078
}
79+
.task {
80+
try? await Task.sleep(for: .seconds(10))
81+
withAnimation { showSlowMessage = true }
82+
}
7183
}
7284
}
7385

rust/src/bootstrap.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ use tracing::{error, info};
1313
#[uniffi::export(async_runtime = "tokio")]
1414
pub async fn bootstrap() -> Result<Option<String>, AppInitError> {
1515
cove_tokio::init();
16+
info!("Bootstrap: tokio initialized, starting blocking work");
17+
1618
cove_tokio::unblock::run_blocking(|| {
1719
// critical bootstrap (cached via OnceLock)
1820
ensure_storage_bootstrapped()?;
21+
info!("Bootstrap: storage bootstrapped, attempting BDK migration");
1922

2023
// BDK migration (not cached — retries every launch)
2124
let warning = match attempt_bdk_migration() {
@@ -27,6 +30,7 @@ pub async fn bootstrap() -> Result<Option<String>, AppInitError> {
2730
}
2831
};
2932

33+
info!("Bootstrap: blocking work complete");
3034
Ok(warning)
3135
})
3236
.await
@@ -91,12 +95,15 @@ fn do_bootstrap() -> Result<(), AppInitError> {
9195
info!("Encryption key derived and set");
9296

9397
// recover interrupted redb migrations then migrate plaintext → encrypted
98+
info!("Recovering interrupted redb migrations");
9499
crate::database::migration::recover_interrupted_migrations()
95100
.map_err_display_alt(AppInitError::MainDatabaseMigration)?;
96101

102+
info!("Migrating main database if needed");
97103
crate::database::migration::migrate_main_database_if_needed()
98104
.map_err_display_alt(AppInitError::MainDatabaseMigration)?;
99105

106+
info!("Migrating wallet databases if needed");
100107
crate::database::migration::migrate_wallet_databases_if_needed()
101108
.map_err_display_alt(AppInitError::WalletDatabaseMigration)?;
102109

0 commit comments

Comments
 (0)