From e64c0672121fd0e0151d3ec3b70125623059a97a Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 28 Oct 2022 15:11:01 -0600 Subject: [PATCH] desktop all transaction list item layout --- .../all_transactions_view.dart | 268 +++++++++++++++++- 1 file changed, 257 insertions(+), 11 deletions(-) diff --git a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart index 7122f5379..192389720 100644 --- a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart +++ b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart @@ -1,15 +1,23 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/models/contact.dart'; import 'package:stackwallet/models/paymint/transactions_model.dart'; import 'package:stackwallet/models/transaction_filter.dart'; +import 'package:stackwallet/notifications/show_flush_bar.dart'; +import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart'; +import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart'; import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_search_filter_view.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/ui/transaction_filter_provider.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/flush_bar_type.dart'; +import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; @@ -437,21 +445,46 @@ class _TransactionDetailsViewState extends ConsumerState { const SizedBox( height: 12, ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( - children: [ - ...month.item2.map( - (tx) => TransactionCard( - key: Key( - "transactionCard_key_${tx.txid}"), - transaction: tx, + if (isDesktop) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: ListView.separated( + shrinkWrap: true, + primary: false, + separatorBuilder: (context, _) => + Container( + height: 1, + color: Theme.of(context) + .extension()! + .background, + ), + itemCount: month.item2.length, + itemBuilder: (context, index) => + Padding( + padding: const EdgeInsets.all(4), + child: DesktopTransactionCardRow( + transaction: month.item2[index], walletId: walletId, ), ), - ], + ), + ), + if (!isDesktop) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + children: [ + ...month.item2.map( + (tx) => TransactionCard( + key: Key( + "transactionCard_key_${tx.txid}"), + transaction: tx, + walletId: walletId, + ), + ), + ], + ), ), - ), ], ), ); @@ -472,3 +505,216 @@ class _TransactionDetailsViewState extends ConsumerState { ); } } + +class DesktopTransactionCardRow extends ConsumerStatefulWidget { + const DesktopTransactionCardRow({ + Key? key, + required this.transaction, + required this.walletId, + }) : super(key: key); + + final Transaction transaction; + final String walletId; + + @override + ConsumerState createState() => + _DesktopTransactionCardRowState(); +} + +class _DesktopTransactionCardRowState + extends ConsumerState { + late final Transaction _transaction; + late final String walletId; + + String whatIsIt(String type, Coin coin) { + if (coin == Coin.epicCash && _transaction.slateId == null) { + return "Restored Funds"; + } + + if (_transaction.subType == "mint") { + if (_transaction.confirmedStatus) { + return "Anonymized"; + } else { + return "Anonymizing"; + } + } + + if (type == "Received") { + if (_transaction.confirmedStatus) { + return "Received"; + } else { + return "Receiving"; + } + } else if (type == "Sent") { + if (_transaction.confirmedStatus) { + return "Sent"; + } else { + return "Sending"; + } + } else { + return type; + } + } + + @override + void initState() { + walletId = widget.walletId; + _transaction = widget.transaction; + super.initState(); + } + + @override + Widget build(BuildContext context) { + final locale = ref.watch( + localeServiceChangeNotifierProvider.select((value) => value.locale)); + final manager = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManager(walletId))); + + final baseCurrency = ref + .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + + final coin = manager.coin; + + final price = ref + .watch(priceAnd24hChangeNotifierProvider + .select((value) => value.getPrice(coin))) + .item1; + + late final String prefix; + if (Util.isDesktop) { + if (_transaction.txType == "Sent") { + prefix = "-"; + } else if (_transaction.txType == "Received") { + prefix = "+"; + } + } else { + prefix = ""; + } + + return Material( + color: Theme.of(context).extension()!.popupBG, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(Constants.size.circularBorderRadius), + ), + child: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () async { + if (coin == Coin.epicCash && _transaction.slateId == null) { + unawaited( + showFloatingFlushBar( + context: context, + message: + "Restored Epic funds from your Seed have no Data.\nUse Stack Backup to keep your transaction history.", + type: FlushBarType.warning, + duration: const Duration(seconds: 5), + ), + ); + return; + } + unawaited( + Navigator.of(context).pushNamed( + TransactionDetailsView.routeName, + arguments: Tuple3( + _transaction, + coin, + walletId, + ), + ), + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ), + child: Row( + children: [ + TxIcon(transaction: _transaction), + const SizedBox( + width: 12, + ), + Expanded( + flex: 3, + child: Text( + _transaction.isCancelled + ? "Cancelled" + : whatIsIt(_transaction.txType, coin), + style: + STextStyles.desktopTextExtraExtraSmall(context).copyWith( + color: Theme.of(context).extension()!.textDark, + ), + ), + ), + Expanded( + flex: 4, + child: Text( + Format.extractDateFrom(_transaction.timestamp), + style: STextStyles.label(context), + ), + ), + Expanded( + flex: 6, + child: Builder( + builder: (_) { + final amount = coin == Coin.monero + ? (_transaction.amount ~/ 10000) + : coin == Coin.wownero + ? (_transaction.amount ~/ 1000) + : _transaction.amount; + return Text( + "$prefix${Format.satoshiAmountToPrettyString(amount, locale)} ${coin.ticker}", + style: STextStyles.desktopTextExtraExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark, + ), + ); + }, + ), + ), + if (ref.watch(prefsChangeNotifierProvider + .select((value) => value.externalCalls))) + Expanded( + flex: 4, + child: Builder( + builder: (_) { + // TODO: modify Format. to take optional Coin parameter so this type oif check isn't done in ui + int value = _transaction.amount; + if (coin == Coin.monero) { + value = (value ~/ 10000); + } else if (coin == Coin.wownero) { + value = (value ~/ 1000); + } + + return Text( + "$prefix${Format.localizedStringAsFixed( + value: Format.satoshisToAmount(value) * price, + locale: locale, + decimalPlaces: 2, + )} $baseCurrency", + style: STextStyles.desktopTextExtraExtraSmall(context), + ); + }, + ), + ), + SvgPicture.asset( + Assets.svg.circleInfo, + width: 20, + height: 20, + color: + Theme.of(context).extension()!.textSubtitle2, + ), + ], + ), + ), + ), + ); + } +}