Merge pull request 'Refresh button for balance' (#219) from SEND022 into main
Some checks failed
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/mntx_gateway Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline failed
Some checks failed
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/mntx_gateway Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline failed
Reviewed-on: #219
This commit was merged in pull request #219.
This commit is contained in:
@@ -29,6 +29,8 @@ class WalletsProvider with ChangeNotifier {
|
||||
|
||||
bool _isRefreshingBalances = false;
|
||||
bool get isRefreshingBalances => _isRefreshingBalances;
|
||||
final Set<String> _refreshingWallets = <String>{};
|
||||
bool isWalletRefreshing(String walletId) => _refreshingWallets.contains(walletId);
|
||||
|
||||
void update(OrganizationsProvider organizations) {
|
||||
_organizations = organizations;
|
||||
@@ -81,6 +83,31 @@ class WalletsProvider with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refreshBalance(String walletId) async {
|
||||
if (_refreshingWallets.contains(walletId)) return;
|
||||
final wallet = wallets.firstWhereOrNull((w) => w.id == walletId);
|
||||
if (wallet == null) return;
|
||||
|
||||
_refreshingWallets.add(walletId);
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
final balance = await _service.getBalance(_organizations.current.id, walletId);
|
||||
final updatedWallet = wallet.copyWith(balance: balance);
|
||||
final next = List<Wallet>.from(wallets);
|
||||
final idx = next.indexWhere((w) => w.id == walletId);
|
||||
if (idx >= 0) {
|
||||
next[idx] = updatedWallet;
|
||||
_setResource(_resource.copyWith(data: next));
|
||||
}
|
||||
} catch (e) {
|
||||
_setResource(_resource.copyWith(error: toException(e)));
|
||||
} finally {
|
||||
_refreshingWallets.remove(walletId);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void toggleVisibility(String walletId) {
|
||||
final index = wallets.indexWhere((w) => w.id == walletId);
|
||||
if (index < 0) return;
|
||||
|
||||
@@ -383,6 +383,7 @@
|
||||
"payout": "Payout",
|
||||
"sendTo": "Send Payout To",
|
||||
"send": "Send Payout",
|
||||
"refreshBalance": "Refresh balance",
|
||||
"recipientPaysFee": "Recipient pays the fee",
|
||||
|
||||
"sentAmount": "Sent amount: {amount}",
|
||||
|
||||
@@ -383,6 +383,7 @@
|
||||
"payout": "Выплата",
|
||||
"sendTo": "Отправить выплату",
|
||||
"send": "Отправить выплату",
|
||||
"refreshBalance": "Обновить баланс",
|
||||
"recipientPaysFee": "Получатель оплачивает комиссию",
|
||||
|
||||
"sentAmount": "Отправленная сумма: {amount}",
|
||||
|
||||
@@ -8,6 +8,7 @@ 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';
|
||||
|
||||
|
||||
class WalletCard extends StatelessWidget {
|
||||
@@ -37,11 +38,18 @@ class WalletCard extends StatelessWidget {
|
||||
walletNetwork: wallet.network,
|
||||
tokenSymbol: wallet.tokenSymbol,
|
||||
),
|
||||
BalanceAmount(
|
||||
wallet: wallet,
|
||||
onToggleVisibility: () {
|
||||
context.read<WalletsProvider>().toggleVisibility(wallet.id);
|
||||
},
|
||||
Row(
|
||||
children: [
|
||||
BalanceAmount(
|
||||
wallet: wallet,
|
||||
onToggleVisibility: () {
|
||||
context.read<WalletsProvider>().toggleVisibility(wallet.id);
|
||||
},
|
||||
),
|
||||
WalletBalanceRefreshButton(
|
||||
walletId: wallet.id,
|
||||
),
|
||||
],
|
||||
),
|
||||
BalanceAddFunds(
|
||||
onTopUp: () {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.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';
|
||||
@@ -14,6 +17,7 @@ import 'package:pweb/pages/payment_methods/widgets/recipient_section.dart';
|
||||
import 'package:pweb/pages/payment_methods/widgets/section_title.dart';
|
||||
import 'package:pweb/utils/dimensions.dart';
|
||||
import 'package:pweb/widgets/sidebar/destinations.dart';
|
||||
import 'package:pweb/widgets/wallet_balance_refresh_button.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
@@ -74,7 +78,20 @@ class PaymentPageContent extends StatelessWidget {
|
||||
SizedBox(height: dimensions.paddingSmall),
|
||||
PaymentHeader(),
|
||||
SizedBox(height: dimensions.paddingXXLarge),
|
||||
SectionTitle(loc.sourceOfFunds),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: SectionTitle(loc.sourceOfFunds)),
|
||||
Consumer<WalletsProvider>(
|
||||
builder: (context, provider, _) {
|
||||
final selectedWalletId = provider.selectedWallet?.id;
|
||||
if (selectedWalletId == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return WalletBalanceRefreshButton(walletId: selectedWalletId);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: dimensions.paddingSmall),
|
||||
PaymentMethodSelector(
|
||||
onMethodChanged: onWalletSelected,
|
||||
|
||||
@@ -5,8 +5,10 @@ import 'package:provider/provider.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/pages/dashboard/buttons/balance/amount.dart';
|
||||
import 'package:pweb/widgets/wallet_balance_refresh_button.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
@@ -43,11 +45,20 @@ class WalletCard extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
BalanceAmount(
|
||||
wallet: wallet,
|
||||
onToggleVisibility: () {
|
||||
context.read<WalletsProvider>().toggleVisibility(wallet.id);
|
||||
},
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BalanceAmount(
|
||||
wallet: wallet,
|
||||
onToggleVisibility: () {
|
||||
context.read<WalletsProvider>().toggleVisibility(wallet.id);
|
||||
},
|
||||
),
|
||||
WalletBalanceRefreshButton(
|
||||
walletId: wallet.id,
|
||||
iconOnly: VisibilityState.hidden,
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
AppLocalizations.of(context)!.paymentTypeCryptoWallet,
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:pshared/provider/payment/wallets.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/amount.dart';
|
||||
import 'package:pweb/widgets/wallet_balance_refresh_button.dart';
|
||||
|
||||
|
||||
class WalletEditFields extends StatelessWidget {
|
||||
@@ -26,12 +27,15 @@ class WalletEditFields extends StatelessWidget {
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
BalanceAmount(
|
||||
wallet: wallet,
|
||||
onToggleVisibility: () {
|
||||
context.read<WalletsProvider>().toggleVisibility(wallet.id);
|
||||
},
|
||||
Expanded(
|
||||
child: BalanceAmount(
|
||||
wallet: wallet,
|
||||
onToggleVisibility: () {
|
||||
context.read<WalletsProvider>().toggleVisibility(wallet.id);
|
||||
},
|
||||
),
|
||||
),
|
||||
WalletBalanceRefreshButton(walletId: wallet.id),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
@@ -51,4 +55,4 @@ class WalletEditFields extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
62
frontend/pweb/lib/widgets/wallet_balance_refresh_button.dart
Normal file
62
frontend/pweb/lib/widgets/wallet_balance_refresh_button.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/provider/payment/wallets.dart';
|
||||
|
||||
import 'package:pweb/models/visibility.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class WalletBalanceRefreshButton extends StatelessWidget {
|
||||
final String walletId;
|
||||
final VisibilityState iconOnly;
|
||||
final double iconSize = 18;
|
||||
|
||||
const WalletBalanceRefreshButton({
|
||||
super.key,
|
||||
required this.walletId,
|
||||
this.iconOnly = VisibilityState.visible,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletsProvider = context.watch<WalletsProvider>();
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
final isBusy = walletsProvider.isWalletRefreshing(walletId) || walletsProvider.isLoading;
|
||||
final hasTarget = walletsProvider.wallets.any((w) => w.id == walletId);
|
||||
|
||||
void refresh() {
|
||||
final provider = context.read<WalletsProvider>();
|
||||
provider.refreshBalance(walletId);
|
||||
}
|
||||
|
||||
if (iconOnly == VisibilityState.hidden) {
|
||||
return IconButton(
|
||||
tooltip: loc.refreshBalance,
|
||||
onPressed: hasTarget && !isBusy ? refresh : null,
|
||||
icon: isBusy
|
||||
? SizedBox(
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
child: const CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
: const Icon(Icons.refresh),
|
||||
);
|
||||
}
|
||||
|
||||
return TextButton.icon(
|
||||
onPressed: hasTarget && !isBusy ? refresh : null,
|
||||
icon: isBusy
|
||||
? SizedBox(
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
child: const CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
: const Icon(Icons.refresh),
|
||||
label: Text(loc.refreshBalance),
|
||||
style: TextButton.styleFrom(visualDensity: VisualDensity.compact),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user