From be39ad2cd71594bb5a6f61766256f514bf11cf7d Mon Sep 17 00:00:00 2001
From: julian <julian@cypherstack.com>
Date: Wed, 1 Nov 2023 13:00:36 -0600
Subject: [PATCH] WIP walletInfo provider

---
 lib/wallets/isar/isar_id_interface.dart       |  5 ++
 .../models}/wallet_info.dart                  | 61 +++++++++++++++-
 .../models}/wallet_info.g.dart                |  0
 lib/wallets/isar/providers/util/watcher.dart  | 31 ++++++++
 .../isar/providers/wallet_info_provider.dart  | 70 +++++++++++++++++++
 5 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 lib/wallets/isar/isar_id_interface.dart
 rename lib/wallets/{isar_models => isar/models}/wallet_info.dart (80%)
 rename lib/wallets/{isar_models => isar/models}/wallet_info.g.dart (100%)
 create mode 100644 lib/wallets/isar/providers/util/watcher.dart
 create mode 100644 lib/wallets/isar/providers/wallet_info_provider.dart

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));
+  },
+);