diff --git a/lib/wallets/isar/isar_id_interface.dart b/lib/wallets/isar/isar_id_interface.dart new file mode 100644 index 000000000..c98455284 --- /dev/null +++ b/lib/wallets/isar/isar_id_interface.dart @@ -0,0 +1,5 @@ +import 'package:isar/isar.dart'; + +abstract interface class IsarId { + Id get id; +} diff --git a/lib/wallets/isar_models/wallet_info.dart b/lib/wallets/isar/models/wallet_info.dart similarity index 80% rename from lib/wallets/isar_models/wallet_info.dart rename to lib/wallets/isar/models/wallet_info.dart index 1eae508db..5a383f354 100644 --- a/lib/wallets/isar_models/wallet_info.dart +++ b/lib/wallets/isar/models/wallet_info.dart @@ -4,11 +4,13 @@ import 'package:isar/isar.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/blockchain_data/address.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/wallets/isar/isar_id_interface.dart'; part 'wallet_info.g.dart'; @Collection(accessor: "walletInfo", inheritance: false) -class WalletInfo { +class WalletInfo implements IsarId { + @override Id id = Isar.autoIncrement; @Index(unique: true, replace: false) @@ -132,6 +134,63 @@ class WalletInfo { } } + /// update favourite wallet and its index it the ui list. + /// When [customIndexOverride] is not null the [flag] will be ignored. + Future<void> updateIsFavourite( + bool flag, { + required Isar isar, + int? customIndexOverride, + }) async { + final int index; + + if (customIndexOverride != null) { + index = customIndexOverride; + } else if (flag) { + final highest = await isar.walletInfo + .where() + .walletIdEqualTo(walletId) + .sortByFavouriteOrderIndexDesc() + .favouriteOrderIndexProperty() + .findFirst(); + index = highest ?? 0; + } else { + index = -1; + } + + // only update if there were changes to the height + if (favouriteOrderIndex != index) { + final updated = copyWith( + favouriteOrderIndex: index, + ); + await isar.writeTxn(() async { + await isar.walletInfo.delete(id); + await isar.walletInfo.put(updated); + }); + } + } + + /// copies this with a new name and updates the db + Future<void> updateName({ + required String newName, + required Isar isar, + }) async { + // don't allow empty names + if (newName.isEmpty) { + throw Exception("Empty wallet name not allowed!"); + } + + // only update if there were changes to the name + if (name != newName) { + final updated = copyWith( + name: newName, + ); + await isar.writeTxn(() async { + await isar.walletInfo.delete(id); + await isar.walletInfo.put(updated); + }); + } + } + //============================================================================ WalletInfo({ diff --git a/lib/wallets/isar_models/wallet_info.g.dart b/lib/wallets/isar/models/wallet_info.g.dart similarity index 100% rename from lib/wallets/isar_models/wallet_info.g.dart rename to lib/wallets/isar/models/wallet_info.g.dart diff --git a/lib/wallets/isar/providers/util/watcher.dart b/lib/wallets/isar/providers/util/watcher.dart new file mode 100644 index 000000000..2a6ab50e3 --- /dev/null +++ b/lib/wallets/isar/providers/util/watcher.dart @@ -0,0 +1,31 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:isar/isar.dart'; +import 'package:stackwallet/wallets/isar/isar_id_interface.dart'; + +class Watcher<T extends IsarId> extends ChangeNotifier { + late final StreamSubscription<T?> _streamSubscription; + + T _value; + + T get value => _value; + + Watcher( + this._value, { + required IsarCollection<T> collection, + }) { + _streamSubscription = collection.watchObject(_value.id).listen((event) { + if (event != null) { + _value = event; + notifyListeners(); + } + }); + } + + @override + void dispose() { + _streamSubscription.cancel(); + super.dispose(); + } +} diff --git a/lib/wallets/isar/providers/wallet_info_provider.dart b/lib/wallets/isar/providers/wallet_info_provider.dart new file mode 100644 index 000000000..cc8a5bc28 --- /dev/null +++ b/lib/wallets/isar/providers/wallet_info_provider.dart @@ -0,0 +1,70 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:isar/isar.dart'; +import 'package:stackwallet/models/balance.dart'; +import 'package:stackwallet/providers/db/main_db_provider.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/wallets/isar/models/wallet_info.dart'; +import 'package:stackwallet/wallets/isar/providers/util/watcher.dart'; + +final _wiProvider = ChangeNotifierProvider.autoDispose.family<Watcher, String>( + (ref, walletId) { + final collection = ref.watch(mainDBProvider).isar.walletInfo; + + final watcher = Watcher( + collection.where().walletIdEqualTo(walletId).findFirstSync()!, + collection: collection, + ); + + ref.onDispose(() => watcher.dispose()); + + return watcher; + }, +); + +final pWalletInfo = Provider.autoDispose.family<WalletInfo, String>( + (ref, walletId) { + return ref.watch(_wiProvider(walletId)).value as WalletInfo; + }, +); + +final pWalletCoin = Provider.autoDispose.family<Coin, String>( + (ref, walletId) { + return ref.watch(_wiProvider(walletId) + .select((value) => (value.value as WalletInfo).coin)); + }, +); + +final pWalletBalance = Provider.autoDispose.family<Balance, String>( + (ref, walletId) { + return ref.watch(_wiProvider(walletId) + .select((value) => (value.value as WalletInfo).cachedBalance)); + }, +); + +final pWalletBalanceSecondary = Provider.autoDispose.family<Balance, String>( + (ref, walletId) { + return ref.watch(_wiProvider(walletId) + .select((value) => (value.value as WalletInfo).cachedSecondaryBalance)); + }, +); + +final pWalletChainHeight = Provider.autoDispose.family<int, String>( + (ref, walletId) { + return ref.watch(_wiProvider(walletId) + .select((value) => (value.value as WalletInfo).cachedChainHeight)); + }, +); + +final pWalletIsFavourite = Provider.autoDispose.family<bool, String>( + (ref, walletId) { + return ref.watch(_wiProvider(walletId) + .select((value) => (value.value as WalletInfo).isFavourite)); + }, +); + +final pWalletName = Provider.autoDispose.family<String, String>( + (ref, walletId) { + return ref.watch(_wiProvider(walletId) + .select((value) => (value.value as WalletInfo).name)); + }, +);