From fdc2c3f1d440194c420aa4e6bbdb9d9c8d5f0f49 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Sun, 1 Mar 2026 21:11:36 -0600 Subject: [PATCH 1/2] feat: coin control row tap-to-toggle and per-address options menu Tapping an address/output row now toggles its selection instead of opening the details view. A vertical ellipsis options button is added to the right of each row to reach the address options. Keeps the filtering, WillPopScope migration, and the UTXOConfirmedStatus deduplication from the prior work. closes #406 --- lib/pages/coin_control/coin_control_view.dart | 66 +++++++------------ lib/pages/coin_control/utxo_card.dart | 64 ++++++++++-------- .../coin_control/utxo_confirmed_status.dart | 27 ++++++++ lib/pages/coin_control/utxo_details_view.dart | 18 +---- .../coin_control/utxo_row.dart | 41 ++++++++---- 5 files changed, 118 insertions(+), 98 deletions(-) create mode 100644 lib/pages/coin_control/utxo_confirmed_status.dart diff --git a/lib/pages/coin_control/coin_control_view.dart b/lib/pages/coin_control/coin_control_view.dart index 7960733643..8cc425dc2e 100644 --- a/lib/pages/coin_control/coin_control_view.dart +++ b/lib/pages/coin_control/coin_control_view.dart @@ -26,8 +26,6 @@ import '../../utilities/assets.dart'; import '../../utilities/constants.dart'; import '../../utilities/text_styles.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; -import '../../wallets/wallet/impl/namecoin_wallet.dart'; -import '../../wallets/wallet/wallet.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; import '../../widgets/animated_widgets/rotate_icon.dart'; import '../../widgets/app_bar_field.dart'; @@ -42,6 +40,7 @@ import '../../widgets/rounded_container.dart'; import '../../widgets/rounded_white_container.dart'; import '../../widgets/toggle.dart'; import 'utxo_card.dart'; +import 'utxo_confirmed_status.dart'; import 'utxo_details_view.dart'; enum CoinControlViewType { manage, use } @@ -87,18 +86,6 @@ class _CoinControlViewState extends ConsumerState { await coinControlInterface.updateBalance(); } - bool _isConfirmed(UTXO utxo, int currentChainHeight, Wallet wallet) { - if (wallet is NamecoinWallet) { - return wallet.checkUtxoConfirmed(utxo, currentChainHeight); - } else { - return utxo.isConfirmed( - currentChainHeight, - wallet.cryptoCurrency.minConfirms, - wallet.cryptoCurrency.minCoinbaseConfirms, - ); - } - } - @override void initState() { if (widget.selectedUTXOs != null) { @@ -123,21 +110,21 @@ class _CoinControlViewState extends ConsumerState { Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - final minConfirms = - ref - .watch(pWallets) - .getWallet(widget.walletId) - .cryptoCurrency - .minConfirms; - final coin = ref.watch(pWalletCoin(widget.walletId)); final currentHeight = ref.watch(pWalletChainHeight(widget.walletId)); + final CCFilter _filter = + _isSearching + ? CCFilter.all + : _showBlocked + ? CCFilter.frozen + : CCFilter.available; + if (_sort == CCSortDescriptor.address && !_isSearching) { _list = null; _map = MainDB.instance.queryUTXOsGroupedByAddressSync( walletId: widget.walletId, - filter: CCFilter.all, + filter: _filter, sort: _sort, searchTerm: "", cryptoCurrency: coin, @@ -146,25 +133,21 @@ class _CoinControlViewState extends ConsumerState { _map = null; _list = MainDB.instance.queryUTXOsSync( walletId: widget.walletId, - filter: - _isSearching - ? CCFilter.all - : _showBlocked - ? CCFilter.frozen - : CCFilter.available, + filter: _filter, sort: _sort, searchTerm: _isSearching ? searchController.text : "", cryptoCurrency: coin, ); } - return WillPopScope( - onWillPop: () async { + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, _) { + if (didPop) return; unawaited(_refreshBalance()); Navigator.of(context).pop( widget.type == CoinControlViewType.use ? _selectedAvailable : null, ); - return false; }, child: Background( child: Scaffold( @@ -291,8 +274,8 @@ class _CoinControlViewState extends ConsumerState { RoundedWhiteContainer( child: Text( "This option allows you to control, freeze, and utilize " - "outputs at your discretion. Tap the output circle to " - "select.", + "outputs at your discretion. Tap an output to select it, " + "or use the options button for more actions.", style: STextStyles.w500_14(context).copyWith( color: Theme.of( @@ -302,7 +285,7 @@ class _CoinControlViewState extends ConsumerState { ), ), if (!_isSearching) const SizedBox(height: 10), - if (!(_isSearching || _map != null)) + if (!_isSearching) SizedBox( height: 48, child: Toggle( @@ -360,8 +343,7 @@ class _CoinControlViewState extends ConsumerState { CoinControlViewType.manage || (widget.type == CoinControlViewType.use && !utxo.isBlocked && - _isConfirmed( - utxo, + utxo.isConfirmedStatus( currentHeight, ref.watch( pWallets.select( @@ -384,7 +366,7 @@ class _CoinControlViewState extends ConsumerState { } setState(() {}); }, - onPressed: () async { + onOptionsPressed: () async { final result = await Navigator.of( context, ).pushNamed( @@ -434,8 +416,7 @@ class _CoinControlViewState extends ConsumerState { (widget.type == CoinControlViewType.use && !_showBlocked && - _isConfirmed( - utxo, + utxo.isConfirmedStatus( currentHeight, ref.watch( pWallets.select( @@ -458,7 +439,7 @@ class _CoinControlViewState extends ConsumerState { } setState(() {}); }, - onPressed: () async { + onOptionsPressed: () async { final result = await Navigator.of( context, ).pushNamed( @@ -590,8 +571,7 @@ class _CoinControlViewState extends ConsumerState { CoinControlViewType .use && !utxo.isBlocked && - _isConfirmed( - utxo, + utxo.isConfirmedStatus( currentHeight, ref.watch( pWallets.select( @@ -621,7 +601,7 @@ class _CoinControlViewState extends ConsumerState { } setState(() {}); }, - onPressed: () async { + onOptionsPressed: () async { final result = await Navigator.of( context, diff --git a/lib/pages/coin_control/utxo_card.dart b/lib/pages/coin_control/utxo_card.dart index 624b41eee9..e45737aca9 100644 --- a/lib/pages/coin_control/utxo_card.dart +++ b/lib/pages/coin_control/utxo_card.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import '../../db/isar/main_db.dart'; import '../../models/isar/models/isar_models.dart'; @@ -17,14 +18,15 @@ import '../../providers/global/wallets_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/amount/amount.dart'; import '../../utilities/amount/amount_formatter.dart'; +import '../../utilities/assets.dart'; import '../../utilities/constants.dart'; import '../../utilities/text_styles.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; -import '../../wallets/wallet/impl/namecoin_wallet.dart'; -import '../../wallets/wallet/wallet.dart'; import '../../widgets/conditional_parent.dart'; +import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/icon_widgets/utxo_status_icon.dart'; import '../../widgets/rounded_container.dart'; +import 'utxo_confirmed_status.dart'; class UtxoCard extends ConsumerStatefulWidget { const UtxoCard({ @@ -34,14 +36,14 @@ class UtxoCard extends ConsumerStatefulWidget { required this.onSelectedChanged, required this.initialSelectedState, required this.canSelect, - this.onPressed, + this.onOptionsPressed, }); final String walletId; final UTXO utxo; final void Function(bool) onSelectedChanged; final bool initialSelectedState; - final VoidCallback? onPressed; + final VoidCallback? onOptionsPressed; final bool canSelect; @override @@ -54,18 +56,6 @@ class _UtxoCardState extends ConsumerState { late bool _selected; - bool _isConfirmed(UTXO utxo, int currentChainHeight, Wallet wallet) { - if (wallet is NamecoinWallet) { - return wallet.checkUtxoConfirmed(utxo, currentChainHeight); - } else { - return utxo.isConfirmed( - currentChainHeight, - wallet.cryptoCurrency.minConfirms, - wallet.cryptoCurrency.minCoinbaseConfirms, - ); - } - } - @override void initState() { _selected = widget.initialSelectedState; @@ -75,6 +65,12 @@ class _UtxoCardState extends ConsumerState { super.initState(); } + void _toggleSelected() { + _selected = !_selected; + widget.onSelectedChanged(_selected); + setState(() {}); + } + @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); @@ -83,7 +79,7 @@ class _UtxoCardState extends ConsumerState { final currentHeight = ref.watch(pWalletChainHeight(widget.walletId)); return ConditionalParent( - condition: widget.onPressed != null, + condition: widget.canSelect, builder: (child) => MaterialButton( padding: const EdgeInsets.all(0), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, @@ -97,13 +93,11 @@ class _UtxoCardState extends ConsumerState { borderRadius: BorderRadius.circular(Constants.size.circularBorderRadius), ), - onPressed: widget.onPressed, + onPressed: _toggleSelected, child: child, ), child: RoundedContainer( - color: widget.onPressed == null - ? Theme.of(context).extension()!.popupBG - : Colors.transparent, + color: Theme.of(context).extension()!.popupBG, child: StreamBuilder( stream: stream, builder: (context, snapshot) { @@ -115,17 +109,12 @@ class _UtxoCardState extends ConsumerState { ConditionalParent( condition: widget.canSelect, builder: (child) => GestureDetector( - onTap: () { - _selected = !_selected; - widget.onSelectedChanged(_selected); - setState(() {}); - }, + onTap: _toggleSelected, child: child, ), child: UTXOStatusIcon( blocked: utxo.isBlocked, - status: _isConfirmed( - utxo, + status: utxo.isConfirmedStatus( currentHeight, ref.watch( pWallets.select( @@ -182,6 +171,25 @@ class _UtxoCardState extends ConsumerState { ], ), ), + if (widget.onOptionsPressed != null) + const SizedBox( + width: 10, + ), + if (widget.onOptionsPressed != null) + AppBarIconButton( + size: 36, + shadows: const [], + color: Theme.of(context).extension()!.popupBG, + icon: SvgPicture.asset( + Assets.svg.verticalEllipsis, + color: Theme.of(context) + .extension()! + .textSubtitle1, + width: 20, + height: 20, + ), + onPressed: widget.onOptionsPressed, + ), ], ); }, diff --git a/lib/pages/coin_control/utxo_confirmed_status.dart b/lib/pages/coin_control/utxo_confirmed_status.dart new file mode 100644 index 0000000000..6928eea15e --- /dev/null +++ b/lib/pages/coin_control/utxo_confirmed_status.dart @@ -0,0 +1,27 @@ +/* + * This file is part of Stack Wallet. + * + * Copyright (c) 2023 Cypher Stack + * All Rights Reserved. + * The code is distributed under GPLv3 license, see LICENSE file for details. + * Generated by Cypher Stack on 2023-05-26 + * + */ + +import '../../models/isar/models/isar_models.dart'; +import '../../wallets/wallet/impl/namecoin_wallet.dart'; +import '../../wallets/wallet/wallet.dart'; + +extension UTXOConfirmedStatus on UTXO { + bool isConfirmedStatus(int currentChainHeight, Wallet wallet) { + if (wallet is NamecoinWallet) { + return wallet.checkUtxoConfirmed(this, currentChainHeight); + } else { + return isConfirmed( + currentChainHeight, + wallet.cryptoCurrency.minConfirms, + wallet.cryptoCurrency.minCoinbaseConfirms, + ); + } + } +} diff --git a/lib/pages/coin_control/utxo_details_view.dart b/lib/pages/coin_control/utxo_details_view.dart index b77b152bda..59d373f684 100644 --- a/lib/pages/coin_control/utxo_details_view.dart +++ b/lib/pages/coin_control/utxo_details_view.dart @@ -23,8 +23,6 @@ import '../../utilities/amount/amount_formatter.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; -import '../../wallets/wallet/impl/namecoin_wallet.dart'; -import '../../wallets/wallet/wallet.dart'; import '../../widgets/background.dart'; import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; @@ -36,6 +34,7 @@ import '../../widgets/desktop/secondary_button.dart'; import '../../widgets/icon_widgets/utxo_status_icon.dart'; import '../../widgets/rounded_container.dart'; import '../wallet_view/transaction_views/transaction_details_view.dart' as tdv; +import 'utxo_confirmed_status.dart'; class UtxoDetailsView extends ConsumerStatefulWidget { const UtxoDetailsView({ @@ -69,18 +68,6 @@ class _UtxoDetailsViewState extends ConsumerState { await MainDB.instance.putUTXO(utxo!.copyWith(isBlocked: !utxo!.isBlocked)); } - bool _isConfirmed(UTXO utxo, int currentChainHeight, Wallet wallet) { - if (wallet is NamecoinWallet) { - return wallet.checkUtxoConfirmed(utxo, currentChainHeight); - } else { - return utxo.isConfirmed( - currentChainHeight, - wallet.cryptoCurrency.minConfirms, - wallet.cryptoCurrency.minCoinbaseConfirms, - ); - } - } - @override void initState() { utxo = @@ -110,8 +97,7 @@ class _UtxoDetailsViewState extends ConsumerState { final coin = ref.watch(pWalletCoin(widget.walletId)); final currentHeight = ref.watch(pWalletChainHeight(widget.walletId)); - final confirmed = _isConfirmed( - utxo!, + final confirmed = utxo!.isConfirmedStatus( currentHeight, ref.watch(pWallets.select((s) => s.getWallet(widget.walletId))), ); diff --git a/lib/pages_desktop_specific/coin_control/utxo_row.dart b/lib/pages_desktop_specific/coin_control/utxo_row.dart index e27d970fc5..5fb66da891 100644 --- a/lib/pages_desktop_specific/coin_control/utxo_row.dart +++ b/lib/pages_desktop_specific/coin_control/utxo_row.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:isar_community/isar.dart'; import '../../db/isar/main_db.dart'; @@ -19,13 +20,13 @@ import '../../providers/global/wallets_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/amount/amount.dart'; import '../../utilities/amount/amount_formatter.dart'; +import '../../utilities/assets.dart'; import '../../utilities/text_styles.dart'; import '../../wallets/crypto_currency/coins/namecoin.dart'; import '../../wallets/isar/providers/wallet_info_provider.dart'; import '../../wallets/wallet/impl/namecoin_wallet.dart'; import '../../widgets/conditional_parent.dart'; -import '../../widgets/custom_buttons/blue_text_button.dart'; -import '../../widgets/desktop/secondary_button.dart'; +import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/icon_widgets/utxo_status_icon.dart'; import '../../widgets/rounded_container.dart'; @@ -84,6 +85,16 @@ class _UtxoRowState extends ConsumerState { ); } + void _toggleSelected() { + if (widget.compact && utxo.isBlocked) { + return; + } + setState(() { + widget.data.selected = !widget.data.selected; + }); + widget.onSelectionChanged?.call(widget.data); + } + @override void initState() { utxo = @@ -109,7 +120,9 @@ class _UtxoRowState extends ConsumerState { utxo = snapshot.data!; } - return RoundedContainer( + return GestureDetector( + onTap: _toggleSelected, + child: RoundedContainer( borderColor: widget.compact && widget.compactWithBorder ? Theme.of( @@ -219,16 +232,22 @@ class _UtxoRowState extends ConsumerState { ), ), const SizedBox(width: 10), - widget.compact - ? CustomTextButton(text: "Details", onTap: _details) - : SecondaryButton( - width: 120, - buttonHeight: ButtonHeight.xs, - label: "Details", - onPressed: _details, - ), + AppBarIconButton( + size: 36, + shadows: const [], + color: Theme.of(context).extension()!.popupBG, + icon: SvgPicture.asset( + Assets.svg.verticalEllipsis, + color: + Theme.of(context).extension()!.textSubtitle1, + width: 20, + height: 20, + ), + onPressed: _details, + ), ], ), + ), ); }, ); From fb00543174b0cacad9e80b76477bea8db2217118 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 28 May 2026 11:30:57 -0500 Subject: [PATCH 2/2] chore: dart format --- lib/pages/coin_control/coin_control_view.dart | 756 +++++++++--------- lib/pages/coin_control/utxo_card.dart | 62 +- lib/pages/coin_control/utxo_details_view.dart | 259 +++--- .../coin_control/utxo_row.dart | 219 +++-- 4 files changed, 614 insertions(+), 682 deletions(-) diff --git a/lib/pages/coin_control/coin_control_view.dart b/lib/pages/coin_control/coin_control_view.dart index 8cc425dc2e..e89b60e147 100644 --- a/lib/pages/coin_control/coin_control_view.dart +++ b/lib/pages/coin_control/coin_control_view.dart @@ -113,12 +113,11 @@ class _CoinControlViewState extends ConsumerState { final coin = ref.watch(pWalletCoin(widget.walletId)); final currentHeight = ref.watch(pWalletChainHeight(widget.walletId)); - final CCFilter _filter = - _isSearching - ? CCFilter.all - : _showBlocked - ? CCFilter.frozen - : CCFilter.available; + final CCFilter _filter = _isSearching + ? CCFilter.all + : _showBlocked + ? CCFilter.frozen + : CCFilter.available; if (_sort == CCSortDescriptor.address && !_isSearching) { _list = null; @@ -151,115 +150,107 @@ class _CoinControlViewState extends ConsumerState { }, child: Background( child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, + backgroundColor: Theme.of( + context, + ).extension()!.background, appBar: AppBar( automaticallyImplyLeading: false, - leading: - _isSearching - ? null - : widget.type == CoinControlViewType.use && - _selectedAvailable.isNotEmpty - ? AppBarIconButton( - icon: XIcon( - width: 24, - height: 24, - color: - Theme.of( - context, - ).extension()!.topNavIconPrimary, - ), - onPressed: () { - setState(() { - _selectedAvailable.clear(); - }); - }, - ) - : AppBarBackButton( - onPressed: () { - unawaited(_refreshBalance()); - Navigator.of(context).pop( - widget.type == CoinControlViewType.use - ? _selectedAvailable - : null, - ); - }, - ), - title: - _isSearching - ? AppBarSearchField( - controller: searchController, - focusNode: searchFocus, - ) - : Text( - "Coin control", - style: STextStyles.navBarTitle(context), + leading: _isSearching + ? null + : widget.type == CoinControlViewType.use && + _selectedAvailable.isNotEmpty + ? AppBarIconButton( + icon: XIcon( + width: 24, + height: 24, + color: Theme.of( + context, + ).extension()!.topNavIconPrimary, ), + onPressed: () { + setState(() { + _selectedAvailable.clear(); + }); + }, + ) + : AppBarBackButton( + onPressed: () { + unawaited(_refreshBalance()); + Navigator.of(context).pop( + widget.type == CoinControlViewType.use + ? _selectedAvailable + : null, + ); + }, + ), + title: _isSearching + ? AppBarSearchField( + controller: searchController, + focusNode: searchFocus, + ) + : Text("Coin control", style: STextStyles.navBarTitle(context)), titleSpacing: 0, - actions: - _isSearching - ? [ - AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - size: 36, - icon: SvgPicture.asset( - Assets.svg.x, - width: 20, - height: 20, - color: - Theme.of( - context, - ).extension()!.topNavIconPrimary, - ), - onPressed: () { - // show search - setState(() { - _isSearching = false; - }); - }, + actions: _isSearching + ? [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.x, + width: 20, + height: 20, + color: Theme.of( + context, + ).extension()!.topNavIconPrimary, ), + onPressed: () { + // show search + setState(() { + _isSearching = false; + }); + }, ), - ] - : [ - AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - size: 36, - icon: SvgPicture.asset( - Assets.svg.search, - width: 20, - height: 20, - color: - Theme.of( - context, - ).extension()!.topNavIconPrimary, - ), - onPressed: () { - // show search - setState(() { - _isSearching = true; - }); - }, + ), + ] + : [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.search, + width: 20, + height: 20, + color: Theme.of( + context, + ).extension()!.topNavIconPrimary, ), + onPressed: () { + // show search + setState(() { + _isSearching = true; + }); + }, ), - AspectRatio( - aspectRatio: 1, - child: JDropdownIconButton( - mobileAppBar: true, - groupValue: _sort, - items: CCSortDescriptor.values.toSet(), - onSelectionChanged: (CCSortDescriptor? newValue) { - if (newValue != null && newValue != _sort) { - setState(() { - _sort = newValue; - }); - } - }, - displayPrefix: "Sort by", - ), + ), + AspectRatio( + aspectRatio: 1, + child: JDropdownIconButton( + mobileAppBar: true, + groupValue: _sort, + items: CCSortDescriptor.values.toSet(), + onSelectionChanged: (CCSortDescriptor? newValue) { + if (newValue != null && newValue != _sort) { + setState(() { + _sort = newValue; + }); + } + }, + displayPrefix: "Sort by", ), - ], + ), + ], ), body: SafeArea( child: Column( @@ -277,10 +268,9 @@ class _CoinControlViewState extends ConsumerState { "outputs at your discretion. Tap an output to select it, " "or use the options button for more actions.", style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, + color: Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ), @@ -290,15 +280,13 @@ class _CoinControlViewState extends ConsumerState { height: 48, child: Toggle( key: UniqueKey(), - onColor: - Theme.of( - context, - ).extension()!.popupBG, + onColor: Theme.of( + context, + ).extension()!.popupBG, onText: "Available outputs", - offColor: - Theme.of(context) - .extension()! - .textFieldDefaultBG, + offColor: Theme.of( + context, + ).extension()!.textFieldDefaultBG, offText: "Frozen outputs", isOn: _showBlocked, onValueChanged: (value) { @@ -319,14 +307,13 @@ class _CoinControlViewState extends ConsumerState { Expanded( child: ListView.separated( itemCount: _list!.length, - separatorBuilder: - (context, _) => const SizedBox(height: 10), + separatorBuilder: (context, _) => + const SizedBox(height: 10), itemBuilder: (context, index) { - final utxo = - MainDB.instance.isar.utxos - .where() - .idEqualTo(_list![index]) - .findFirstSync()!; + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(_list![index]) + .findFirstSync()!; final isSelected = _selectedBlocked.contains(utxo) || @@ -367,15 +354,14 @@ class _CoinControlViewState extends ConsumerState { setState(() {}); }, onOptionsPressed: () async { - final result = await Navigator.of( - context, - ).pushNamed( - UtxoDetailsView.routeName, - arguments: Tuple2( - utxo.id, - widget.walletId, - ), - ); + final result = await Navigator.of(context) + .pushNamed( + UtxoDetailsView.routeName, + arguments: Tuple2( + utxo.id, + widget.walletId, + ), + ); if (mounted && result == "refresh") { setState(() {}); } @@ -387,242 +373,234 @@ class _CoinControlViewState extends ConsumerState { if (!_isSearching) _list != null ? Expanded( - child: ListView.separated( - itemCount: _list!.length, - separatorBuilder: - (context, _) => - const SizedBox(height: 10), - itemBuilder: (context, index) { - final utxo = - MainDB.instance.isar.utxos - .where() - .idEqualTo(_list![index]) - .findFirstSync()!; + child: ListView.separated( + itemCount: _list!.length, + separatorBuilder: (context, _) => + const SizedBox(height: 10), + itemBuilder: (context, index) { + final utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(_list![index]) + .findFirstSync()!; - final isSelected = - _showBlocked - ? _selectedBlocked.contains(utxo) - : _selectedAvailable.contains(utxo); + final isSelected = _showBlocked + ? _selectedBlocked.contains(utxo) + : _selectedAvailable.contains(utxo); - return UtxoCard( - key: Key( - "${utxo.walletId}_${utxo.id}_$isSelected", - ), - walletId: widget.walletId, - utxo: utxo, - canSelect: - widget.type == - CoinControlViewType.manage || - (widget.type == - CoinControlViewType.use && - !_showBlocked && - utxo.isConfirmedStatus( - currentHeight, - ref.watch( - pWallets.select( - (s) => s.getWallet( - widget.walletId, + return UtxoCard( + key: Key( + "${utxo.walletId}_${utxo.id}_$isSelected", + ), + walletId: widget.walletId, + utxo: utxo, + canSelect: + widget.type == + CoinControlViewType.manage || + (widget.type == + CoinControlViewType.use && + !_showBlocked && + utxo.isConfirmedStatus( + currentHeight, + ref.watch( + pWallets.select( + (s) => s.getWallet( + widget.walletId, + ), ), ), - ), - )), - initialSelectedState: isSelected, - onSelectedChanged: (value) { - if (value) { - _showBlocked - ? _selectedBlocked.add(utxo) - : _selectedAvailable.add(utxo); - } else { - _showBlocked - ? _selectedBlocked.remove(utxo) - : _selectedAvailable.remove(utxo); - } - setState(() {}); - }, - onOptionsPressed: () async { - final result = await Navigator.of( - context, - ).pushNamed( - UtxoDetailsView.routeName, - arguments: Tuple2( - utxo.id, - widget.walletId, - ), - ); - if (mounted && result == "refresh") { + )), + initialSelectedState: isSelected, + onSelectedChanged: (value) { + if (value) { + _showBlocked + ? _selectedBlocked.add(utxo) + : _selectedAvailable.add(utxo); + } else { + _showBlocked + ? _selectedBlocked.remove(utxo) + : _selectedAvailable.remove( + utxo, + ); + } setState(() {}); - } - }, - ); - }, - ), - ) + }, + onOptionsPressed: () async { + final result = + await Navigator.of( + context, + ).pushNamed( + UtxoDetailsView.routeName, + arguments: Tuple2( + utxo.id, + widget.walletId, + ), + ); + if (mounted && result == "refresh") { + setState(() {}); + } + }, + ); + }, + ), + ) : Expanded( - child: ListView.separated( - itemCount: _map!.entries.length, - separatorBuilder: - (context, _) => - const SizedBox(height: 10), - itemBuilder: (context, index) { - final entry = _map!.entries.elementAt( - index, - ); - final _controller = RotateIconController(); + child: ListView.separated( + itemCount: _map!.entries.length, + separatorBuilder: (context, _) => + const SizedBox(height: 10), + itemBuilder: (context, index) { + final entry = _map!.entries.elementAt( + index, + ); + final _controller = + RotateIconController(); - return Expandable2( - border: - Theme.of(context) - .extension()! - .backgroundAppBar, - background: - Theme.of( - context, - ).extension()!.popupBG, - animationDurationMultiplier: - 0.2 * entry.value.length, - onExpandWillChange: (state) { - if (state == - Expandable2State.expanded) { - _controller.forward?.call(); - } else { - _controller.reverse?.call(); - } - }, - header: RoundedContainer( - padding: const EdgeInsets.all(14), - color: Colors.transparent, - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - entry.key, - style: STextStyles.w600_14( - context, + return Expandable2( + border: Theme.of(context) + .extension()! + .backgroundAppBar, + background: Theme.of( + context, + ).extension()!.popupBG, + animationDurationMultiplier: + 0.2 * entry.value.length, + onExpandWillChange: (state) { + if (state == + Expandable2State.expanded) { + _controller.forward?.call(); + } else { + _controller.reverse?.call(); + } + }, + header: RoundedContainer( + padding: const EdgeInsets.all(14), + color: Colors.transparent, + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + entry.key, + style: + STextStyles.w600_14( + context, + ), ), - ), - const SizedBox(height: 2), - Text( - "${entry.value.length} " - "output${entry.value.length > 1 ? "s" : ""}", - style: STextStyles.w500_12( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textSubtitle1, + const SizedBox(height: 2), + Text( + "${entry.value.length} " + "output${entry.value.length > 1 ? "s" : ""}", + style: + STextStyles.w500_12( + context, + ).copyWith( + color: Theme.of(context) + .extension< + StackColors + >()! + .textSubtitle1, + ), ), - ), - ], + ], + ), ), - ), - RotateIcon( - animationDurationMultiplier: - 0.2 * entry.value.length, - icon: SvgPicture.asset( - Assets.svg.chevronDown, - width: 14, - color: - Theme.of(context) - .extension< - StackColors - >()! - .textSubtitle1, + RotateIcon( + animationDurationMultiplier: + 0.2 * entry.value.length, + icon: SvgPicture.asset( + Assets.svg.chevronDown, + width: 14, + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + curve: Curves.easeInOut, + controller: _controller, ), - curve: Curves.easeInOut, - controller: _controller, - ), - ], + ], + ), ), - ), - children: - entry.value.map((id) { - final utxo = - MainDB.instance.isar.utxos - .where() - .idEqualTo(id) - .findFirstSync()!; + children: entry.value.map((id) { + final utxo = MainDB + .instance + .isar + .utxos + .where() + .idEqualTo(id) + .findFirstSync()!; - final isSelected = - _selectedBlocked.contains( - utxo, - ) || - _selectedAvailable.contains( - utxo, - ); + final isSelected = + _selectedBlocked.contains(utxo) || + _selectedAvailable.contains(utxo); - return UtxoCard( - key: Key( - "${utxo.walletId}_${utxo.id}_$isSelected", - ), - walletId: widget.walletId, - utxo: utxo, - canSelect: - widget.type == - CoinControlViewType - .manage || - (widget.type == - CoinControlViewType - .use && - !utxo.isBlocked && - utxo.isConfirmedStatus( - currentHeight, - ref.watch( - pWallets.select( - (s) => s.getWallet( - widget.walletId, - ), + return UtxoCard( + key: Key( + "${utxo.walletId}_${utxo.id}_$isSelected", + ), + walletId: widget.walletId, + utxo: utxo, + canSelect: + widget.type == + CoinControlViewType + .manage || + (widget.type == + CoinControlViewType + .use && + !utxo.isBlocked && + utxo.isConfirmedStatus( + currentHeight, + ref.watch( + pWallets.select( + (s) => s.getWallet( + widget.walletId, ), ), - )), - initialSelectedState: isSelected, - onSelectedChanged: (value) { - if (value) { - utxo.isBlocked - ? _selectedBlocked.add( - utxo, - ) - : _selectedAvailable.add( + ), + )), + initialSelectedState: isSelected, + onSelectedChanged: (value) { + if (value) { + utxo.isBlocked + ? _selectedBlocked.add(utxo) + : _selectedAvailable.add( utxo, ); - } else { - utxo.isBlocked - ? _selectedBlocked.remove( + } else { + utxo.isBlocked + ? _selectedBlocked.remove( utxo, ) - : _selectedAvailable - .remove(utxo); - } + : _selectedAvailable.remove( + utxo, + ); + } + setState(() {}); + }, + onOptionsPressed: () async { + final result = + await Navigator.of( + context, + ).pushNamed( + UtxoDetailsView.routeName, + arguments: Tuple2( + utxo.id, + widget.walletId, + ), + ); + if (mounted && + result == "refresh") { setState(() {}); - }, - onOptionsPressed: () async { - final result = - await Navigator.of( - context, - ).pushNamed( - UtxoDetailsView.routeName, - arguments: Tuple2( - utxo.id, - widget.walletId, - ), - ); - if (mounted && - result == "refresh") { - setState(() {}); - } - }, - ); - }).toList(), - ); - }, + } + }, + ); + }).toList(), + ); + }, + ), ), - ), ], ), ), @@ -632,10 +610,9 @@ class _CoinControlViewState extends ConsumerState { widget.type == CoinControlViewType.manage) Container( decoration: BoxDecoration( - color: - Theme.of( - context, - ).extension()!.backgroundAppBar, + color: Theme.of( + context, + ).extension()!.backgroundAppBar, boxShadow: [ Theme.of( context, @@ -670,10 +647,9 @@ class _CoinControlViewState extends ConsumerState { if (!_showBlocked && widget.type == CoinControlViewType.use) Container( decoration: BoxDecoration( - color: - Theme.of( - context, - ).extension()!.backgroundAppBar, + color: Theme.of( + context, + ).extension()!.backgroundAppBar, boxShadow: [ Theme.of( context, @@ -702,13 +678,13 @@ class _CoinControlViewState extends ConsumerState { builder: (context) { final int selectedSumInt = _selectedAvailable.isEmpty - ? 0 - : _selectedAvailable - .map((e) => e.value) - .reduce( - (value, element) => - value += element, - ); + ? 0 + : _selectedAvailable + .map((e) => e.value) + .reduce( + (value, element) => + value += element, + ); final selectedSum = selectedSumInt .toAmountAsRaw( fractionDigits: @@ -718,33 +694,26 @@ class _CoinControlViewState extends ConsumerState { ref .watch(pAmountFormatter(coin)) .format(selectedSum), - style: - widget.requestedTotal == null - ? STextStyles.w600_14( - context, - ) - : STextStyles.w600_14( - context, - ).copyWith( - color: - selectedSum >= - widget - .requestedTotal! - ? Theme.of( - context, - ) - .extension< - StackColors - >()! - .accentColorGreen - : Theme.of( - context, - ) - .extension< - StackColors - >()! - .accentColorRed, - ), + style: widget.requestedTotal == null + ? STextStyles.w600_14(context) + : STextStyles.w600_14( + context, + ).copyWith( + color: + selectedSum >= + widget + .requestedTotal! + ? Theme.of(context) + .extension< + StackColors + >()! + .accentColorGreen + : Theme.of(context) + .extension< + StackColors + >()! + .accentColorRed, + ), ); }, ), @@ -755,10 +724,9 @@ class _CoinControlViewState extends ConsumerState { Container( width: double.infinity, height: 1.5, - color: - Theme.of(context) - .extension()! - .backgroundAppBar, + color: Theme.of(context) + .extension()! + .backgroundAppBar, ), if (widget.requestedTotal != null) Padding( diff --git a/lib/pages/coin_control/utxo_card.dart b/lib/pages/coin_control/utxo_card.dart index e45737aca9..29de77e44b 100644 --- a/lib/pages/coin_control/utxo_card.dart +++ b/lib/pages/coin_control/utxo_card.dart @@ -90,8 +90,9 @@ class _UtxoCardState extends ConsumerState { focusElevation: 0, highlightElevation: 0, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), onPressed: _toggleSelected, child: child, @@ -108,50 +109,46 @@ class _UtxoCardState extends ConsumerState { children: [ ConditionalParent( condition: widget.canSelect, - builder: (child) => GestureDetector( - onTap: _toggleSelected, - child: child, - ), + builder: (child) => + GestureDetector(onTap: _toggleSelected, child: child), child: UTXOStatusIcon( blocked: utxo.isBlocked, - status: utxo.isConfirmedStatus( - currentHeight, - ref.watch( - pWallets.select( - (s) => s.getWallet( - widget.walletId, + status: + utxo.isConfirmedStatus( + currentHeight, + ref.watch( + pWallets.select( + (s) => s.getWallet(widget.walletId), + ), ), - ), - ), - ) + ) ? UTXOStatusIconStatus.confirmed : UTXOStatusIconStatus.unconfirmed, - background: - Theme.of(context).extension()!.popupBG, + background: Theme.of( + context, + ).extension()!.popupBG, selected: _selected, width: 32, height: 32, ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( utxo.value.toAmountAsRaw( fractionDigits: coin.fractionDigits, ), ), style: STextStyles.w600_14(context), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Row( children: [ Flexible( @@ -160,9 +157,9 @@ class _UtxoCardState extends ConsumerState { ? utxo.name : utxo.address ?? utxo.txid, style: STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ), @@ -171,10 +168,7 @@ class _UtxoCardState extends ConsumerState { ], ), ), - if (widget.onOptionsPressed != null) - const SizedBox( - width: 10, - ), + if (widget.onOptionsPressed != null) const SizedBox(width: 10), if (widget.onOptionsPressed != null) AppBarIconButton( size: 36, @@ -182,9 +176,9 @@ class _UtxoCardState extends ConsumerState { color: Theme.of(context).extension()!.popupBG, icon: SvgPicture.asset( Assets.svg.verticalEllipsis, - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: Theme.of( + context, + ).extension()!.textSubtitle1, width: 20, height: 20, ), diff --git a/lib/pages/coin_control/utxo_details_view.dart b/lib/pages/coin_control/utxo_details_view.dart index 59d373f684..6c79fba2b6 100644 --- a/lib/pages/coin_control/utxo_details_view.dart +++ b/lib/pages/coin_control/utxo_details_view.dart @@ -70,11 +70,10 @@ class _UtxoDetailsViewState extends ConsumerState { @override void initState() { - utxo = - MainDB.instance.isar.utxos - .where() - .idEqualTo(widget.utxoId) - .findFirstSync()!; + utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(widget.utxoId) + .findFirstSync()!; streamUTXO = MainDB.instance.watchUTXO(id: widget.utxoId); @@ -104,45 +103,44 @@ class _UtxoDetailsViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: - (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () { - Navigator.of( - context, - ).pop(_popWithRefresh ? "refresh" : null); - }, - ), - title: Text( - "Output details", - style: STextStyles.navBarTitle(context), - ), - ), - body: SafeArea( - child: LayoutBuilder( - builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight(child: child), - ), + builder: (child) => Background( + child: Scaffold( + backgroundColor: Theme.of( + context, + ).extension()!.background, + appBar: AppBar( + backgroundColor: Theme.of( + context, + ).extension()!.background, + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(_popWithRefresh ? "refresh" : null); + }, + ), + title: Text( + "Output details", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, ), - ); - }, - ), - ), + child: IntrinsicHeight(child: child), + ), + ), + ); + }, ), ), + ), + ), child: StreamBuilder( stream: streamUTXO, builder: (context, snapshot) { @@ -189,10 +187,9 @@ class _UtxoDetailsViewState extends ConsumerState { child: RoundedContainer( padding: EdgeInsets.zero, color: Colors.transparent, - borderColor: - Theme.of(context) - .extension()! - .textFieldDefaultBG, + borderColor: Theme.of( + context, + ).extension()!.textFieldDefaultBG, child: child, ), ), @@ -216,10 +213,9 @@ class _UtxoDetailsViewState extends ConsumerState { if (!isDesktop) const SizedBox(height: 10), RoundedContainer( padding: const EdgeInsets.all(12), - color: - isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.popupBG, + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -228,14 +224,12 @@ class _UtxoDetailsViewState extends ConsumerState { if (isDesktop) UTXOStatusIcon( blocked: utxo!.isBlocked, - status: - confirmed - ? UTXOStatusIconStatus.confirmed - : UTXOStatusIconStatus.unconfirmed, - background: - Theme.of( - context, - ).extension()!.popupBG, + status: confirmed + ? UTXOStatusIconStatus.confirmed + : UTXOStatusIconStatus.unconfirmed, + background: Theme.of( + context, + ).extension()!.popupBG, selected: false, width: 32, height: 32, @@ -260,16 +254,15 @@ class _UtxoDetailsViewState extends ConsumerState { ? "Available" : "Unconfirmed", style: STextStyles.w500_14(context).copyWith( - color: - utxo!.isBlocked - ? const Color(0xFF7FA2D4) // todo theme - : confirmed - ? Theme.of( - context, - ).extension()!.accentColorGreen - : Theme.of( - context, - ).extension()!.accentColorYellow, + color: utxo!.isBlocked + ? const Color(0xFF7FA2D4) // todo theme + : confirmed + ? Theme.of( + context, + ).extension()!.accentColorGreen + : Theme.of( + context, + ).extension()!.accentColorYellow, ), ), ], @@ -277,14 +270,12 @@ class _UtxoDetailsViewState extends ConsumerState { ), const _Div(), RoundedContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.popupBG, + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -295,10 +286,9 @@ class _UtxoDetailsViewState extends ConsumerState { Text( "Label", style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, + color: Theme.of( + context, + ).extension()!.textSubtitle1, ), ), SimpleEditButton( @@ -319,14 +309,12 @@ class _UtxoDetailsViewState extends ConsumerState { ), const _Div(), RoundedContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.popupBG, + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -337,10 +325,9 @@ class _UtxoDetailsViewState extends ConsumerState { Text( "Address", style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, + color: Theme.of( + context, + ).extension()!.textSubtitle1, ), ), isDesktop @@ -356,16 +343,12 @@ class _UtxoDetailsViewState extends ConsumerState { if (label != null && label!.value.isNotEmpty) const _Div(), if (label != null && label!.value.isNotEmpty) RoundedContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - isDesktop - ? Colors.transparent - : Theme.of( - context, - ).extension()!.popupBG, + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -376,10 +359,9 @@ class _UtxoDetailsViewState extends ConsumerState { Text( "Address label", style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, + color: Theme.of( + context, + ).extension()!.textSubtitle1, ), ), isDesktop @@ -394,14 +376,12 @@ class _UtxoDetailsViewState extends ConsumerState { ), const _Div(), RoundedContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.popupBG, + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -412,10 +392,9 @@ class _UtxoDetailsViewState extends ConsumerState { Text( "Transaction ID", style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, + color: Theme.of( + context, + ).extension()!.textSubtitle1, ), ), isDesktop @@ -430,14 +409,12 @@ class _UtxoDetailsViewState extends ConsumerState { ), const _Div(), RoundedContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.popupBG, + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.popupBG, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -445,10 +422,9 @@ class _UtxoDetailsViewState extends ConsumerState { Text( "Confirmations", style: STextStyles.w500_14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, + color: Theme.of( + context, + ).extension()!.textSubtitle1, ), ), const SizedBox(height: 4), @@ -466,16 +442,14 @@ class _UtxoDetailsViewState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ RoundedContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - color: - isDesktop - ? Colors.transparent - : Theme.of( - context, - ).extension()!.popupBG, + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.popupBG, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -486,10 +460,9 @@ class _UtxoDetailsViewState extends ConsumerState { Text( "Freeze reason", style: STextStyles.w500_14(context).copyWith( - color: - Theme.of(context) - .extension()! - .textSubtitle1, + color: Theme.of( + context, + ).extension()!.textSubtitle1, ), ), SimpleEditButton( diff --git a/lib/pages_desktop_specific/coin_control/utxo_row.dart b/lib/pages_desktop_specific/coin_control/utxo_row.dart index 5fb66da891..0083e27a9d 100644 --- a/lib/pages_desktop_specific/coin_control/utxo_row.dart +++ b/lib/pages_desktop_specific/coin_control/utxo_row.dart @@ -79,9 +79,8 @@ class _UtxoRowState extends ConsumerState { void _details() async { await showDialog( context: context, - builder: - (context) => - UtxoDetailsView(utxoId: utxo.id, walletId: widget.walletId), + builder: (context) => + UtxoDetailsView(utxoId: utxo.id, walletId: widget.walletId), ); } @@ -97,11 +96,10 @@ class _UtxoRowState extends ConsumerState { @override void initState() { - utxo = - MainDB.instance.isar.utxos - .where() - .idEqualTo(widget.data.utxoId) - .findFirstSync()!; + utxo = MainDB.instance.isar.utxos + .where() + .idEqualTo(widget.data.utxoId) + .findFirstSync()!; stream = MainDB.instance.watchUTXO(id: utxo.id); super.initState(); @@ -123,40 +121,36 @@ class _UtxoRowState extends ConsumerState { return GestureDetector( onTap: _toggleSelected, child: RoundedContainer( - borderColor: - widget.compact && widget.compactWithBorder - ? Theme.of( - context, - ).extension()!.textFieldDefaultBG - : null, - color: Theme.of(context).extension()!.popupBG, - boxShadow: - widget.data.selected && widget.raiseOnSelected - ? [ + borderColor: widget.compact && widget.compactWithBorder + ? Theme.of(context).extension()!.textFieldDefaultBG + : null, + color: Theme.of(context).extension()!.popupBG, + boxShadow: widget.data.selected && widget.raiseOnSelected + ? [ Theme.of( context, ).extension()!.standardBoxShadow, ] - : null, - child: Row( - children: [ - if (!(widget.compact && utxo.isBlocked)) - Checkbox( - value: widget.data.selected, - onChanged: (value) { - setState(() { - widget.data.selected = value!; - }); - widget.onSelectionChanged?.call(widget.data); - }, - ), - if (!(widget.compact && utxo.isBlocked)) - const SizedBox(width: 10), - UTXOStatusIcon( - blocked: utxo.isBlocked, - status: - (coin is Namecoin - ? (ref.watch(pWallets).getWallet(widget.walletId) + : null, + child: Row( + children: [ + if (!(widget.compact && utxo.isBlocked)) + Checkbox( + value: widget.data.selected, + onChanged: (value) { + setState(() { + widget.data.selected = value!; + }); + widget.onSelectionChanged?.call(widget.data); + }, + ), + if (!(widget.compact && utxo.isBlocked)) + const SizedBox(width: 10), + UTXOStatusIcon( + blocked: utxo.isBlocked, + status: + (coin is Namecoin + ? (ref.watch(pWallets).getWallet(widget.walletId) as NamecoinWallet) .checkUtxoConfirmed( utxo, @@ -164,89 +158,92 @@ class _UtxoRowState extends ConsumerState { pWalletChainHeight(widget.walletId), ), ) - : utxo.isConfirmed( + : utxo.isConfirmed( ref.watch(pWalletChainHeight(widget.walletId)), coin.minConfirms, coin.minCoinbaseConfirms, )) - ? UTXOStatusIconStatus.confirmed - : UTXOStatusIconStatus.unconfirmed, - background: Theme.of(context).extension()!.popupBG, - selected: false, - width: 32, - height: 32, - ), - const SizedBox(width: 10), - if (!widget.compact) - Text( - ref - .watch(pAmountFormatter(coin)) - .format( - Amount( - rawValue: BigInt.from(utxo.value), - fractionDigits: coin.fractionDigits, - ), - ), - textAlign: TextAlign.right, - style: STextStyles.w600_14(context), + ? UTXOStatusIconStatus.confirmed + : UTXOStatusIconStatus.unconfirmed, + background: Theme.of( + context, + ).extension()!.popupBG, + selected: false, + width: 32, + height: 32, ), - if (!widget.compact) const SizedBox(width: 10), - Expanded( - child: ConditionalParent( - condition: widget.compact, - builder: (child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - ref - .watch(pAmountFormatter(coin)) - .format( - Amount( - rawValue: BigInt.from(utxo.value), - fractionDigits: coin.fractionDigits, - ), - ), - textAlign: TextAlign.right, - style: STextStyles.w600_14(context), + const SizedBox(width: 10), + if (!widget.compact) + Text( + ref + .watch(pAmountFormatter(coin)) + .format( + Amount( + rawValue: BigInt.from(utxo.value), + fractionDigits: coin.fractionDigits, + ), ), - const SizedBox(height: 2), - child, - ], - ); - }, - child: Text( - utxo.name.isNotEmpty - ? utxo.name - : utxo.address ?? utxo.txid, - textAlign: - widget.compact ? TextAlign.left : TextAlign.center, - style: STextStyles.w500_12(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textSubtitle1, + textAlign: TextAlign.right, + style: STextStyles.w600_14(context), + ), + if (!widget.compact) const SizedBox(width: 10), + Expanded( + child: ConditionalParent( + condition: widget.compact, + builder: (child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + ref + .watch(pAmountFormatter(coin)) + .format( + Amount( + rawValue: BigInt.from(utxo.value), + fractionDigits: coin.fractionDigits, + ), + ), + textAlign: TextAlign.right, + style: STextStyles.w600_14(context), + ), + const SizedBox(height: 2), + child, + ], + ); + }, + child: Text( + utxo.name.isNotEmpty + ? utxo.name + : utxo.address ?? utxo.txid, + textAlign: widget.compact + ? TextAlign.left + : TextAlign.center, + style: STextStyles.w500_12(context).copyWith( + color: Theme.of( + context, + ).extension()!.textSubtitle1, + ), ), ), ), - ), - const SizedBox(width: 10), - AppBarIconButton( - size: 36, - shadows: const [], - color: Theme.of(context).extension()!.popupBG, - icon: SvgPicture.asset( - Assets.svg.verticalEllipsis, - color: - Theme.of(context).extension()!.textSubtitle1, - width: 20, - height: 20, + const SizedBox(width: 10), + AppBarIconButton( + size: 36, + shadows: const [], + color: Theme.of(context).extension()!.popupBG, + icon: SvgPicture.asset( + Assets.svg.verticalEllipsis, + color: Theme.of( + context, + ).extension()!.textSubtitle1, + width: 20, + height: 20, + ), + onPressed: _details, ), - onPressed: _details, - ), - ], - ), + ], + ), ), ); },