diff --git a/lib/hive/db.dart b/lib/hive/db.dart index d5402752e..48e6ba154 100644 --- a/lib/hive/db.dart +++ b/lib/hive/db.dart @@ -43,23 +43,23 @@ class DB { static bool _initialized = false; - late final Box _boxAddressBook; - late final Box _boxDebugInfo; - late final Box _boxNodeModels; - late final Box _boxPrimaryNodes; - late final Box _boxAllWalletsData; - late final Box _boxNotifications; - late final Box _boxWatchedTransactions; - late final Box _boxWatchedTrades; - late final Box _boxTrades; - late final Box _boxTradesV2; - late final Box _boxTradeNotes; - late final Box _boxFavoriteWallets; - late final Box _walletInfoSource; - late final Box _boxPrefs; - late final Box _boxTradeLookup; - late final Box _boxDBInfo; - late final Box _boxDesktopData; + Box? _boxAddressBook; + Box? _boxDebugInfo; + Box? _boxNodeModels; + Box? _boxPrimaryNodes; + Box? _boxAllWalletsData; + Box? _boxNotifications; + Box? _boxWatchedTransactions; + Box? _boxWatchedTrades; + Box? _boxTrades; + Box? _boxTradesV2; + Box? _boxTradeNotes; + Box? _boxFavoriteWallets; + Box? _walletInfoSource; + Box? _boxPrefs; + Box? _boxTradeLookup; + Box? _boxDBInfo; + Box? _boxDesktopData; final Map> _walletBoxes = {}; @@ -68,7 +68,7 @@ class DB { final Map> _usedSerialsCacheBoxes = {}; // exposed for monero - Box get moneroWalletInfoBox => _walletInfoSource; + Box get moneroWalletInfoBox => _walletInfoSource!; // mutex for stack backup final mutex = Mutex(); @@ -124,6 +124,12 @@ class DB { _boxAllWalletsData = await Hive.openBox(boxNameAllWalletsData); } + if (Hive.isBoxOpen(boxNameDesktopData)) { + _boxDesktopData = Hive.box(boxNameDesktopData); + } else { + _boxDesktopData = await Hive.openBox(boxNameDesktopData); + } + _boxNotifications = await Hive.openBox(boxNameNotifications); _boxWatchedTransactions = @@ -147,11 +153,11 @@ class DB { _initialized = true; try { - if (_boxPrefs.get("familiarity") == null) { - await _boxPrefs.put("familiarity", 0); + if (_boxPrefs!.get("familiarity") == null) { + await _boxPrefs!.put("familiarity", 0); } - int count = _boxPrefs.get("familiarity") as int; - await _boxPrefs.put("familiarity", count + 1); + int count = _boxPrefs!.get("familiarity") as int; + await _boxPrefs!.put("familiarity", count + 1); Constants.exchangeForExperiencedUsers(count + 1); } catch (e, s) { print("$e $s"); @@ -160,7 +166,7 @@ class DB { } Future _loadWalletBoxes() async { - final names = _boxAllWalletsData.get("names") as Map? ?? {}; + final names = _boxAllWalletsData!.get("names") as Map? ?? {}; names.removeWhere((name, dyn) { final jsonObject = Map.from(dyn as Map); try { diff --git a/lib/main.dart b/lib/main.dart index a8b515b02..a04170bd9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -48,19 +48,16 @@ import 'package:stackwallet/services/node_service.dart'; import 'package:stackwallet/services/notifications_api.dart'; import 'package:stackwallet/services/notifications_service.dart'; import 'package:stackwallet/services/trade_service.dart'; -import 'package:stackwallet/services/wallets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/db_version_migration.dart'; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/logger.dart'; -import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:stackwallet/utilities/theme/dark_colors.dart'; import 'package:stackwallet/utilities/theme/light_colors.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; -import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:window_size/window_size.dart'; final openedFromSWBFileStringStateProvider = @@ -221,8 +218,8 @@ class _MaterialAppWithThemeState extends ConsumerState static const platform = MethodChannel("STACK_WALLET_RESTORE"); final GlobalKey navigatorKey = GlobalKey(); - late final Wallets _wallets; - late final Prefs _prefs; + // late final Wallets _wallets; + // late final Prefs _prefs; late final NotificationsService _notificationsService; late final NodeService _nodeService; late final TradesService _tradesService; @@ -232,6 +229,16 @@ class _MaterialAppWithThemeState extends ConsumerState bool didLoad = false; bool _desktopHasPassword = false; + Future loadShared() async { + await DB.instance.init(); + await ref.read(prefsChangeNotifierProvider).init(); + + if (Util.isDesktop) { + _desktopHasPassword = + await ref.read(storageCryptoHandlerProvider).hasPassword(); + } + } + Future load() async { try { if (didLoad) { @@ -239,19 +246,15 @@ class _MaterialAppWithThemeState extends ConsumerState } didLoad = true; - await DB.instance.init(); - await _prefs.init(); - - if (Util.isDesktop) { - _desktopHasPassword = - await ref.read(storageCryptoHandlerProvider).hasPassword(); + if (!Util.isDesktop) { + await loadShared(); } _notificationsService = ref.read(notificationsProvider); _nodeService = ref.read(nodeServiceChangeNotifierProvider); _tradesService = ref.read(tradesServiceProvider); - NotificationApi.prefs = _prefs; + NotificationApi.prefs = ref.read(prefsChangeNotifierProvider); NotificationApi.notificationsService = _notificationsService; unawaited(ref.read(baseCurrenciesProvider).update()); @@ -260,23 +263,25 @@ class _MaterialAppWithThemeState extends ConsumerState await _notificationsService.init( nodeService: _nodeService, tradesService: _tradesService, - prefs: _prefs, + prefs: ref.read(prefsChangeNotifierProvider), ); ref.read(priceAnd24hChangeNotifierProvider).start(true); - await _wallets.load(_prefs); + await ref + .read(walletsChangeNotifierProvider) + .load(ref.read(prefsChangeNotifierProvider)); loadingCompleter.complete(); // TODO: this should probably run unawaited. Keep commented out for now as proper community nodes ui hasn't been implemented yet // unawaited(_nodeService.updateCommunityNodes()); // run without awaiting if (Constants.enableExchange && - _prefs.externalCalls && - await _prefs.isExternalCallsSet()) { + ref.read(prefsChangeNotifierProvider).externalCalls && + await ref.read(prefsChangeNotifierProvider).isExternalCallsSet()) { unawaited(ExchangeDataLoadingService().loadAll(ref)); } - if (_prefs.isAutoBackupEnabled) { - switch (_prefs.backupFrequencyType) { + if (ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled) { + switch (ref.read(prefsChangeNotifierProvider).backupFrequencyType) { case BackupFrequencyType.everyTenMinutes: ref.read(autoSWBServiceProvider).startPeriodicBackupTimer( duration: const Duration(minutes: 10)); @@ -316,9 +321,6 @@ class _MaterialAppWithThemeState extends ConsumerState .read(localeServiceChangeNotifierProvider.notifier) .loadLocale(notify: false); - _prefs = ref.read(prefsChangeNotifierProvider); - _wallets = ref.read(walletsChangeNotifierProvider); - WidgetsBinding.instance.addPostFrameCallback((_) async { ref.read(colorThemeProvider.state).state = StackColors.fromStackColorTheme( @@ -423,7 +425,7 @@ class _MaterialAppWithThemeState extends ConsumerState } Future goToRestoreSWB(String encrypted) async { - if (!_prefs.hasPin) { + if (!ref.read(prefsChangeNotifierProvider).hasPin) { await Navigator.of(navigatorKey.currentContext!) .pushNamed(CreatePinView.routeName, arguments: true) .then((value) { @@ -569,57 +571,70 @@ class _MaterialAppWithThemeState extends ConsumerState _buildOutlineInputBorder(colorScheme.textFieldDefaultBG), ), ), - home: ConditionalParent( - condition: Util.isDesktop, - builder: (child) { - return child; - }, - child: FutureBuilder( - future: load(), - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - // FlutterNativeSplash.remove(); - if (Util.isDesktop && - (_wallets.hasWallets || _desktopHasPassword)) { - String? startupWalletId; - if (ref.read(prefsChangeNotifierProvider).gotoWalletOnStartup) { - startupWalletId = - ref.read(prefsChangeNotifierProvider).startupWalletId; + home: Util.isDesktop + ? FutureBuilder( + future: loadShared(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + if (_desktopHasPassword) { + String? startupWalletId; + if (ref + .read(prefsChangeNotifierProvider) + .gotoWalletOnStartup) { + startupWalletId = + ref.read(prefsChangeNotifierProvider).startupWalletId; + } + + return DesktopLoginView( + startupWalletId: startupWalletId, + load: load, + ); + } else { + return const IntroView(); + } + } else { + return const LoadingView(); } + }, + ) + : FutureBuilder( + future: load(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + // FlutterNativeSplash.remove(); + if (ref.read(walletsChangeNotifierProvider).hasWallets || + ref.read(prefsChangeNotifierProvider).hasPin) { + // return HomeView(); - return DesktopLoginView(startupWalletId: startupWalletId); - } else if (!Util.isDesktop && - (_wallets.hasWallets || _prefs.hasPin)) { - // return HomeView(); + String? startupWalletId; + if (ref + .read(prefsChangeNotifierProvider) + .gotoWalletOnStartup) { + startupWalletId = + ref.read(prefsChangeNotifierProvider).startupWalletId; + } - String? startupWalletId; - if (ref.read(prefsChangeNotifierProvider).gotoWalletOnStartup) { - startupWalletId = - ref.read(prefsChangeNotifierProvider).startupWalletId; + return LockscreenView( + isInitialAppLogin: true, + routeOnSuccess: HomeView.routeName, + routeOnSuccessArguments: startupWalletId, + biometricsAuthenticationTitle: "Unlock Stack", + biometricsLocalizedReason: + "Unlock your stack wallet using biometrics", + biometricsCancelButtonString: "Cancel", + ); + } else { + return const IntroView(); + } + } else { + // CURRENTLY DISABLED as cannot be animated + // technically not needed as FlutterNativeSplash will overlay + // anything returned here until the future completes but + // FutureBuilder requires you to return something + return const LoadingView(); } - - return LockscreenView( - isInitialAppLogin: true, - routeOnSuccess: HomeView.routeName, - routeOnSuccessArguments: startupWalletId, - biometricsAuthenticationTitle: "Unlock Stack", - biometricsLocalizedReason: - "Unlock your stack wallet using biometrics", - biometricsCancelButtonString: "Cancel", - ); - } else { - return const IntroView(); - } - } else { - // CURRENTLY DISABLED as cannot be animated - // technically not needed as FlutterNativeSplash will overlay - // anything returned here until the future completes but - // FutureBuilder requires you to return something - return const LoadingView(); - } - }, - ), - ), + }, + ), ); } } diff --git a/lib/pages_desktop_specific/desktop_login_view.dart b/lib/pages_desktop_specific/desktop_login_view.dart index 0a47c2a96..d90e742fb 100644 --- a/lib/pages_desktop_specific/desktop_login_view.dart +++ b/lib/pages_desktop_specific/desktop_login_view.dart @@ -21,11 +21,13 @@ class DesktopLoginView extends ConsumerStatefulWidget { const DesktopLoginView({ Key? key, this.startupWalletId, + this.load, }) : super(key: key); static const String routeName = "/desktopLogin"; final String? startupWalletId; + final Future Function()? load; @override ConsumerState createState() => _DesktopLoginViewState(); @@ -39,6 +41,32 @@ class _DesktopLoginViewState extends ConsumerState { bool hidePassword = true; bool _continueEnabled = false; + Future login() async { + try { + await ref + .read(storageCryptoHandlerProvider) + .initFromExisting(passwordController.text); + + await widget.load?.call(); + + // if no errors passphrase is correct + if (mounted) { + unawaited( + Navigator.of(context).pushNamedAndRemoveUntil( + DesktopHomeView.routeName, + (route) => false, + ), + ); + } + } catch (e) { + await showFloatingFlushBar( + type: FlushBarType.warning, + message: e.toString(), + context: context, + ); + } + } + @override void initState() { passwordController = TextEditingController(); @@ -159,29 +187,7 @@ class _DesktopLoginViewState extends ConsumerState { PrimaryButton( label: "Continue", enabled: _continueEnabled, - onPressed: () async { - try { - await ref - .read(storageCryptoHandlerProvider) - .initFromExisting(passwordController.text); - - // if no errors passphrase is correct - if (mounted) { - unawaited( - Navigator.of(context).pushNamedAndRemoveUntil( - DesktopHomeView.routeName, - (route) => false, - ), - ); - } - } catch (e) { - await showFloatingFlushBar( - type: FlushBarType.warning, - message: e.toString(), - context: context, - ); - } - }, + onPressed: login, ), const SizedBox( height: 60, diff --git a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/create_auto_backup.dart b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/create_auto_backup.dart index e804071cc..2583e16c5 100644 --- a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/create_auto_backup.dart +++ b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore/create_auto_backup.dart @@ -5,13 +5,13 @@ import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stack_wallet_backup/stack_wallet_backup.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/helpers/stack_file_system.dart'; import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/providers/global/secure_store_provider.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; @@ -35,13 +35,8 @@ import 'package:zxcvbn/zxcvbn.dart'; class CreateAutoBackup extends ConsumerStatefulWidget { const CreateAutoBackup({ Key? key, - this.secureStore = const SecureStorageWrapper( - FlutterSecureStorage(), - ), }) : super(key: key); - final FlutterSecureStorageInterface secureStore; - @override ConsumerState createState() => _CreateAutoBackup(); } @@ -51,7 +46,7 @@ class _CreateAutoBackup extends ConsumerState { late final TextEditingController passphraseController; late final TextEditingController passphraseRepeatController; - late final FlutterSecureStorageInterface secureStore; + late final SecureStorageInterface secureStore; late final StackFileSystem stackFileSystem; late final FocusNode passphraseFocusNode; @@ -85,7 +80,7 @@ class _CreateAutoBackup extends ConsumerState { @override void initState() { - secureStore = widget.secureStore; + secureStore = ref.read(secureStoreProvider); stackFileSystem = StackFileSystem(); fileLocationController = TextEditingController(); @@ -686,7 +681,9 @@ class _CreateAutoBackup extends ConsumerState { final String fileToSave = createAutoBackupFilename(pathToSave, now); - final backup = await SWB.createStackWalletJSON(); + final backup = await SWB.createStackWalletJSON( + secureStorage: secureStore, + ); bool result = await SWB.encryptStackWalletWithADK( fileToSave, diff --git a/lib/utilities/desktop_password_service.dart b/lib/utilities/desktop_password_service.dart index 178871e69..24299b855 100644 --- a/lib/utilities/desktop_password_service.dart +++ b/lib/utilities/desktop_password_service.dart @@ -89,12 +89,10 @@ class DPS { } Future hasPassword() async { - final box = await Hive.openBox(DB.boxNameDesktopData); final keyBlob = DB.instance.get( boxName: DB.boxNameDesktopData, key: _kKeyBlobKey, ); - await box.close(); return keyBlob != null; } }