Fix: Complete setup would sometimes get stuck
Some checks failed
Flutter analyze & test / flutter_analyze_and_test (push) Has been cancelled

This commit is contained in:
otsmr 2026-05-05 10:57:59 +02:00
parent dc044ee0d2
commit 8c15a95165
6 changed files with 76 additions and 40 deletions

View file

@ -2,7 +2,9 @@
## 0.2.9
- Improved: Make contact avatars clickable
- Fix: Messages occasionally not received until app restart
- Fix: Complete setup would sometimes get stuck
## 0.2.8

View file

@ -193,6 +193,21 @@ Future<void> postStartupTasks() async {
unawaited(finishStartedPreprocessing());
unawaited(createPushAvatars());
if (userService.currentUser.userDiscoveryInitializationError) {
unawaited(() async {
try {
await UserDiscoveryService.initializeOrUpdate(
threshold: userService.currentUser.userDiscoveryThreshold,
sharePromotion: userService.currentUser.userDiscoverySharePromotion,
);
} catch (e) {
Log.error(
'Failed to retry UserDiscovery initialization on startup: $e',
);
}
}());
}
await Future.delayed(const Duration(seconds: 10));
unawaited(initializeBackgroundTaskManager());
// 3. Delayed tasks (Wait for app to settle)

View file

@ -109,6 +109,9 @@ class UserData {
@JsonKey(defaultValue: true)
bool userDiscoverySharePromotion = true;
@JsonKey(defaultValue: false)
bool userDiscoveryInitializationError = false;
// -- Custom DATA --
@JsonKey(defaultValue: 100_000)

View file

@ -75,7 +75,6 @@ class UserDiscoveryService {
required int threshold,
required bool sharePromotion,
}) async {
try {
Log.info('UserDiscoveryService: initializeOrUpdate started');
final userId = userService.currentUser.userId;
final publicKey = await getUserPublicKey();
@ -85,7 +84,7 @@ class UserDiscoveryService {
userId: userId,
publicKey: publicKey,
sharePromotion: sharePromotion,
);
).timeout(const Duration(seconds: 8));
Log.info(
'UserDiscoveryService: Rust bridge initialized, updating UserService',
);
@ -93,12 +92,10 @@ class UserDiscoveryService {
(u) => u
..isUserDiscoveryEnabled = true
..userDiscoverySharePromotion = sharePromotion
..userDiscoveryThreshold = threshold,
..userDiscoveryThreshold = threshold
..userDiscoveryInitializationError = false,
);
Log.info('UserDiscoveryService: initializeOrUpdate finished');
} catch (e) {
Log.error('UserDiscoveryService: initializeOrUpdate error: $e');
}
}
static Future<Uint8List?> getCurrentVersion() async {

View file

@ -55,12 +55,20 @@ class UserDiscoverySetupState {
Future<bool> initializeOrUpdate() async {
try {
Log.info('UserDiscoverySetupState: initializeOrUpdate started');
var hasError = false;
if (isUserDiscoveryEnabled) {
Log.info('UserDiscoverySetupState: initializing UserDiscoveryService');
try {
await UserDiscoveryService.initializeOrUpdate(
threshold: threshold,
sharePromotion: sharePromotion,
);
} catch (e) {
Log.error(
'UserDiscoverySetupState: UserDiscoveryService failed or timed out: $e',
);
hasError = true;
}
}
Log.info('UserDiscoverySetupState: updating UserService');
@ -68,7 +76,8 @@ class UserDiscoverySetupState {
u
..isUserDiscoveryEnabled = isUserDiscoveryEnabled
..requiredSendImages = requiredSendImages
..userDiscoveryRequiresManualApproval = isManualApprovalEnabled;
..userDiscoveryRequiresManualApproval = isManualApprovalEnabled
..userDiscoveryInitializationError = hasError;
});
Log.info('UserDiscoverySetupState: initializeOrUpdate finished');
@ -474,7 +483,7 @@ class _ExampleLabel extends StatelessWidget {
),
child: Text(
context.lang.onboardingExampleLabel,
style: const TextStyle(fontSize: 10, color: Colors.white),
style: const TextStyle(fontSize: 10),
),
),
),

View file

@ -91,10 +91,8 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
public_key: Vec<u8>,
share_promotion: bool,
) -> Result<()> {
tracing::info!("Protocols: initialize_or_update started, getting config_lock");
let config_lock = self.config_lock.lock().await;
tracing::info!("Protocols: got config_lock, getting config from store");
let mut config = match self.store.get_config().await {
tracing::info!("Protocols: initialize_or_update started, getting config from store");
let config = match self.store.get_config().await {
Ok(config) => {
let mut config: UserDiscoveryConfig = serde_json::from_str(&config)?;
config.threshold = threshold;
@ -127,13 +125,25 @@ impl<Store: UserDiscoveryStore, Utils: UserDiscoveryUtils> UserDiscovery<Store,
debug_assert_eq!(verification_shares.len(), threshold as usize - 1);
config.public_id = public_id;
config.announcement_version += 1;
config.verification_shares = verification_shares;
config.share_promotion = share_promotion;
tracing::info!("Protocols: updating config in store");
self.update_config(config, config_lock).await?;
let config_lock = self.config_lock.lock().await;
let mut final_config = match self.store.get_config().await {
Ok(c) => serde_json::from_str(&c)?,
Err(_) => UserDiscoveryConfig {
threshold,
user_id,
..Default::default()
},
};
final_config.public_id = public_id;
final_config.announcement_version += 1;
final_config.verification_shares = verification_shares;
final_config.share_promotion = share_promotion;
final_config.threshold = threshold;
self.update_config(final_config, config_lock).await?;
tracing::info!("Protocols: initialize_or_update finished");
Ok(())