diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart index 76c845027..602d588da 100644 --- a/lib/pages/exchange_view/trade_details_view.dart +++ b/lib/pages/exchange_view/trade_details_view.dart @@ -15,17 +15,23 @@ import 'package:stackwallet/pages/wallet_view/transaction_views/edit_note_view.d import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart'; import 'package:stackwallet/providers/global/trades_service_provider.dart'; import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; import 'package:stackwallet/services/exchange/exchange.dart'; import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/clipboard_interface.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'; +import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_container.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; @@ -157,34 +163,113 @@ class _TradeDetailsViewState extends ConsumerState { final sendAmount = Decimal.tryParse(trade.payInAmount) ?? Decimal.parse("-1"); - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( + final isDesktop = Util.isDesktop; + + return ConditionalParent( + condition: !isDesktop, + builder: (child) => Scaffold( backgroundColor: Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Trade details", + style: STextStyles.navBarTitle(context), + ), ), - title: Text( - "Trade details", - style: STextStyles.navBarTitle(context), + body: Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), ), ), - body: Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( + child: Padding( + padding: isDesktop + ? const EdgeInsets.only(left: 32) + : const EdgeInsets.all(0), + child: BranchedParent( + condition: isDesktop, + conditionBranchBuilder: (children) => Padding( + padding: const EdgeInsets.only( + right: 20, + ), + child: Padding( + padding: const EdgeInsets.only( + right: 12, + ), + child: RoundedWhiteContainer( + borderColor: isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: const EdgeInsets.all(0), + child: ListView( + primary: false, + shrinkWrap: true, + children: children, + ), + ), + ), + ), + otherBranchBuilder: (children) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, + children: children, + ), + children: [ + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(12), + child: Container( + decoration: isDesktop + ? BoxDecoration( + color: Theme.of(context) + .extension()! + .background, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants.size.circularBorderRadius, + ), + ), + ) + : null, + child: Padding( + padding: isDesktop + ? const EdgeInsets.all(12) + : const EdgeInsets.all(0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + if (isDesktop) + Row( + children: [ + SvgPicture.asset( + _fetchIconAssetForStatus(trade.status), + width: 32, + height: 32, + ), + const SizedBox( + width: 16, + ), + SelectableText( + "Exchange", + style: STextStyles.desktopTextMedium(context), + ), + ], + ), Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: isDesktop + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, children: [ SelectableText( "${trade.payInCurrency.toUpperCase()} → ${trade.payOutCurrency.toUpperCase()}", @@ -194,7 +279,7 @@ class _TradeDetailsViewState extends ConsumerState { height: 4, ), SelectableText( - "${Format.localizedStringAsFixed(value: sendAmount, locale: ref.watch( + "-${Format.localizedStringAsFixed(value: sendAmount, locale: ref.watch( localeServiceChangeNotifierProvider .select((value) => value.locale), ), decimalPlaces: trade.payInCurrency.toLowerCase() == "xmr" ? 12 : 8)} ${trade.payInCurrency.toUpperCase()}", @@ -202,136 +287,178 @@ class _TradeDetailsViewState extends ConsumerState { ), ], ), - Container( - width: 32, - height: 32, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(32), - ), - child: Center( - child: SvgPicture.asset( - _fetchIconAssetForStatus(trade.status), - width: 32, - height: 32, + if (!isDesktop) + Container( + width: 32, + height: 32, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(32), + ), + child: Center( + child: SvgPicture.asset( + _fetchIconAssetForStatus(trade.status), + width: 32, + height: 32, + ), ), ), - ), ], ), ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Status", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - trade.status, - style: STextStyles.itemSubtitle(context).copyWith( - color: Theme.of(context) - .extension()! - .colorForStatus(trade.status), - ), - ), - // ), - // ), - ], - ), - ), - if (!sentFromStack && !hasTx) - const SizedBox( + ), + ), + isDesktop + ? const _Divider() + : const SizedBox( height: 12, ), - if (!sentFromStack && !hasTx) - RoundedContainer( - color: Theme.of(context) - .extension()! - .warningBackground, - child: RichText( - text: TextSpan( + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Status", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox( + height: 4, + ), + SelectableText( + trade.status, + style: STextStyles.itemSubtitle(context).copyWith( + color: Theme.of(context) + .extension()! + .colorForStatus(trade.status), + ), + ), + // ), + // ), + ], + ), + ), + if (!sentFromStack && !hasTx) + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), + if (!sentFromStack && !hasTx) + RoundedContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + color: Theme.of(context) + .extension()! + .warningBackground, + child: RichText( + text: TextSpan( + text: + "You must send at least ${sendAmount.toStringAsFixed( + trade.payInCurrency.toLowerCase() == "xmr" ? 12 : 8, + )} ${trade.payInCurrency.toUpperCase()}. ", + style: STextStyles.label700(context).copyWith( + color: Theme.of(context) + .extension()! + .warningForeground, + ), + children: [ + TextSpan( text: - "You must send at least ${sendAmount.toStringAsFixed( + "If you send less than ${sendAmount.toStringAsFixed( trade.payInCurrency.toLowerCase() == "xmr" ? 12 : 8, - )} ${trade.payInCurrency.toUpperCase()}. ", - style: STextStyles.label700(context).copyWith( + )} ${trade.payInCurrency.toUpperCase()}, your transaction may not be converted and it may not be refunded.", + style: STextStyles.label(context).copyWith( color: Theme.of(context) .extension()! .warningForeground, ), - children: [ - TextSpan( - text: - "If you send less than ${sendAmount.toStringAsFixed( - trade.payInCurrency.toLowerCase() == "xmr" - ? 12 - : 8, - )} ${trade.payInCurrency.toUpperCase()}, your transaction may not be converted and it may not be refunded.", - style: STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + ), + ]), + ), + ), + if (sentFromStack) + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), + if (sentFromStack) + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Sent from", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox( + height: 4, + ), + SelectableText( + widget.walletName!, + style: STextStyles.itemSubtitle12(context), + ), + const SizedBox( + height: 10, + ), + BlueTextButton( + text: "View transaction", + onTap: () { + final Coin coin = + coinFromTickerCaseInsensitive(trade.payInCurrency); + + if (isDesktop) { + Navigator.of(context).push( + FadePageRoute( + DesktopDialog( + maxHeight: + MediaQuery.of(context).size.height - 64, + maxWidth: 580, + child: TransactionDetailsView( + coin: coin, + transaction: transactionIfSentFromStack!, + walletId: walletId!, + ), + ), + const RouteSettings( + name: TransactionDetailsView.routeName, ), ), - ]), + ); + } else { + Navigator.of(context).pushNamed( + TransactionDetailsView.routeName, + arguments: Tuple3( + transactionIfSentFromStack!, coin, walletId!), + ); + } + }, ), - ), - if (sentFromStack) - const SizedBox( - height: 12, - ), - if (sentFromStack) - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Sent from", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - widget.walletName!, - style: STextStyles.itemSubtitle12(context), - ), - const SizedBox( - height: 10, - ), - GestureDetector( - onTap: () { - final Coin coin = coinFromTickerCaseInsensitive( - trade.payInCurrency); - - Navigator.of(context).pushNamed( - TransactionDetailsView.routeName, - arguments: Tuple3( - transactionIfSentFromStack!, coin, walletId!), - ); - }, - child: Text( - "View transaction", - style: STextStyles.link2(context), - ), - ), - ], + ], + ), + ), + if (sentFromStack) + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, ), - ), - if (sentFromStack) - const SizedBox( - height: 12, - ), - if (sentFromStack) - RoundedWhiteContainer( - child: Column( + if (sentFromStack) + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( @@ -347,252 +474,224 @@ class _TradeDetailsViewState extends ConsumerState { ), ], ), - ), - if (!sentFromStack && !hasTx) - const SizedBox( - height: 12, - ), - if (!sentFromStack && !hasTx) - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + if (isDesktop) + IconCopyButton( + data: trade.payInAddress, + ), + ], + ), + ), + if (!sentFromStack && !hasTx) + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), + if (!sentFromStack && !hasTx) + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Send ${trade.payInCurrency.toUpperCase()} to this address", - style: STextStyles.itemSubtitle(context), - ), - GestureDetector( - onTap: () async { - final address = trade.payInAddress; - await Clipboard.setData( - ClipboardData( - text: address, - ), - ); - unawaited(showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - )); - }, - child: Row( + Text( + "Send ${trade.payInCurrency.toUpperCase()} to this address", + style: STextStyles.itemSubtitle(context), + ), + isDesktop + ? IconCopyButton( + data: trade.payInAddress, + ) + : GestureDetector( + onTap: () async { + final address = trade.payInAddress; + await Clipboard.setData( + ClipboardData( + text: address, + ), + ); + unawaited(showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + context: context, + )); + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + width: 12, + height: 12, + color: Theme.of(context) + .extension()! + .infoItemIcons, + ), + const SizedBox( + width: 4, + ), + Text( + "Copy", + style: STextStyles.link2(context), + ), + ], + ), + ), + ], + ), + const SizedBox( + height: 4, + ), + SelectableText( + trade.payInAddress, + style: STextStyles.itemSubtitle12(context), + ), + const SizedBox( + height: 10, + ), + GestureDetector( + onTap: () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (_) { + final width = MediaQuery.of(context).size.width / 2; + return StackDialogBase( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - SvgPicture.asset( - Assets.svg.copy, - width: 12, - height: 12, - color: Theme.of(context) - .extension()! - .infoItemIcons, + Center( + child: Text( + "Send ${trade.payInCurrency.toUpperCase()} to this address", + style: STextStyles.pageTitleH2(context), + ), ), const SizedBox( - width: 4, + height: 12, ), - Text( - "Copy", - style: STextStyles.link2(context), + Center( + child: RepaintBoundary( + // key: _qrKey, + child: SizedBox( + width: width + 20, + height: width + 20, + child: QrImage( + data: trade.payInAddress, + size: width, + backgroundColor: Theme.of(context) + .extension()! + .popupBG, + foregroundColor: Theme.of(context) + .extension()! + .accentColorDark), + ), + ), + ), + const SizedBox( + height: 12, + ), + Center( + child: SizedBox( + width: width, + child: TextButton( + onPressed: () async { + // await _capturePng(true); + Navigator.of(context).pop(); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonColor( + context), + child: Text( + "Cancel", + style: STextStyles.button(context) + .copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + ), + ), ), ], ), - ), - ], - ), - const SizedBox( - height: 4, - ), - SelectableText( - trade.payInAddress, - style: STextStyles.itemSubtitle12(context), - ), - const SizedBox( - height: 10, - ), - GestureDetector( - onTap: () { - showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (_) { - final width = - MediaQuery.of(context).size.width / 2; - return StackDialogBase( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Center( - child: Text( - "Send ${trade.payInCurrency.toUpperCase()} to this address", - style: - STextStyles.pageTitleH2(context), - ), - ), - const SizedBox( - height: 12, - ), - Center( - child: RepaintBoundary( - // key: _qrKey, - child: SizedBox( - width: width + 20, - height: width + 20, - child: QrImage( - data: trade.payInAddress, - size: width, - backgroundColor: Theme.of( - context) - .extension()! - .popupBG, - foregroundColor: Theme.of( - context) - .extension()! - .accentColorDark), - ), - ), - ), - const SizedBox( - height: 12, - ), - Center( - child: SizedBox( - width: width, - child: TextButton( - onPressed: () async { - // await _capturePng(true); - Navigator.of(context).pop(); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonColor( - context), - child: Text( - "Cancel", - style: STextStyles.button(context) - .copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .accentColorDark), - ), - ), - ), - ), - ], - ), - ); - }, ); }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.qrcode, - width: 12, - height: 12, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Show QR code", - style: STextStyles.link2(context), - ), - ], - ), - ), - ], - ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + ); + }, + child: Row( children: [ - Text( - "Trade note", - style: STextStyles.itemSubtitle(context), + SvgPicture.asset( + Assets.svg.qrcode, + width: 12, + height: 12, + color: Theme.of(context) + .extension()! + .infoItemIcons, ), - GestureDetector( - onTap: () { - Navigator.of(context).pushNamed( - EditTradeNoteView.routeName, - arguments: Tuple2( - tradeId, - ref - .read(tradeNoteServiceProvider) - .getNote(tradeId: tradeId), - ), - ); - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Edit", - style: STextStyles.link2(context), - ), - ], - ), + const SizedBox( + width: 4, + ), + Text( + "Show QR code", + style: STextStyles.link2(context), ), ], ), - const SizedBox( - height: 4, - ), - SelectableText( - ref.watch(tradeNoteServiceProvider.select( - (value) => value.getNote(tradeId: tradeId))), - style: STextStyles.itemSubtitle12(context), - ), - ], - ), + ), + ], ), - if (sentFromStack) - const SizedBox( + ), + isDesktop + ? const _Divider() + : const SizedBox( height: 12, ), - if (sentFromStack) - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Transaction note", - style: STextStyles.itemSubtitle(context), - ), - GestureDetector( + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Trade note", + style: STextStyles.itemSubtitle(context), + ), + isDesktop + ? IconPencilButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: EditTradeNoteView( + tradeId: tradeId, + note: _note, + ), + ); + }, + ); + }, + ) + : GestureDetector( onTap: () { Navigator.of(context).pushNamed( - EditNoteView.routeName, - arguments: Tuple3( - transactionIfSentFromStack!.txid, - walletId!, - _note, + EditTradeNoteView.routeName, + arguments: Tuple2( + tradeId, + ref + .read(tradeNoteServiceProvider) + .getNote(tradeId: tradeId), ), ); }, @@ -616,193 +715,371 @@ class _TradeDetailsViewState extends ConsumerState { ], ), ), - ], - ), - const SizedBox( - height: 4, - ), - FutureBuilder( - future: ref.watch( - notesServiceChangeNotifierProvider(walletId!) - .select((value) => value.getNoteFor( - txid: transactionIfSentFromStack!.txid))), - builder: - (builderContext, AsyncSnapshot snapshot) { - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - _note = snapshot.data ?? ""; - } - return SelectableText( - _note, - style: STextStyles.itemSubtitle12(context), - ); - }, + ], + ), + const SizedBox( + height: 4, + ), + SelectableText( + ref.watch(tradeNoteServiceProvider + .select((value) => value.getNote(tradeId: tradeId))), + style: STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + if (sentFromStack) + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), + if (sentFromStack) + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction note", + style: STextStyles.itemSubtitle(context), ), + isDesktop + ? IconPencilButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: EditNoteView( + txid: + transactionIfSentFromStack!.txid, + walletId: walletId!, + note: _note, + ), + ); + }, + ); + }, + ) + : GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + EditNoteView.routeName, + arguments: Tuple3( + transactionIfSentFromStack!.txid, + walletId!, + _note, + ), + ); + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, + color: Theme.of(context) + .extension()! + .infoItemIcons, + ), + const SizedBox( + width: 4, + ), + Text( + "Edit", + style: STextStyles.link2(context), + ), + ], + ), + ), ], ), - ), - const SizedBox( - height: 12, + const SizedBox( + height: 4, + ), + FutureBuilder( + future: ref.watch( + notesServiceChangeNotifierProvider(walletId!).select( + (value) => value.getNoteFor( + txid: transactionIfSentFromStack!.txid))), + builder: + (builderContext, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + _note = snapshot.data ?? ""; + } + return SelectableText( + _note, + style: STextStyles.itemSubtitle12(context), + ); + }, + ), + ], ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + ), + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Date", style: STextStyles.itemSubtitle(context), ), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - Format.extractDateFrom( - trade.timestamp.millisecondsSinceEpoch ~/ 1000), - style: STextStyles.itemSubtitle12(context), - ), - // ), - // ), + if (isDesktop) + const SizedBox( + height: 2, + ), + if (isDesktop) + SelectableText( + Format.extractDateFrom( + trade.timestamp.millisecondsSinceEpoch ~/ 1000), + style: STextStyles.desktopTextExtraExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark, + ), + ), ], ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + if (!isDesktop) + SelectableText( + Format.extractDateFrom( + trade.timestamp.millisecondsSinceEpoch ~/ 1000), + style: STextStyles.itemSubtitle12(context), + ), + if (isDesktop) + IconCopyButton( + data: Format.extractDateFrom( + trade.timestamp.millisecondsSinceEpoch ~/ 1000), + ), + ], + ), + ), + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Exchange", style: STextStyles.itemSubtitle(context), ), - SelectableText( - trade.exchangeName, - style: STextStyles.itemSubtitle12(context), - ), + if (isDesktop) + const SizedBox( + height: 2, + ), + if (isDesktop) + SelectableText( + trade.exchangeName, + style: STextStyles.itemSubtitle12(context), + ), ], ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Row( + if (isDesktop) + IconCopyButton( + data: trade.exchangeName, + ), + if (!isDesktop) + SelectableText( + trade.exchangeName, + style: STextStyles.itemSubtitle12(context), + ), + ], + ), + ), + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Trade ID", style: STextStyles.itemSubtitle(context), ), - const Spacer(), - Row( - children: [ - Text( - trade.tradeId, - style: STextStyles.itemSubtitle12(context), - ), - const SizedBox( - width: 10, - ), - GestureDetector( - onTap: () async { - final data = ClipboardData(text: trade.tradeId); - await clipboard.setData(data); - unawaited(showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - )); - }, - child: SvgPicture.asset( - Assets.svg.copy, - color: Theme.of(context) - .extension()! - .infoItemIcons, - width: 12, - ), - ) - ], - ) - ], - ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Tracking", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 4, - ), - Builder(builder: (context) { - late final String url; - switch (trade.exchangeName) { - case ChangeNowExchange.exchangeName: - url = - "https://changenow.io/exchange/txs/${trade.tradeId}"; - break; - case SimpleSwapExchange.exchangeName: - url = - "https://simpleswap.io/exchange?id=${trade.tradeId}"; - break; - } - return GestureDetector( - onTap: () { - launchUrl( - Uri.parse(url), - mode: LaunchMode.externalApplication, - ); - }, - child: Text( - url, - style: STextStyles.link2(context), - ), - ); - }), - ], - ), - ), - const SizedBox( - height: 12, - ), - if (isStackCoin(trade.payInCurrency) && - (trade.status == "New" || - trade.status == "new" || - trade.status == "waiting" || - trade.status == "Waiting")) - SecondaryButton( - label: "Send from Stack", - onPressed: () { - final amount = sendAmount; - final address = trade.payInAddress; - - final coin = - coinFromTickerCaseInsensitive(trade.payInCurrency); - - Navigator.of(context).pushNamed( - SendFromView.routeName, - arguments: Tuple4( - coin, - amount, - address, - trade, + if (isDesktop) + const SizedBox( + height: 2, ), - ); - }, + if (isDesktop) + Text( + trade.tradeId, + style: STextStyles.itemSubtitle12(context), + ), + ], ), - ], + if (isDesktop) + IconCopyButton( + data: trade.tradeId, + ), + if (!isDesktop) + Row( + children: [ + Text( + trade.tradeId, + style: STextStyles.itemSubtitle12(context), + ), + const SizedBox( + width: 10, + ), + GestureDetector( + onTap: () async { + final data = ClipboardData(text: trade.tradeId); + await clipboard.setData(data); + unawaited(showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + context: context, + )); + }, + child: SvgPicture.asset( + Assets.svg.copy, + color: Theme.of(context) + .extension()! + .infoItemIcons, + width: 12, + ), + ) + ], + ), + ], + ), ), - ), + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), + RoundedWhiteContainer( + padding: isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Tracking", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox( + height: 4, + ), + Builder(builder: (context) { + late final String url; + switch (trade.exchangeName) { + case ChangeNowExchange.exchangeName: + url = + "https://changenow.io/exchange/txs/${trade.tradeId}"; + break; + case SimpleSwapExchange.exchangeName: + url = + "https://simpleswap.io/exchange?id=${trade.tradeId}"; + break; + } + return GestureDetector( + onTap: () { + launchUrl( + Uri.parse(url), + mode: LaunchMode.externalApplication, + ); + }, + child: Text( + url, + style: STextStyles.link2(context), + ), + ); + }), + ], + ), + ), + isDesktop + ? const _Divider() + : const SizedBox( + height: 12, + ), + if (isStackCoin(trade.payInCurrency) && + (trade.status == "New" || + trade.status == "new" || + trade.status == "waiting" || + trade.status == "Waiting")) + SecondaryButton( + label: "Send from Stack", + onPressed: () { + final amount = sendAmount; + final address = trade.payInAddress; + + final coin = + coinFromTickerCaseInsensitive(trade.payInCurrency); + + Navigator.of(context).pushNamed( + SendFromView.routeName, + arguments: Tuple4( + coin, + amount, + address, + trade, + ), + ); + }, + ), + ], ), ), ); } } + +class _Divider extends StatelessWidget { + const _Divider({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 1, + color: Theme.of(context).extension()!.background, + ); + } +} diff --git a/lib/pages/wallet_view/sub_widgets/transactions_list.dart b/lib/pages/wallet_view/sub_widgets/transactions_list.dart index d23d3082f..11353c7c6 100644 --- a/lib/pages/wallet_view/sub_widgets/transactions_list.dart +++ b/lib/pages/wallet_view/sub_widgets/transactions_list.dart @@ -7,10 +7,14 @@ import 'package:stackwallet/pages/exchange_view/trade_details_view.dart'; import 'package:stackwallet/pages/wallet_view/sub_widgets/no_transactions_found.dart'; import 'package:stackwallet/providers/global/trades_service_provider.dart'; import 'package:stackwallet/providers/global/wallets_provider.dart'; +import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/services/coins/manager.dart'; import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/loading_indicator.dart'; import 'package:stackwallet/widgets/trade_card.dart'; import 'package:stackwallet/widgets/transaction_card.dart'; @@ -94,18 +98,79 @@ class _TransactionsListState extends ConsumerState { // this may mess with combined firo transactions key: Key(tx.toString() + trade.uuid), // trade: trade, - onTap: () { - unawaited( - Navigator.of(context).pushNamed( - TradeDetailsView.routeName, - arguments: Tuple4( - trade.tradeId, - tx, - widget.walletId, - ref.read(managerProvider).walletName, + onTap: () async { + if (Util.isDesktop) { + await showDialog( + context: context, + builder: (context) => Navigator( + initialRoute: TradeDetailsView.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + FadePageRoute( + DesktopDialog( + // maxHeight: + // MediaQuery.of(context).size.height - 64, + maxHeight: double.infinity, + maxWidth: 580, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + bottom: 16, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Trade details", + style: STextStyles.desktopH3(context), + ), + DesktopDialogCloseButton( + onPressedOverride: Navigator.of( + context, + rootNavigator: true, + ).pop, + ), + ], + ), + ), + Flexible( + child: TradeDetailsView( + tradeId: trade.tradeId, + transactionIfSentFromStack: tx, + walletName: + ref.read(managerProvider).walletName, + walletId: widget.walletId, + ), + ), + ], + ), + ), + const RouteSettings( + name: TradeDetailsView.routeName, + ), + ), + ]; + }, ), - ), - ); + ); + } else { + unawaited( + Navigator.of(context).pushNamed( + TradeDetailsView.routeName, + arguments: Tuple4( + trade.tradeId, + tx, + widget.walletId, + ref.read(managerProvider).walletName, + ), + ), + ); + } }, ) ],