all wallets sync changes for better ui performance

This commit is contained in:
julian 2024-05-13 10:10:34 -06:00
parent 3f4ebe0229
commit 20438da655
5 changed files with 218 additions and 65 deletions

View file

@ -11,7 +11,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart';
import 'package:stackwallet/providers/global/active_wallet_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/constants.dart';
@ -95,12 +94,12 @@ class SyncingOptionsView extends ConsumerWidget {
ref.read(prefsChangeNotifierProvider).syncType =
SyncingType.currentWalletOnly;
// disable auto sync on all wallets that aren't active/current
ref.read(pWallets).wallets.forEach((e) {
if (e.walletId != ref.read(currentWalletIdProvider)) {
e.shouldAutoSync = false;
}
});
// // disable auto sync on all wallets that aren't active/current
// ref.read(pWallets).wallets.forEach((e) {
// if (e.walletId != ref.read(currentWalletIdProvider)) {
// e.shouldAutoSync = false;
// }
// });
}
},
child: Container(
@ -174,11 +173,11 @@ class SyncingOptionsView extends ConsumerWidget {
ref.read(prefsChangeNotifierProvider).syncType =
SyncingType.allWalletsOnStartup;
// enable auto sync on all wallets
ref
.read(pWallets)
.wallets
.forEach((e) => e.shouldAutoSync = true);
// // enable auto sync on all wallets
// ref
// .read(pWallets)
// .wallets
// .forEach((e) => e.shouldAutoSync = true);
}
},
child: Container(
@ -252,13 +251,13 @@ class SyncingOptionsView extends ConsumerWidget {
ref.read(prefsChangeNotifierProvider).syncType =
SyncingType.selectedWalletsAtStartup;
final ids = ref
.read(prefsChangeNotifierProvider)
.walletIdsSyncOnStartup;
// enable auto sync on selected wallets only
ref.read(pWallets).wallets.forEach(
(e) => e.shouldAutoSync = ids.contains(e.walletId));
// final ids = ref
// .read(prefsChangeNotifierProvider)
// .walletIdsSyncOnStartup;
//
// // enable auto sync on selected wallets only
// ref.read(pWallets).wallets.forEach(
// (e) => e.shouldAutoSync = ids.contains(e.walletId));
}
},
child: Container(

View file

@ -13,13 +13,11 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/global/active_wallet_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
@ -181,9 +179,9 @@ class WalletSyncingOptionsView extends ConsumerWidget {
.walletIdsSyncOnStartup))
.contains(info.walletId),
onValueChanged: (value) {
final syncType = ref
.read(prefsChangeNotifierProvider)
.syncType;
// final syncType = ref
// .read(prefsChangeNotifierProvider)
// .syncType;
final ids = ref
.read(prefsChangeNotifierProvider)
.walletIdsSyncOnStartup
@ -194,25 +192,25 @@ class WalletSyncingOptionsView extends ConsumerWidget {
ids.remove(info.walletId);
}
final wallet = ref
.read(pWallets)
.getWallet(info.walletId);
switch (syncType) {
case SyncingType.currentWalletOnly:
if (info.walletId ==
ref.read(
currentWalletIdProvider)) {
wallet.shouldAutoSync = value;
}
break;
case SyncingType
.selectedWalletsAtStartup:
case SyncingType
.allWalletsOnStartup:
wallet.shouldAutoSync = value;
break;
}
// final wallet = ref
// .read(pWallets)
// .getWallet(info.walletId);
//
// switch (syncType) {
// case SyncingType.currentWalletOnly:
// if (info.walletId ==
// ref.read(
// currentWalletIdProvider)) {
// wallet.shouldAutoSync = value;
// }
// break;
// case SyncingType
// .selectedWalletsAtStartup:
// case SyncingType
// .allWalletsOnStartup:
// wallet.shouldAutoSync = value;
// break;
// }
ref
.read(prefsChangeNotifierProvider)

View file

@ -124,7 +124,7 @@ class _WalletViewState extends ConsumerState<WalletView> {
late final bool isSparkWallet;
late final bool _shouldDisableAutoSyncOnLogOut;
// late final bool _shouldDisableAutoSyncOnLogOut;
late WalletSyncStatus _currentSyncStatus;
late NodeConnectionStatus _currentNodeStatus;
@ -177,9 +177,9 @@ class _WalletViewState extends ConsumerState<WalletView> {
if (!wallet.shouldAutoSync) {
// enable auto sync if it wasn't enabled when loading wallet
wallet.shouldAutoSync = true;
_shouldDisableAutoSyncOnLogOut = true;
} else {
_shouldDisableAutoSyncOnLogOut = false;
// _shouldDisableAutoSyncOnLogOut = true;
// } else {
// _shouldDisableAutoSyncOnLogOut = false;
}
isSparkWallet = wallet is SparkInterface;
@ -303,10 +303,10 @@ class _WalletViewState extends ConsumerState<WalletView> {
}
void _logout() async {
if (_shouldDisableAutoSyncOnLogOut) {
// disable auto sync if it was enabled only when loading wallet
ref.read(pWallets).getWallet(walletId).shouldAutoSync = false;
}
// if (_shouldDisableAutoSyncOnLogOut) {
// // disable auto sync if it was enabled only when loading wallet
ref.read(pWallets).getWallet(walletId).shouldAutoSync = false;
// }
ref.read(currentWalletIdProvider.notifier).state = null;
ref.read(transactionFilterProvider.state).state = null;

View file

@ -72,7 +72,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
late final TextEditingController controller;
late final EventBus eventBus;
late final bool _shouldDisableAutoSyncOnLogOut;
// late final bool _shouldDisableAutoSyncOnLogOut;
Future<void> onBackPressed() async {
await _logout();
@ -83,10 +83,10 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
Future<void> _logout() async {
final wallet = ref.read(pWallets).getWallet(widget.walletId);
if (_shouldDisableAutoSyncOnLogOut) {
// disable auto sync if it was enabled only when loading wallet
wallet.shouldAutoSync = false;
}
// if (_shouldDisableAutoSyncOnLogOut) {
// // disable auto sync if it was enabled only when loading wallet
wallet.shouldAutoSync = false;
// }
ref.read(transactionFilterProvider.state).state = null;
if (ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled &&
ref.read(prefsChangeNotifierProvider).backupFrequencyType ==
@ -131,11 +131,11 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
ref.read(currentWalletIdProvider.notifier).state = wallet.walletId);
if (!wallet.shouldAutoSync) {
// enable auto sync if it wasn't enabled when loading wallet
// // enable auto sync if it wasn't enabled when loading wallet
wallet.shouldAutoSync = true;
_shouldDisableAutoSyncOnLogOut = true;
} else {
_shouldDisableAutoSyncOnLogOut = false;
// _shouldDisableAutoSyncOnLogOut = true;
// } else {
// _shouldDisableAutoSyncOnLogOut = false;
}
wallet.refresh();

View file

@ -136,7 +136,8 @@ class Wallets {
Future<void> load(Prefs prefs, MainDB mainDB) async {
// return await _loadV1(prefs, mainDB);
return await _loadV2(prefs, mainDB);
// return await _loadV2(prefs, mainDB);
return await _loadV3(prefs, mainDB);
}
Future<void> _loadV1(Prefs prefs, MainDB mainDB) async {
@ -240,6 +241,7 @@ class Wallets {
}
}
/// should be fastest but big ui performance hit
Future<void> _loadV2(Prefs prefs, MainDB mainDB) async {
if (hasLoaded) {
return;
@ -358,6 +360,160 @@ class Wallets {
await Future.wait(deleteFutures);
}
/// should be best performance
Future<void> _loadV3(Prefs prefs, MainDB mainDB) async {
if (hasLoaded) {
return;
}
hasLoaded = true;
// clear out any wallet hive boxes where the wallet was deleted in previous app run
for (final walletId in DB.instance
.values<String>(boxName: DB.boxNameWalletsToDeleteOnStart)) {
await mainDB.isar.writeTxn(() async => await mainDB.isar.walletInfo
.where()
.walletIdEqualTo(walletId)
.deleteAll());
}
// clear list
await DB.instance
.deleteAll<String>(boxName: DB.boxNameWalletsToDeleteOnStart);
final walletInfoList = await mainDB.isar.walletInfo.where().findAll();
if (walletInfoList.isEmpty) {
return;
}
final List<Future<String>> walletIDInitFutures = [];
final List<Future<void>> deleteFutures = [];
final List<({Wallet wallet, bool shouldAutoSync})> walletsToInitLinearly =
[];
final List<String> walletIdsToSyncOnceOnStartup = [];
bool shouldSyncAllOnceOnStartup = false;
switch (prefs.syncType) {
case SyncingType.currentWalletOnly:
// do nothing as this will be set when going into a wallet from the main screen
break;
case SyncingType.selectedWalletsAtStartup:
walletIdsToSyncOnceOnStartup.addAll(prefs.walletIdsSyncOnStartup);
break;
case SyncingType.allWalletsOnStartup:
shouldSyncAllOnceOnStartup = true;
break;
}
for (final walletInfo in walletInfoList) {
try {
final isVerified = await walletInfo.isMnemonicVerified(mainDB.isar);
Logging.instance.log(
"LOADING WALLET: ${walletInfo.name}:${walletInfo.walletId} "
"IS VERIFIED: $isVerified",
level: LogLevel.Info,
);
if (isVerified) {
// TODO: integrate this into the new wallets somehow?
// requires some thinking
// final txTracker =
// TransactionNotificationTracker(walletId: walletInfo.walletId);
final walletIdCompleter = Completer<String>();
walletIDInitFutures.add(walletIdCompleter.future);
await Wallet.load(
walletId: walletInfo.walletId,
mainDB: mainDB,
secureStorageInterface: nodeService.secureStorageInterface,
nodeService: nodeService,
prefs: prefs,
).then((wallet) {
if (wallet is CwBasedInterface) {
// walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
walletIdCompleter.complete("dummy_ignore");
} else {
walletIdCompleter.complete(wallet.walletId);
}
_wallets[wallet.walletId] = wallet;
});
} else {
// wallet creation was not completed by user so we remove it completely
deleteFutures.add(_deleteWallet(walletInfo.walletId));
}
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Fatal);
continue;
}
}
final asyncWalletIds = await Future.wait(walletIDInitFutures);
asyncWalletIds.removeWhere((e) => e == "dummy_ignore");
final List<String> idsToRefresh = [];
final List<Future<void>> walletInitFutures = asyncWalletIds
.map(
(id) => _wallets[id]!.init().then(
(_) {
if (shouldSyncAllOnceOnStartup ||
walletIdsToSyncOnceOnStartup.contains(id)) {
idsToRefresh.add(id);
}
},
),
)
.toList();
Future<void> _refreshFutures(List<String> idsToRefresh) async {
final start = DateTime.now();
Logging.instance.log(
"Initial refresh start: ${start.toUtc()}",
level: LogLevel.Warning,
);
const groupCount = 3;
for (int i = 0; i < idsToRefresh.length; i += groupCount) {
final List<Future<void>> futures = [];
for (int j = 0; j < groupCount; j++) {
if (i + j >= idsToRefresh.length) {
break;
}
futures.add(
_wallets[idsToRefresh[i + j]]!.refresh(),
);
}
await Future.wait(futures);
}
Logging.instance.log(
"Initial refresh duration: ${DateTime.now().difference(start)}",
level: LogLevel.Warning,
);
}
if (walletInitFutures.isNotEmpty && walletsToInitLinearly.isNotEmpty) {
unawaited(
Future.wait([
_initLinearly(walletsToInitLinearly),
...walletInitFutures,
]).then(
(value) => _refreshFutures(idsToRefresh),
),
);
} else if (walletInitFutures.isNotEmpty) {
unawaited(
Future.wait(walletInitFutures).then(
(value) => _refreshFutures(idsToRefresh),
),
);
} else if (walletsToInitLinearly.isNotEmpty) {
unawaited(_initLinearly(walletsToInitLinearly));
}
// finally await any deletions that haven't completed yet
await Future.wait(deleteFutures);
}
Future<void> loadAfterStackRestore(
Prefs prefs,
List<Wallet> wallets,
@ -396,10 +552,10 @@ class Wallets {
if (wallet is CwBasedInterface) {
// walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
} else {
walletInitFutures.add(wallet.init().then((value) {
if (shouldSetAutoSync) {
wallet.shouldAutoSync = true;
}
walletInitFutures.add(wallet.init().then((_) {
// if (shouldSetAutoSync) {
// wallet.shouldAutoSync = true;
// }
}));
}
}