From 32e837670062c28595923f3374156af247c6b660 Mon Sep 17 00:00:00 2001 From: Stephan D Date: Thu, 22 Jan 2026 14:15:14 +0100 Subject: [PATCH] Fixed compilation --- frontend/pshared/lib/controllers/wallets.dart | 129 ++++++++++ .../pshared/lib/data/dto/ledger/account.dart | 47 ++++ .../pshared/lib/data/dto/ledger/balance.dart | 27 ++ .../lib/data/dto/payment/fee_line.dart | 2 +- .../lib/data/dto/payment/fx_quote.dart | 2 +- .../lib/data/dto/payment/intent/payment.dart | 2 +- .../lib/data/dto/payment/network_fee.dart | 2 +- .../lib/data/dto/payment/payment_quote.dart | 2 +- .../lib/data/dto/payment/quote_aggregate.dart | 2 +- .../lib/data/mapper/ledger/account.dart | 43 ++++ .../lib/data/mapper/ledger/balance.dart | 22 ++ frontend/pshared/lib/data/mapper/money.dart | 2 +- .../lib/data/mapper/payment/fee_line.dart | 2 +- .../lib/data/mapper/payment/fx_quote.dart | 2 +- .../data/mapper/payment/intent/payment.dart | 2 +- .../lib/data/mapper/payment/network_fee.dart | 2 +- .../data/mapper/payment/payment_quote.dart | 2 +- .../data/mapper/payment/quote/aggregate.dart | 2 +- .../pshared/lib/data/mapper/wallet/ui.dart | 1 - .../pshared/lib/models/ledger/account.dart | 4 + .../pshared/lib/models/ledger/balance.dart | 16 ++ .../pshared/lib/models/payment/wallet.dart | 34 +-- .../payment/quotation/intent_builder.dart | 4 +- .../provider/payment/quotation/quotation.dart | 7 +- .../pshared/lib/provider/payment/wallets.dart | 231 ++++++++++++------ .../pweb/lib/app/router/payout_shell.dart | 10 +- frontend/pweb/lib/main.dart | 5 + .../dashboard/buttons/balance/amount.dart | 8 +- .../dashboard/buttons/balance/balance.dart | 20 +- .../pages/dashboard/buttons/balance/card.dart | 5 +- .../dashboard/payouts/summary/widget.dart | 4 +- .../pweb/lib/pages/payment_methods/page.dart | 4 +- .../payment_methods/payment_page/content.dart | 4 +- .../payment_page/method_selector.dart | 4 +- .../lib/pages/payout_page/wallet/card.dart | 6 +- .../payout_page/wallet/edit/buttons/send.dart | 6 +- .../wallet/edit/buttons/top_up.dart | 4 +- .../pages/payout_page/wallet/edit/fields.dart | 12 +- .../pages/payout_page/wallet/edit/header.dart | 6 +- .../pages/payout_page/wallet/edit/page.dart | 8 +- .../pweb/lib/pages/wallet_top_up/page.dart | 42 ++-- 41 files changed, 549 insertions(+), 190 deletions(-) create mode 100644 frontend/pshared/lib/controllers/wallets.dart create mode 100644 frontend/pshared/lib/data/dto/ledger/account.dart create mode 100644 frontend/pshared/lib/data/dto/ledger/balance.dart create mode 100644 frontend/pshared/lib/data/mapper/ledger/account.dart create mode 100644 frontend/pshared/lib/data/mapper/ledger/balance.dart create mode 100644 frontend/pshared/lib/models/ledger/balance.dart diff --git a/frontend/pshared/lib/controllers/wallets.dart b/frontend/pshared/lib/controllers/wallets.dart new file mode 100644 index 00000000..858693a9 --- /dev/null +++ b/frontend/pshared/lib/controllers/wallets.dart @@ -0,0 +1,129 @@ +import 'package:collection/collection.dart'; + +import 'package:flutter/foundation.dart'; + +import 'package:pshared/models/payment/wallet.dart'; +import 'package:pshared/provider/payment/wallets.dart'; + + +class WalletsController with ChangeNotifier { + late WalletsProvider _wallets; + + // If you want per-org isolation, we reset when org changes. + String? _orgRef; + + // Visibility is UI-only: store hidden wallet ids here. + final Set _hiddenWalletIds = {}; + + String? _selectedWalletId; + + bool get isLoading => _wallets.isLoading; + + Exception? get error => _wallets.error; + + /// Inject / update dependency (use ProxyProvider). + void update(WalletsProvider wallets) { + _wallets = wallets; + + final nextOrgRef = wallets.organizationId; + final orgChanged = nextOrgRef != _orgRef; + if (orgChanged) { + _orgRef = nextOrgRef; + _hiddenWalletIds.clear(); + _selectedWalletId = null; + } + + // Prune hidden ids for wallets that no longer exist. + final ids = wallets.wallets.map((w) => w.id).toSet(); + final beforeHiddenLen = _hiddenWalletIds.length; + _hiddenWalletIds.removeWhere((id) => !ids.contains(id)); + + // Ensure selection is valid. + final beforeSelected = _selectedWalletId; + _selectedWalletId = _resolveSelectedId( + currentId: _selectedWalletId, + wallets: wallets.wallets, + hiddenIds: _hiddenWalletIds, + ); + + final selectionChanged = beforeSelected != _selectedWalletId; + final hiddenChanged = beforeHiddenLen != _hiddenWalletIds.length; + + if (orgChanged || selectionChanged || hiddenChanged) { + notifyListeners(); + } + } + + List get wallets => _wallets.wallets; + + bool isHidden(String walletId) => _hiddenWalletIds.contains(walletId); + + List get visibleWallets => + wallets.where((w) => !_hiddenWalletIds.contains(w.id)).toList(growable: false); + + Wallet? get selectedWallet { + final id = _selectedWalletId; + if (id == null) return null; + return wallets.firstWhereOrNull((w) => w.id == id); + } + + String? get selectedWalletId => _selectedWalletId; + + void selectWallet(Wallet wallet) => selectWalletId(wallet.id); + + void selectWalletId(String walletId) { + if (_selectedWalletId == walletId) return; + + // Allow selecting hidden wallet if you want; if not, block it: + // if (isHidden(walletId)) return; + + _selectedWalletId = walletId; + notifyListeners(); + } + + void toggleVisibility(String walletId) { + final existed = _hiddenWalletIds.remove(walletId); + if (!existed) _hiddenWalletIds.add(walletId); + + // If we hid the selected wallet, move selection to next visible. + _selectedWalletId = _resolveSelectedId( + currentId: _selectedWalletId, + wallets: wallets, + hiddenIds: _hiddenWalletIds, + ); + + notifyListeners(); + } + + void showAll() { + if (_hiddenWalletIds.isEmpty) return; + _hiddenWalletIds.clear(); + _selectedWalletId = _resolveSelectedId( + currentId: _selectedWalletId, + wallets: wallets, + hiddenIds: _hiddenWalletIds, + ); + notifyListeners(); + } + + String? _resolveSelectedId({ + required String? currentId, + required List wallets, + required Set hiddenIds, + }) { + if (wallets.isEmpty) return null; + + // Keep current if exists and is not hidden. + if (currentId != null) { + final exists = wallets.any((w) => w.id == currentId); + if (exists && !hiddenIds.contains(currentId)) return currentId; + } + + // Pick first visible. + final firstVisible = wallets.firstWhereOrNull((w) => !hiddenIds.contains(w.id)); + if (firstVisible != null) return firstVisible.id; + + // All hidden: fall back to first wallet id (or return null if you prefer). + return wallets.first.id; + } +} diff --git a/frontend/pshared/lib/data/dto/ledger/account.dart b/frontend/pshared/lib/data/dto/ledger/account.dart new file mode 100644 index 00000000..92c59117 --- /dev/null +++ b/frontend/pshared/lib/data/dto/ledger/account.dart @@ -0,0 +1,47 @@ +import 'package:json_annotation/json_annotation.dart'; + +import 'package:pshared/data/dto/describable.dart'; +import 'package:pshared/data/dto/ledger/balance.dart'; + +part 'account.g.dart'; + + +@JsonSerializable(includeIfNull: false, explicitToJson: true) +class LedgerAccountDTO { + final String ledgerAccountRef; + final String organizationRef; + final String? ownerRef; + final String accountCode; + final String accountType; + final String currency; + final String status; + final bool allowNegative; + final bool isSettlement; + final Map? metadata; + final DateTime? createdAt; + final DateTime? updatedAt; + + final DescribableDTO describable; + + final LedgerBalanceDTO? balance; + + const LedgerAccountDTO({ + required this.ledgerAccountRef, + required this.organizationRef, + this.ownerRef, + required this.accountCode, + required this.accountType, + required this.currency, + required this.status, + required this.allowNegative, + required this.isSettlement, + this.metadata, + this.createdAt, + this.updatedAt, + required this.describable, + this.balance, + }); + + factory LedgerAccountDTO.fromJson(Map json) => _$LedgerAccountDTOFromJson(json); + Map toJson() => _$LedgerAccountDTOToJson(this); +} diff --git a/frontend/pshared/lib/data/dto/ledger/balance.dart b/frontend/pshared/lib/data/dto/ledger/balance.dart new file mode 100644 index 00000000..5af56d38 --- /dev/null +++ b/frontend/pshared/lib/data/dto/ledger/balance.dart @@ -0,0 +1,27 @@ +import 'package:json_annotation/json_annotation.dart'; + +import 'package:pshared/data/dto/money.dart'; + +part 'balance.g.dart'; + + +@JsonSerializable( + includeIfNull: false, // <- omitempty behavior + explicitToJson: true, // <- nested DTOs call toJson() +) +class LedgerBalanceDTO { + final String ledgerAccountRef; + final MoneyDTO? balance; + final int version; + final DateTime? lastUpdated; + + const LedgerBalanceDTO({ + required this.ledgerAccountRef, + this.balance, + required this.version, + this.lastUpdated, + }); + + factory LedgerBalanceDTO.fromJson(Map json) => _$LedgerBalanceDTOFromJson(json); + Map toJson() => _$LedgerBalanceDTOToJson(this); +} diff --git a/frontend/pshared/lib/data/dto/payment/fee_line.dart b/frontend/pshared/lib/data/dto/payment/fee_line.dart index 63aa7120..a83297d8 100644 --- a/frontend/pshared/lib/data/dto/payment/fee_line.dart +++ b/frontend/pshared/lib/data/dto/payment/fee_line.dart @@ -1,6 +1,6 @@ import 'package:json_annotation/json_annotation.dart'; -import 'package:pshared/data/dto/payment/money.dart'; +import 'package:pshared/data/dto/money.dart'; part 'fee_line.g.dart'; diff --git a/frontend/pshared/lib/data/dto/payment/fx_quote.dart b/frontend/pshared/lib/data/dto/payment/fx_quote.dart index edfe8011..6487252e 100644 --- a/frontend/pshared/lib/data/dto/payment/fx_quote.dart +++ b/frontend/pshared/lib/data/dto/payment/fx_quote.dart @@ -1,6 +1,6 @@ import 'package:json_annotation/json_annotation.dart'; -import 'package:pshared/data/dto/payment/money.dart'; +import 'package:pshared/data/dto/money.dart'; part 'fx_quote.g.dart'; diff --git a/frontend/pshared/lib/data/dto/payment/intent/payment.dart b/frontend/pshared/lib/data/dto/payment/intent/payment.dart index a1da3e2b..ebb57fdc 100644 --- a/frontend/pshared/lib/data/dto/payment/intent/payment.dart +++ b/frontend/pshared/lib/data/dto/payment/intent/payment.dart @@ -3,7 +3,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pshared/data/dto/payment/endpoint.dart'; import 'package:pshared/data/dto/payment/intent/customer.dart'; import 'package:pshared/data/dto/payment/intent/fx.dart'; -import 'package:pshared/data/dto/payment/money.dart'; +import 'package:pshared/data/dto/money.dart'; part 'payment.g.dart'; diff --git a/frontend/pshared/lib/data/dto/payment/network_fee.dart b/frontend/pshared/lib/data/dto/payment/network_fee.dart index adfa1b25..b9b2f344 100644 --- a/frontend/pshared/lib/data/dto/payment/network_fee.dart +++ b/frontend/pshared/lib/data/dto/payment/network_fee.dart @@ -1,6 +1,6 @@ import 'package:json_annotation/json_annotation.dart'; -import 'package:pshared/data/dto/payment/money.dart'; +import 'package:pshared/data/dto/money.dart'; part 'network_fee.g.dart'; diff --git a/frontend/pshared/lib/data/dto/payment/payment_quote.dart b/frontend/pshared/lib/data/dto/payment/payment_quote.dart index e43fb68c..19ca95c8 100644 --- a/frontend/pshared/lib/data/dto/payment/payment_quote.dart +++ b/frontend/pshared/lib/data/dto/payment/payment_quote.dart @@ -2,7 +2,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pshared/data/dto/payment/fee_line.dart'; import 'package:pshared/data/dto/payment/fx_quote.dart'; -import 'package:pshared/data/dto/payment/money.dart'; +import 'package:pshared/data/dto/money.dart'; import 'package:pshared/data/dto/payment/network_fee.dart'; part 'payment_quote.g.dart'; diff --git a/frontend/pshared/lib/data/dto/payment/quote_aggregate.dart b/frontend/pshared/lib/data/dto/payment/quote_aggregate.dart index 140564e0..34dd779b 100644 --- a/frontend/pshared/lib/data/dto/payment/quote_aggregate.dart +++ b/frontend/pshared/lib/data/dto/payment/quote_aggregate.dart @@ -1,6 +1,6 @@ import 'package:json_annotation/json_annotation.dart'; -import 'package:pshared/data/dto/payment/money.dart'; +import 'package:pshared/data/dto/money.dart'; part 'quote_aggregate.g.dart'; diff --git a/frontend/pshared/lib/data/mapper/ledger/account.dart b/frontend/pshared/lib/data/mapper/ledger/account.dart new file mode 100644 index 00000000..464d1217 --- /dev/null +++ b/frontend/pshared/lib/data/mapper/ledger/account.dart @@ -0,0 +1,43 @@ +import 'package:pshared/data/dto/ledger/account.dart'; +import 'package:pshared/data/mapper/describable.dart'; +import 'package:pshared/data/mapper/ledger/balance.dart'; +import 'package:pshared/models/ledger/account.dart'; + + +extension LedgerAccountDtoMapper on LedgerAccountDTO { + LedgerAccount toModel() => LedgerAccount( + ledgerAccountRef: ledgerAccountRef, + organizationRef: organizationRef, + ownerRef: ownerRef, + accountCode: accountCode, + accountType: accountType, + currency: currency, + status: status, + allowNegative: allowNegative, + isSettlement: isSettlement, + metadata: metadata, + createdAt: createdAt, + updatedAt: updatedAt, + describable: describable.toDomain(), + balance: balance?.toDomain(), + ); +} + +extension LedgerAccountModelMapper on LedgerAccount { + LedgerAccountDTO toDTO() => LedgerAccountDTO( + ledgerAccountRef: ledgerAccountRef, + organizationRef: organizationRef, + ownerRef: ownerRef, + accountCode: accountCode, + accountType: accountType, + currency: currency, + status: status, + allowNegative: allowNegative, + isSettlement: isSettlement, + metadata: metadata, + createdAt: createdAt, + updatedAt: updatedAt, + describable: describable.toDTO(), + balance: balance?.toDTO(), + ); +} diff --git a/frontend/pshared/lib/data/mapper/ledger/balance.dart b/frontend/pshared/lib/data/mapper/ledger/balance.dart new file mode 100644 index 00000000..0bdab0b6 --- /dev/null +++ b/frontend/pshared/lib/data/mapper/ledger/balance.dart @@ -0,0 +1,22 @@ +import 'package:pshared/data/dto/ledger/balance.dart'; +import 'package:pshared/data/mapper/money.dart'; +import 'package:pshared/models/ledger/balance.dart'; + + +extension LedgerBalanceDtoMapper on LedgerBalanceDTO { + LedgerBalance toDomain() => LedgerBalance( + ledgerAccountRef: ledgerAccountRef, + balance: balance?.toDomain(), + version: version, + lastUpdated: lastUpdated, + ); +} + +extension LedgerBalanceModelMapper on LedgerBalance { + LedgerBalanceDTO toDTO() => LedgerBalanceDTO( + ledgerAccountRef: ledgerAccountRef, + balance: balance?.toDTO(), + version: version, + lastUpdated: lastUpdated, + ); +} diff --git a/frontend/pshared/lib/data/mapper/money.dart b/frontend/pshared/lib/data/mapper/money.dart index 9b2841b3..a2d8d9b3 100644 --- a/frontend/pshared/lib/data/mapper/money.dart +++ b/frontend/pshared/lib/data/mapper/money.dart @@ -1,4 +1,4 @@ -import 'package:pshared/data/dto/payment/money.dart'; +import 'package:pshared/data/dto/money.dart'; import 'package:pshared/models/money.dart'; diff --git a/frontend/pshared/lib/data/mapper/payment/fee_line.dart b/frontend/pshared/lib/data/mapper/payment/fee_line.dart index 4845d879..09409615 100644 --- a/frontend/pshared/lib/data/mapper/payment/fee_line.dart +++ b/frontend/pshared/lib/data/mapper/payment/fee_line.dart @@ -1,5 +1,5 @@ import 'package:pshared/data/dto/payment/fee_line.dart'; -import 'package:pshared/data/mapper/payment/money.dart'; +import 'package:pshared/data/mapper/money.dart'; import 'package:pshared/models/payment/fees/line.dart'; diff --git a/frontend/pshared/lib/data/mapper/payment/fx_quote.dart b/frontend/pshared/lib/data/mapper/payment/fx_quote.dart index c45356c7..a09dec5c 100644 --- a/frontend/pshared/lib/data/mapper/payment/fx_quote.dart +++ b/frontend/pshared/lib/data/mapper/payment/fx_quote.dart @@ -1,5 +1,5 @@ import 'package:pshared/data/dto/payment/fx_quote.dart'; -import 'package:pshared/data/mapper/payment/money.dart'; +import 'package:pshared/data/mapper/money.dart'; import 'package:pshared/models/payment/fx/quote.dart'; diff --git a/frontend/pshared/lib/data/mapper/payment/intent/payment.dart b/frontend/pshared/lib/data/mapper/payment/intent/payment.dart index 78c46d57..bab5acbd 100644 --- a/frontend/pshared/lib/data/mapper/payment/intent/payment.dart +++ b/frontend/pshared/lib/data/mapper/payment/intent/payment.dart @@ -3,7 +3,7 @@ import 'package:pshared/data/mapper/payment/payment.dart'; import 'package:pshared/data/mapper/payment/enums.dart'; import 'package:pshared/data/mapper/payment/intent/customer.dart'; import 'package:pshared/data/mapper/payment/intent/fx.dart'; -import 'package:pshared/data/mapper/payment/money.dart'; +import 'package:pshared/data/mapper/money.dart'; import 'package:pshared/models/payment/intent.dart'; diff --git a/frontend/pshared/lib/data/mapper/payment/network_fee.dart b/frontend/pshared/lib/data/mapper/payment/network_fee.dart index 9c7af9ef..ac1d697e 100644 --- a/frontend/pshared/lib/data/mapper/payment/network_fee.dart +++ b/frontend/pshared/lib/data/mapper/payment/network_fee.dart @@ -1,5 +1,5 @@ import 'package:pshared/data/dto/payment/network_fee.dart'; -import 'package:pshared/data/mapper/payment/money.dart'; +import 'package:pshared/data/mapper/money.dart'; import 'package:pshared/models/payment/fees/network.dart'; diff --git a/frontend/pshared/lib/data/mapper/payment/payment_quote.dart b/frontend/pshared/lib/data/mapper/payment/payment_quote.dart index 51bec34d..7e9dea20 100644 --- a/frontend/pshared/lib/data/mapper/payment/payment_quote.dart +++ b/frontend/pshared/lib/data/mapper/payment/payment_quote.dart @@ -1,7 +1,7 @@ import 'package:pshared/data/dto/payment/payment_quote.dart'; import 'package:pshared/data/mapper/payment/fee_line.dart'; import 'package:pshared/data/mapper/payment/fx_quote.dart'; -import 'package:pshared/data/mapper/payment/money.dart'; +import 'package:pshared/data/mapper/money.dart'; import 'package:pshared/data/mapper/payment/network_fee.dart'; import 'package:pshared/models/payment/quote/quote.dart'; diff --git a/frontend/pshared/lib/data/mapper/payment/quote/aggregate.dart b/frontend/pshared/lib/data/mapper/payment/quote/aggregate.dart index 563c0c2a..ab340283 100644 --- a/frontend/pshared/lib/data/mapper/payment/quote/aggregate.dart +++ b/frontend/pshared/lib/data/mapper/payment/quote/aggregate.dart @@ -1,5 +1,5 @@ import 'package:pshared/data/dto/payment/quote_aggregate.dart'; -import 'package:pshared/data/mapper/payment/money.dart'; +import 'package:pshared/data/mapper/money.dart'; import 'package:pshared/models/payment/quote/aggregate.dart'; diff --git a/frontend/pshared/lib/data/mapper/wallet/ui.dart b/frontend/pshared/lib/data/mapper/wallet/ui.dart index 7ce5a4e5..c674d6c6 100644 --- a/frontend/pshared/lib/data/mapper/wallet/ui.dart +++ b/frontend/pshared/lib/data/mapper/wallet/ui.dart @@ -9,7 +9,6 @@ extension WalletUiMapper on domain.WalletModel { walletUserID: walletRef, balance: double.tryParse(availableMoney?.amount ?? balance?.available?.amount ?? '0') ?? 0, currency: currencyStringToCode(asset.tokenSymbol), - isHidden: true, calculatedAt: balance?.calculatedAt ?? DateTime.now(), depositAddress: depositAddress, network: asset.chain, diff --git a/frontend/pshared/lib/models/ledger/account.dart b/frontend/pshared/lib/models/ledger/account.dart index 1486a2a5..f2dabb1a 100644 --- a/frontend/pshared/lib/models/ledger/account.dart +++ b/frontend/pshared/lib/models/ledger/account.dart @@ -1,4 +1,5 @@ import 'package:pshared/models/describable.dart'; +import 'package:pshared/models/ledger/balance.dart'; class LedgerAccount implements Describable { @@ -15,6 +16,7 @@ class LedgerAccount implements Describable { final DateTime? createdAt; final DateTime? updatedAt; final Describable describable; + final LedgerBalance? balance; @override String get name => describable.name; @@ -36,6 +38,7 @@ class LedgerAccount implements Describable { this.createdAt, this.updatedAt, required this.describable, + this.balance, }); LedgerAccount copyWith({ @@ -54,5 +57,6 @@ class LedgerAccount implements Describable { createdAt: createdAt, updatedAt: updatedAt, describable: describable ?? this.describable, + balance: balance, ); } diff --git a/frontend/pshared/lib/models/ledger/balance.dart b/frontend/pshared/lib/models/ledger/balance.dart new file mode 100644 index 00000000..c4b407bd --- /dev/null +++ b/frontend/pshared/lib/models/ledger/balance.dart @@ -0,0 +1,16 @@ +import 'package:pshared/models/money.dart'; + + +class LedgerBalance { + final String ledgerAccountRef; + final Money? balance; + final int version; + final DateTime? lastUpdated; + + const LedgerBalance({ + required this.ledgerAccountRef, + this.balance, + required this.version, + this.lastUpdated, + }); +} diff --git a/frontend/pshared/lib/models/payment/wallet.dart b/frontend/pshared/lib/models/payment/wallet.dart index 24ee7d56..899143a9 100644 --- a/frontend/pshared/lib/models/payment/wallet.dart +++ b/frontend/pshared/lib/models/payment/wallet.dart @@ -8,7 +8,6 @@ class Wallet implements Describable { final String walletUserID; // ID or number that we show the user final double balance; final Currency currency; - final bool isHidden; final DateTime calculatedAt; final String? depositAddress; final ChainNetwork? network; @@ -29,7 +28,6 @@ class Wallet implements Describable { required this.currency, required this.calculatedAt, required this.describable, - this.isHidden = true, this.depositAddress, this.network, this.tokenSymbol, @@ -37,32 +35,18 @@ class Wallet implements Describable { }); Wallet copyWith({ - String? id, - double? balance, - Currency? currency, - String? walletUserID, - bool? isHidden, - String? depositAddress, - ChainNetwork? network, - String? tokenSymbol, - String? contractAddress, Describable? describable, - String? name, - String? Function()? description, + double? balance, }) => Wallet( - id: id ?? this.id, + id: id, balance: balance ?? this.balance, - currency: currency ?? this.currency, - walletUserID: walletUserID ?? this.walletUserID, - isHidden: isHidden ?? this.isHidden, + currency: currency, + walletUserID: walletUserID, calculatedAt: calculatedAt, - depositAddress: depositAddress ?? this.depositAddress, - network: network ?? this.network, - tokenSymbol: tokenSymbol ?? this.tokenSymbol, - contractAddress: contractAddress ?? this.contractAddress, - describable: describable - ?? (name != null || description != null - ? this.describable.copyWith(name: name, description: description) - : this.describable), + depositAddress: depositAddress, + network: network, + tokenSymbol: tokenSymbol, + contractAddress: contractAddress, + describable: describable ?? this.describable, ); } diff --git a/frontend/pshared/lib/provider/payment/quotation/intent_builder.dart b/frontend/pshared/lib/provider/payment/quotation/intent_builder.dart index 94107297..eb4072ff 100644 --- a/frontend/pshared/lib/provider/payment/quotation/intent_builder.dart +++ b/frontend/pshared/lib/provider/payment/quotation/intent_builder.dart @@ -1,5 +1,6 @@ import 'package:collection/collection.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/models/payment/currency_pair.dart'; import 'package:pshared/models/payment/customer.dart'; import 'package:pshared/models/payment/fx/intent.dart'; @@ -13,7 +14,6 @@ import 'package:pshared/models/payment/intent.dart'; import 'package:pshared/models/recipient/recipient.dart'; import 'package:pshared/provider/payment/amount.dart'; import 'package:pshared/provider/payment/flow.dart'; -import 'package:pshared/provider/payment/wallets.dart'; import 'package:pshared/provider/recipient/provider.dart'; import 'package:pshared/provider/recipient/pmethods.dart'; import 'package:pshared/utils/currency.dart'; @@ -22,7 +22,7 @@ import 'package:pshared/utils/currency.dart'; class QuotationIntentBuilder { PaymentIntent? build({ required PaymentAmountProvider payment, - required WalletsProvider wallets, + required WalletsController wallets, required PaymentFlowProvider flow, required RecipientsProvider recipients, required PaymentMethodsProvider methods, diff --git a/frontend/pshared/lib/provider/payment/quotation/quotation.dart b/frontend/pshared/lib/provider/payment/quotation/quotation.dart index c14985ce..3a275b38 100644 --- a/frontend/pshared/lib/provider/payment/quotation/quotation.dart +++ b/frontend/pshared/lib/provider/payment/quotation/quotation.dart @@ -1,11 +1,13 @@ +import 'dart:convert'; + import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; -import 'dart:convert'; import 'package:uuid/uuid.dart'; import 'package:pshared/api/requests/payment/quote.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/data/mapper/payment/intent/payment.dart'; import 'package:pshared/models/asset.dart'; import 'package:pshared/models/payment/intent.dart'; @@ -14,7 +16,6 @@ import 'package:pshared/models/money.dart'; import 'package:pshared/provider/organizations.dart'; import 'package:pshared/provider/payment/amount.dart'; import 'package:pshared/provider/payment/flow.dart'; -import 'package:pshared/provider/payment/wallets.dart'; import 'package:pshared/provider/recipient/provider.dart'; import 'package:pshared/provider/recipient/pmethods.dart'; import 'package:pshared/provider/resource.dart'; @@ -34,7 +35,7 @@ class QuotationProvider extends ChangeNotifier { void update( OrganizationsProvider venue, PaymentAmountProvider payment, - WalletsProvider wallets, + WalletsController wallets, PaymentFlowProvider flow, RecipientsProvider recipients, PaymentMethodsProvider methods, diff --git a/frontend/pshared/lib/provider/payment/wallets.dart b/frontend/pshared/lib/provider/payment/wallets.dart index 5e24ae5f..03c7b796 100644 --- a/frontend/pshared/lib/provider/payment/wallets.dart +++ b/frontend/pshared/lib/provider/payment/wallets.dart @@ -1,5 +1,9 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:flutter/foundation.dart'; + import 'package:collection/collection.dart'; -import 'package:flutter/material.dart'; import 'package:pshared/models/payment/wallet.dart'; import 'package:pshared/provider/organizations.dart'; @@ -8,10 +12,9 @@ import 'package:pshared/service/payment/wallets.dart'; import 'package:pshared/utils/exception.dart'; - class WalletsProvider with ChangeNotifier { final WalletsService _service; - late OrganizationsProvider _organizations; + OrganizationsProvider? _organizations; WalletsProvider(this._service); @@ -22,126 +25,204 @@ class WalletsProvider with ChangeNotifier { bool get isLoading => _resource.isLoading; Exception? get error => _resource.error; - Wallet? _selectedWallet; - Wallet? get selectedWallet => _selectedWallet; - final bool _isHidden = true; - bool get isHidden => _isHidden; - bool _isRefreshingBalances = false; bool get isRefreshingBalances => _isRefreshingBalances; + final Set _refreshingWallets = {}; bool isWalletRefreshing(String walletId) => _refreshingWallets.contains(walletId); + // Expose current org id so UI controller can reset per-org state if needed. + String? get organizationId => + (_organizations?.isOrganizationSet ?? false) ? _organizations!.current.id : null; + + // Used to ignore stale async results (org changes / overlapping requests). + int _opSeq = 0; + + // Per-wallet refresh sequence guard. + final Map _walletSeq = {}; + + // Keep modest concurrency to avoid hammering the backend. + static const int _balanceConcurrency = 6; + void update(OrganizationsProvider organizations) { _organizations = organizations; - if (_organizations.isOrganizationSet) loadWalletsWithBalances(); + if (organizations.isOrganizationSet) { + unawaited(loadWalletsWithBalances()); + } } Future updateWallet(Wallet newWallet) { throw Exception('update wallet is not implemented'); } - void selectWallet(Wallet wallet) => _setSelectedWallet(wallet); - Future loadWalletsWithBalances() async { - _setResource(_resource.copyWith(isLoading: true, error: null)); + final org = _organizations; + if (org == null || !org.isOrganizationSet) return; + + final orgId = org.current.id; + final seq = ++_opSeq; + + _isRefreshingBalances = false; + _refreshingWallets.clear(); + + _applyResource(_resource.copyWith(isLoading: true, error: null), notify: true); + try { - final base = await _service.getWallets(_organizations.current.id); - final withBalances = []; - for (final wallet in base) { - try { - final balance = await _service.getBalance(_organizations.current.id, wallet.id); - withBalances.add(wallet.copyWith(balance: balance)); - } catch (e) { - _setResource(_resource.copyWith(error: toException(e))); - withBalances.add(wallet); - } - } - _setResource(Resource(data: withBalances, isLoading: false, error: _resource.error)); + final base = await _service.getWallets(orgId); + + final result = await _withBalances(orgId, base); + if (seq != _opSeq) return; + + _applyResource( + Resource>( + data: result.wallets, + isLoading: false, + error: result.error, + ), + notify: true, + ); } catch (e) { - _setResource(_resource.copyWith(isLoading: false, error: toException(e))); + if (seq != _opSeq) return; + + _applyResource( + _resource.copyWith(isLoading: false, error: toException(e)), + notify: true, + ); } } Future refreshBalances() async { + final org = _organizations; + if (org == null || !org.isOrganizationSet) return; if (wallets.isEmpty) return; + + final orgId = org.current.id; + final seq = ++_opSeq; + _isRefreshingBalances = true; + _applyResource(_resource.copyWith(error: null), notify: false); notifyListeners(); try { - final updated = []; - for (final wallet in wallets) { - final balance = await _service.getBalance(_organizations.current.id, wallet.id); - updated.add(wallet.copyWith(balance: balance)); - } - _setResource(_resource.copyWith(data: updated)); + final result = await _withBalances(orgId, wallets); + if (seq != _opSeq) return; + + _applyResource( + _resource.copyWith(data: result.wallets, error: result.error), + notify: false, + ); } catch (e) { - _setResource(_resource.copyWith(error: toException(e))); + if (seq != _opSeq) return; + + _applyResource(_resource.copyWith(error: toException(e)), notify: false); } finally { - _isRefreshingBalances = false; - notifyListeners(); + if (seq == _opSeq) { + _isRefreshingBalances = false; + notifyListeners(); + } } } Future refreshBalance(String walletId) async { + final org = _organizations; + if (org == null || !org.isOrganizationSet) return; + if (_refreshingWallets.contains(walletId)) return; - final wallet = wallets.firstWhereOrNull((w) => w.id == walletId); - if (wallet == null) return; + + final existing = wallets.firstWhereOrNull((w) => w.id == walletId); + if (existing == null) return; + + final orgId = org.current.id; + final seq = (_walletSeq[walletId] ?? 0) + 1; + _walletSeq[walletId] = seq; _refreshingWallets.add(walletId); notifyListeners(); try { - final balance = await _service.getBalance(_organizations.current.id, walletId); - final updatedWallet = wallet.copyWith(balance: balance); - final next = List.from(wallets); - final idx = next.indexWhere((w) => w.id == walletId); - if (idx >= 0) { - next[idx] = updatedWallet; - _setResource(_resource.copyWith(data: next)); - } + final balance = await _service.getBalance(orgId, walletId); + if ((_walletSeq[walletId] ?? 0) != seq) return; + + final next = _replaceWallet(walletId, (w) => w.copyWith(balance: balance)); + if (next == null) return; + + _applyResource(_resource.copyWith(data: next), notify: false); } catch (e) { - _setResource(_resource.copyWith(error: toException(e))); + if ((_walletSeq[walletId] ?? 0) != seq) return; + + _applyResource(_resource.copyWith(error: toException(e)), notify: false); } finally { - _refreshingWallets.remove(walletId); - notifyListeners(); + if ((_walletSeq[walletId] ?? 0) == seq) { + _refreshingWallets.remove(walletId); + notifyListeners(); + } } } - void toggleVisibility(String walletId) { - final index = wallets.indexWhere((w) => w.id == walletId); - if (index < 0) return; - final wallet = wallets[index]; - final updated = wallet.copyWith(isHidden: !wallet.isHidden); - final next = List.from(wallets); - next[index] = updated; - _setResource(_resource.copyWith(data: next)); - if (_selectedWallet?.id == walletId) { - _selectedWallet = updated; - } - } + // ---------- internals ---------- - void _setResource(Resource> newResource) { + void _applyResource(Resource> newResource, {required bool notify}) { _resource = newResource; - _selectedWallet = _resolveSelectedWallet(_selectedWallet, wallets); - notifyListeners(); + if (notify) notifyListeners(); } - Wallet? _resolveSelectedWallet(Wallet? current, List available) { - if (available.isEmpty) return null; - final currentId = current?.id; - if (currentId != null) { - final existing = available.firstWhereOrNull((wallet) => wallet.id == currentId); - if (existing != null) return existing; - } - return available.firstWhereOrNull((wallet) => !wallet.isHidden) ?? available.first; + List? _replaceWallet(String walletId, Wallet Function(Wallet) updater) { + final idx = wallets.indexWhere((w) => w.id == walletId); + if (idx < 0) return null; + + final next = List.from(wallets); + next[idx] = updater(next[idx]); + return next; } - void _setSelectedWallet(Wallet wallet) { - if (_selectedWallet?.id == wallet.id && _selectedWallet?.isHidden == wallet.isHidden) { - return; + Future<_WalletLoadResult> _withBalances(String orgId, List base) async { + Exception? firstError; + + final withBalances = await _mapConcurrent( + base, + _balanceConcurrency, + (wallet) async { + try { + final balance = await _service.getBalance(orgId, wallet.id); + return wallet.copyWith(balance: balance); + } catch (e) { + firstError ??= toException(e); + return wallet; + } + }, + ); + + return _WalletLoadResult(withBalances, firstError); + } + + static Future> _mapConcurrent( + List items, + int concurrency, + Future Function(T) fn, + ) async { + if (items.isEmpty) return []; + + final results = List.filled(items.length, null); + var nextIndex = 0; + + Future worker() async { + while (true) { + final i = nextIndex++; + if (i >= items.length) return; + results[i] = await fn(items[i]); + } } - _selectedWallet = wallet; - notifyListeners(); + + final workers = List.generate(min(concurrency, items.length), (_) => worker()); + await Future.wait(workers); + + return results.cast(); } } + +class _WalletLoadResult { + final List wallets; + final Exception? error; + + const _WalletLoadResult(this.wallets, this.error); +} diff --git a/frontend/pweb/lib/app/router/payout_shell.dart b/frontend/pweb/lib/app/router/payout_shell.dart index eaeb30bb..ee55711e 100644 --- a/frontend/pweb/lib/app/router/payout_shell.dart +++ b/frontend/pweb/lib/app/router/payout_shell.dart @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/models/payment/type.dart'; import 'package:pshared/models/recipient/recipient.dart'; import 'package:pshared/provider/organizations.dart'; @@ -28,7 +29,6 @@ import 'package:pweb/pages/payout_page/wallet/edit/page.dart'; import 'package:pweb/pages/report/page.dart'; import 'package:pweb/pages/settings/profile/page.dart'; import 'package:pweb/pages/wallet_top_up/page.dart'; -import 'package:pshared/provider/payment/wallets.dart'; import 'package:pweb/widgets/error/snackbar.dart'; import 'package:pweb/widgets/sidebar/destinations.dart'; import 'package:pweb/widgets/sidebar/page.dart'; @@ -53,7 +53,7 @@ RouteBase payoutShellRoute() => ShellRoute( ChangeNotifierProvider( create: (_) => PaymentAmountProvider(), ), - ChangeNotifierProxyProvider6( + ChangeNotifierProxyProvider6( create: (_) => QuotationProvider(), update: (_, organization, payment, wallet, flow, recipients, methods, provider) => provider!..update(organization, payment, wallet, flow, recipients, methods), @@ -217,7 +217,7 @@ RouteBase payoutShellRoute() => ShellRoute( name: PayoutRoutes.editWallet, path: PayoutRoutes.editWalletPath, pageBuilder: (context, state) { - final walletsProvider = context.read(); + final walletsProvider = context.read(); final wallet = walletsProvider.selectedWallet; final loc = AppLocalizations.of(context)!; final fallbackDestination = PayoutRoutes.fallbackFromState( @@ -279,7 +279,7 @@ void _openWalletEdit( Wallet wallet, { required PayoutDestination returnTo, }) { - context.read().selectWallet(wallet); + context.read().selectWallet(wallet); context.pushToEditWallet(returnTo: returnTo); } @@ -288,7 +288,7 @@ void _openWalletTopUp( Wallet wallet, { required PayoutDestination returnTo, }) { - context.read().selectWallet(wallet); + context.read().selectWallet(wallet); context.pushToWalletTopUp(returnTo: returnTo); } diff --git a/frontend/pweb/lib/main.dart b/frontend/pweb/lib/main.dart index cd36f953..7293e2d2 100644 --- a/frontend/pweb/lib/main.dart +++ b/frontend/pweb/lib/main.dart @@ -20,6 +20,7 @@ import 'package:pshared/provider/invitations.dart'; import 'package:pshared/service/payment/wallets.dart'; import 'package:pweb/app/app.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pweb/pages/invitations/widgets/list/view_model.dart'; import 'package:pweb/app/timeago.dart'; import 'package:pweb/providers/carousel.dart'; @@ -98,6 +99,10 @@ void main() async { create: (_) => WalletsProvider(ApiWalletsService()), update: (context, organizations, provider) => provider!..update(organizations), ), + ChangeNotifierProxyProvider( + create: (_) => WalletsController(), + update: (_, wallets, controller) => controller!..update(wallets), + ), ChangeNotifierProvider( create: (_) => WalletTransactionsProvider(MockWalletTransactionsService())..load(), ), diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/amount.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/amount.dart index 4c0b9f8d..ed240fae 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/amount.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/amount.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/utils/currency.dart'; @@ -23,11 +25,13 @@ class BalanceAmount extends StatelessWidget { final textTheme = Theme.of(context).textTheme; final colorScheme = Theme.of(context).colorScheme; final currencyBalance = currencyCodeToSymbol(wallet.currency); + final wallets = context.read(); return Row( children: [ Text( - wallet.isHidden ? '•••• $currencyBalance' : '${amountToString(wallet.balance)} $currencyBalance', + + wallets.isHidden(wallet.id) ? '•••• $currencyBalance' : '${amountToString(wallet.balance)} $currencyBalance', style: textTheme.headlineSmall?.copyWith( fontWeight: FontWeight.bold, color: colorScheme.onSurface, @@ -37,7 +41,7 @@ class BalanceAmount extends StatelessWidget { GestureDetector( onTap: onToggleVisibility, child: Icon( - wallet.isHidden ? Icons.visibility_off : Icons.visibility, + wallets.isHidden(wallet.id) ? Icons.visibility_off : Icons.visibility, size: _iconSize, color: colorScheme.onSurface, ), diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/balance.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/balance.dart index ccedb116..6f6b1e40 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/balance.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/balance.dart @@ -2,9 +2,10 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/models/payment/wallet.dart'; + import 'package:pweb/pages/dashboard/buttons/balance/carousel.dart'; -import 'package:pshared/provider/payment/wallets.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; @@ -16,24 +17,23 @@ class BalanceWidget extends StatelessWidget { @override Widget build(BuildContext context) { - final walletsProvider = context.watch(); + final walletsController = context.watch(); final loc = AppLocalizations.of(context)!; - if (walletsProvider.isLoading) { + if (walletsController.isLoading) { return const Center(child: CircularProgressIndicator()); } - final wallets = walletsProvider.wallets; + final wallets = walletsController.wallets; if (wallets.isEmpty) { return Center(child: Text(loc.noWalletsAvailable)); } - return - WalletCarousel( - wallets: wallets, - onWalletChanged: walletsProvider.selectWallet, - onTopUp: onTopUp, - ); + return WalletCarousel( + wallets: wallets, + onWalletChanged: walletsController.selectWallet, + onTopUp: onTopUp, + ); } } diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart index 2cfd42cd..327843b8 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart @@ -2,12 +2,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/models/payment/wallet.dart'; + import 'package:pweb/pages/dashboard/buttons/balance/add_funds.dart'; import 'package:pweb/pages/dashboard/buttons/balance/amount.dart'; import 'package:pweb/pages/dashboard/buttons/balance/config.dart'; import 'package:pweb/pages/dashboard/buttons/balance/header.dart'; -import 'package:pshared/provider/payment/wallets.dart'; import 'package:pweb/widgets/wallet_balance_refresh_button.dart'; @@ -43,7 +44,7 @@ class WalletCard extends StatelessWidget { BalanceAmount( wallet: wallet, onToggleVisibility: () { - context.read().toggleVisibility(wallet.id); + context.read().toggleVisibility(wallet.id); }, ), WalletBalanceRefreshButton( diff --git a/frontend/pweb/lib/pages/dashboard/payouts/summary/widget.dart b/frontend/pweb/lib/pages/dashboard/payouts/summary/widget.dart index 36e91e93..34dd2287 100644 --- a/frontend/pweb/lib/pages/dashboard/payouts/summary/widget.dart +++ b/frontend/pweb/lib/pages/dashboard/payouts/summary/widget.dart @@ -2,13 +2,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/utils/currency.dart'; import 'package:pweb/pages/dashboard/payouts/summary/fee.dart'; import 'package:pweb/pages/dashboard/payouts/summary/recipient_receives.dart'; import 'package:pweb/pages/dashboard/payouts/summary/sent_amount.dart'; import 'package:pweb/pages/dashboard/payouts/summary/total.dart'; -import 'package:pshared/provider/payment/wallets.dart'; class PaymentSummary extends StatelessWidget { @@ -22,7 +22,7 @@ class PaymentSummary extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - PaymentSentAmountRow(currency: currencyStringToCode(context.read().selectedWallet?.tokenSymbol ?? 'USDT')), + PaymentSentAmountRow(currency: currencyStringToCode(context.read().selectedWallet?.tokenSymbol ?? 'USDT')), const PaymentFeeRow(), const PaymentRecipientReceivesRow(), SizedBox(height: spacing), diff --git a/frontend/pweb/lib/pages/payment_methods/page.dart b/frontend/pweb/lib/pages/payment_methods/page.dart index a1d4ced1..62facda0 100644 --- a/frontend/pweb/lib/pages/payment_methods/page.dart +++ b/frontend/pweb/lib/pages/payment_methods/page.dart @@ -2,13 +2,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/models/payment/type.dart'; import 'package:pshared/models/recipient/recipient.dart'; import 'package:pshared/provider/payment/flow.dart'; import 'package:pshared/provider/payment/provider.dart'; import 'package:pshared/provider/recipient/pmethods.dart'; import 'package:pshared/provider/recipient/provider.dart'; -import 'package:pshared/provider/payment/wallets.dart'; import 'package:pweb/pages/payment_methods/payment_page/body.dart'; import 'package:pweb/widgets/sidebar/destinations.dart'; @@ -108,7 +108,7 @@ class _PaymentPageState extends State { recipient: recipient, recipientProvider: recipientProvider, methodsProvider: methodsProvider, - onWalletSelected: context.read().selectWallet, + onWalletSelected: context.read().selectWallet, searchController: _searchController, searchFocusNode: _searchFocusNode, onSearchChanged: _handleSearchChanged, diff --git a/frontend/pweb/lib/pages/payment_methods/payment_page/content.dart b/frontend/pweb/lib/pages/payment_methods/payment_page/content.dart index 59b9348c..0eac324a 100644 --- a/frontend/pweb/lib/pages/payment_methods/payment_page/content.dart +++ b/frontend/pweb/lib/pages/payment_methods/payment_page/content.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/models/payment/wallet.dart'; import 'package:pshared/models/recipient/recipient.dart'; -import 'package:pshared/provider/payment/wallets.dart'; import 'package:pshared/provider/recipient/provider.dart'; import 'package:pweb/pages/payment_methods/payment_page/back_button.dart'; @@ -81,7 +81,7 @@ class PaymentPageContent extends StatelessWidget { Row( children: [ Expanded(child: SectionTitle(loc.sourceOfFunds)), - Consumer( + Consumer( builder: (context, provider, _) { final selectedWalletId = provider.selectedWallet?.id; if (selectedWalletId == null) { diff --git a/frontend/pweb/lib/pages/payment_methods/payment_page/method_selector.dart b/frontend/pweb/lib/pages/payment_methods/payment_page/method_selector.dart index ba4c3fca..6686dc1f 100644 --- a/frontend/pweb/lib/pages/payment_methods/payment_page/method_selector.dart +++ b/frontend/pweb/lib/pages/payment_methods/payment_page/method_selector.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/models/payment/wallet.dart'; -import 'package:pshared/provider/payment/wallets.dart'; import 'package:pweb/utils/payment/dropdown.dart'; @@ -17,7 +17,7 @@ class PaymentMethodSelector extends StatelessWidget { }); @override - Widget build(BuildContext context) => Consumer( + Widget build(BuildContext context) => Consumer( builder: (context, provider, _) => PaymentMethodDropdown( methods: provider.wallets, selectedMethod: provider.selectedWallet, diff --git a/frontend/pweb/lib/pages/payout_page/wallet/card.dart b/frontend/pweb/lib/pages/payout_page/wallet/card.dart index b77c22f7..bfcf182b 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/card.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/card.dart @@ -2,11 +2,11 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/utils/currency.dart'; import 'package:pshared/models/payment/wallet.dart'; -import 'package:pshared/provider/payment/wallets.dart'; -import 'package:pweb/models/visibility.dart'; +import 'package:pweb/models/visibility.dart'; import 'package:pweb/pages/dashboard/buttons/balance/amount.dart'; import 'package:pweb/widgets/wallet_balance_refresh_button.dart'; @@ -51,7 +51,7 @@ class WalletCard extends StatelessWidget { BalanceAmount( wallet: wallet, onToggleVisibility: () { - context.read().toggleVisibility(wallet.id); + context.read().toggleVisibility(wallet.id); }, ), WalletBalanceRefreshButton( diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/send.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/send.dart index 878f7b79..223238a0 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/send.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/send.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pshared/models/payment/type.dart'; -import 'package:pshared/provider/payment/wallets.dart'; import 'package:pweb/app/router/payout_routes.dart'; import 'package:pweb/widgets/sidebar/destinations.dart'; @@ -23,8 +23,8 @@ class SendPayoutButton extends StatelessWidget { elevation: 0, ), onPressed: () { - final walletsProvider = context.read(); - final wallet = walletsProvider.selectedWallet; + final wallets = context.read(); + final wallet = wallets.selectedWallet; if (wallet != null) { context.pushToPayment( diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/top_up.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/top_up.dart index c2d6c952..ef377052 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/top_up.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/buttons/top_up.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/provider/payment/wallets.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pweb/app/router/payout_routes.dart'; import 'package:pweb/widgets/sidebar/destinations.dart'; @@ -22,7 +22,7 @@ class TopUpButton extends StatelessWidget{ elevation: 0, ), onPressed: () { - final wallet = context.read().selectedWallet; + final wallet = context.read().selectedWallet; if (wallet == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(loc.noWalletSelected)), diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/fields.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/fields.dart index bb56870c..819b1744 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/fields.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/fields.dart @@ -3,7 +3,7 @@ import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/provider/payment/wallets.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pweb/pages/dashboard/buttons/balance/amount.dart'; import 'package:pweb/widgets/wallet_balance_refresh_button.dart'; @@ -14,9 +14,9 @@ class WalletEditFields extends StatelessWidget { @override Widget build(BuildContext context) { - return Consumer( - builder: (context, provider, child) { - final wallet = provider.selectedWallet; + return Consumer( + builder: (context, controller, _) { + final wallet = controller.selectedWallet; if (wallet == null) { return SizedBox.shrink(); @@ -30,9 +30,7 @@ class WalletEditFields extends StatelessWidget { Expanded( child: BalanceAmount( wallet: wallet, - onToggleVisibility: () { - context.read().toggleVisibility(wallet.id); - }, + onToggleVisibility: () => controller.toggleVisibility(wallet.id), ), ), WalletBalanceRefreshButton(walletId: wallet.id), diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart index df0452bf..61175599 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/provider/payment/wallets.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pweb/generated/i18n/app_localizations.dart'; @@ -12,8 +12,8 @@ class WalletEditHeader extends StatelessWidget { @override Widget build(BuildContext context) { - final provider = context.watch(); - final wallet = provider.selectedWallet; + final controller = context.watch(); + final wallet = controller.selectedWallet; final loc = AppLocalizations.of(context)!; if (wallet == null) { diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/page.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/page.dart index 843a6f7f..0a778a6f 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/page.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/page.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/provider/payment/wallets.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pweb/pages/payout_page/wallet/edit/buttons/buttons.dart'; import 'package:pweb/pages/payout_page/wallet/edit/fields.dart'; @@ -23,9 +23,9 @@ class WalletEditPage extends StatelessWidget { final dimensions = AppDimensions(); final loc = AppLocalizations.of(context)!; - return Consumer( - builder: (context, provider, child) { - final wallet = provider.selectedWallet; + return Consumer( + builder: (context, controller, child) { + final wallet = controller.selectedWallet; if (wallet == null) { return Center(child: Text(loc.noWalletSelected)); diff --git a/frontend/pweb/lib/pages/wallet_top_up/page.dart b/frontend/pweb/lib/pages/wallet_top_up/page.dart index 00e02b91..6e0e30c3 100644 --- a/frontend/pweb/lib/pages/wallet_top_up/page.dart +++ b/frontend/pweb/lib/pages/wallet_top_up/page.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:pshared/provider/payment/wallets.dart'; +import 'package:pshared/controllers/wallets.dart'; import 'package:pweb/pages/wallet_top_up/content.dart'; @@ -18,28 +18,26 @@ class WalletTopUpPage extends StatelessWidget { Widget build(BuildContext context) { final loc = AppLocalizations.of(context)!; - return Consumer( - builder: (context, provider, child) { - if (provider.isLoading) { - return const Center(child: CircularProgressIndicator()); - } + return Consumer(builder: (context, provider, child) { + if (provider.isLoading) { + return const Center(child: CircularProgressIndicator()); + } - if (provider.error != null) { - return Center( - child: Text(loc.notificationError(provider.error.toString())), - ); - } - - final wallet = provider.selectedWallet; - if (wallet == null) { - return Center(child: Text(loc.noWalletSelected)); - } - - return WalletTopUpContent( - wallet: wallet, - onBack: onBack, + if (provider.error != null) { + return Center( + child: Text(loc.notificationError(provider.error.toString())), ); - }, - ); + } + + final wallet = provider.selectedWallet; + if (wallet == null) { + return Center(child: Text(loc.noWalletSelected)); + } + + return WalletTopUpContent( + wallet: wallet, + onBack: onBack, + ); + }); } } -- 2.49.1