Skip to content

Commit b2d9f45

Browse files
BlazebrainOmarHatem28
authored andcommitted
fix: Sync bar ETA (#2515)
* fix: Sync bar ETA * fix: Smooth ETA - WIP * fix: Show disconnected status when sync disconnects * feat: Display blocks remaining for the first five seconds and then switch to percentage * Update * fix: Extend duration for showing blocks remaining during sync from 5 to 15 seconds; update connectivity check to handle multiple connectivity results, and handle disconnected state while syncing * feat: Initially display block if the a reconnection is triggered while syncing * fix: More improvements to syncing
1 parent d4200a7 commit b2d9f45

File tree

6 files changed

+45
-21
lines changed

6 files changed

+45
-21
lines changed

cw_bitcoin/lib/electrum_wallet.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2657,9 +2657,8 @@ abstract class ElectrumWalletBase
26572657

26582658
break;
26592659
case electrum.ConnectionStatus.disconnected:
2660-
if (syncStatus is! NotConnectedSyncStatus &&
2661-
syncStatus is! ConnectingSyncStatus &&
2662-
syncStatus is! SyncronizingSyncStatus) {
2660+
// Always show disconnected status when connection is lost, regardless of current sync state
2661+
if (syncStatus is! NotConnectedSyncStatus) {
26632662
syncStatus = NotConnectedSyncStatus();
26642663
}
26652664
break;

cw_core/lib/sync_status.dart

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class StartingScanSyncStatus extends SyncStatus {
2121
class SyncingSyncStatus extends SyncStatus {
2222
SyncingSyncStatus(this.blocksLeft, this.ptc) {
2323
updateEtaHistory(blocksLeft);
24+
_globalSyncStartTime ??= DateTime.now();
2425
}
2526

2627
double ptc;
@@ -32,6 +33,19 @@ class SyncingSyncStatus extends SyncStatus {
3233
@override
3334
String toString() => '$blocksLeft';
3435

36+
/// Returns true if we should show blocks remaining instead of percentage
37+
/// Shows blocks remaining for the first 15 seconds of syncing
38+
bool shouldShowBlocksRemaining() {
39+
if (_globalSyncStartTime == null) return true;
40+
final elapsed = DateTime.now().difference(_globalSyncStartTime!);
41+
return elapsed.inSeconds < 15;
42+
}
43+
44+
/// Reset the global sync start time (call when sync completes or fails)
45+
static void resetSyncStartTime() {
46+
_globalSyncStartTime = null;
47+
}
48+
3549
factory SyncingSyncStatus.fromHeightValues(int chainTip, int initialSyncHeight, int syncHeight) {
3650
final track = chainTip - initialSyncHeight;
3751
final diff = track - (chainTip - syncHeight);
@@ -45,21 +59,14 @@ class SyncingSyncStatus extends SyncStatus {
4559

4660
static void updateEtaHistory(int blocksLeft) {
4761
blockHistory[DateTime.now()] = blocksLeft;
48-
49-
// keep only the last 30 entries (gives us better statistical accuracy)
50-
while (blockHistory.length > 30) {
51-
blockHistory.remove(blockHistory.keys.first);
52-
}
5362
}
5463

5564
static Map<DateTime, int> blockHistory = {};
5665
static Duration? lastEtaDuration;
5766
static const int _minDataPoints = 3;
58-
static const int _maxDataAgeMinutes = 2;
67+
static DateTime? _globalSyncStartTime;
5968

6069
String? getFormattedEtaWithPlaceholder() {
61-
_cleanOldEntries();
62-
6370
// If we have enough data, show actual ETA
6471
if (blockHistory.length >= _minDataPoints) {
6572
final eta = getFormattedEta();
@@ -70,11 +77,6 @@ class SyncingSyncStatus extends SyncStatus {
7077
return '--:--';
7178
}
7279

73-
void _cleanOldEntries() {
74-
final cutoffTime = DateTime.now().subtract(Duration(minutes: _maxDataAgeMinutes));
75-
blockHistory.removeWhere((key, value) => key.isBefore(cutoffTime));
76-
}
77-
7880
String? getFormattedEta() {
7981
Duration? duration = getEtaDuration();
8082

lib/core/sync_status_title.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ import 'package:cw_core/sync_status.dart';
44

55
String syncStatusTitle(SyncStatus syncStatus, SyncStatusDisplayMode syncStatusDisplayMode) {
66
if (syncStatus is SyncingSyncStatus) {
7+
// Show blocks remaining for the first 3 seconds, then switch to percentage
8+
if (syncStatus.shouldShowBlocksRemaining()) {
9+
if (syncStatus.blocksLeft == 1) {
10+
return S.current.block_remaining;
11+
}
12+
return S.current.Blocks_remaining('${syncStatus.blocksLeft}');
13+
}
14+
15+
// After 3 seconds, show percentage-based display
16+
// Don't show ETA for very few blocks (less than 100) to avoid inconsistency
17+
if (syncStatus.blocksLeft < 100) {
18+
return S.current.Blocks_remaining('${syncStatus.blocksLeft}');
19+
}
20+
721
if (syncStatus.blocksLeft == 1) {
822
return S.current.block_remaining;
923
}

lib/reactions/check_connection.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import 'dart:async';
22

3-
import 'package:cake_wallet/src/screens/base_page.dart';
43
import 'package:cake_wallet/utils/tor.dart';
54
import 'package:connectivity_plus/connectivity_plus.dart';
65
import 'package:cw_core/utils/print_verbose.dart';
76
import 'package:cw_core/wallet_base.dart';
87
import 'package:cw_core/sync_status.dart';
98
import 'package:cw_core/wallet_type.dart';
109
import 'package:cake_wallet/store/settings_store.dart';
11-
import 'package:flutter/material.dart';
12-
import 'package:get_it/get_it.dart';
1310

1411
Timer? _checkConnectionTimer;
1512

@@ -29,7 +26,7 @@ void startCheckConnectionReaction(WalletBase wallet, SettingsStore settingsStore
2926
try {
3027
final connectivityResult = await (Connectivity().checkConnectivity());
3128

32-
if (connectivityResult == ConnectivityResult.none) {
29+
if (connectivityResult.contains(ConnectivityResult.none)) {
3330
wallet.syncStatus = FailedSyncStatus();
3431
return;
3532
}

lib/reactions/on_current_wallet_change.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:cake_wallet/solana/solana.dart';
1111
import 'package:cake_wallet/tron/tron.dart';
1212
import 'package:cake_wallet/utils/tor.dart';
1313
import 'package:cw_core/crypto_currency.dart';
14+
import 'package:cw_core/sync_status.dart';
1415
import 'package:cw_core/transaction_history.dart';
1516
import 'package:cw_core/balance.dart';
1617
import 'package:cw_core/transaction_info.dart';
@@ -92,6 +93,7 @@ void startCurrentWalletChangeReaction(
9293
}
9394

9495
await wallet.connectToNode(node: node);
96+
SyncingSyncStatus.blockHistory.clear();
9597
if (wallet.type == WalletType.nano || wallet.type == WalletType.banano) {
9698
final powNode = settingsStore.getCurrentPowNode(wallet.type);
9799
await wallet.connectToPowNode(node: powNode);

lib/reactions/on_wallet_sync_status_change.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,23 @@ void startWalletSyncStatusChangeReaction(
1919
_onWalletSyncStatusChangeReaction = reaction((_) => wallet.syncStatus, (SyncStatus status) async {
2020
try {
2121
if (status is ConnectedSyncStatus) {
22+
SyncingSyncStatus.resetSyncStartTime();
2223
await wallet.startSync();
2324
}
25+
2426
if (status is SyncingSyncStatus || status is ProcessingSyncStatus) {
2527
await WakelockPlus.enable();
2628
}
27-
if (status is SyncedSyncStatus || status is FailedSyncStatus) {
29+
30+
if (status is SyncedSyncStatus) {
31+
await WakelockPlus.disable();
32+
SyncingSyncStatus.resetSyncStartTime();
33+
SyncingSyncStatus.blockHistory.clear();
34+
}
35+
36+
if (status is FailedSyncStatus) {
2837
await WakelockPlus.disable();
38+
SyncingSyncStatus.resetSyncStartTime();
2939
}
3040

3141
if (status is SyncedSyncStatus &&

0 commit comments

Comments
 (0)