diff --git a/lib/pages/wallet_view/sub_widgets/transactions_list.dart b/lib/pages/wallet_view/sub_widgets/transactions_list.dart index 3d9b9c95e..bdfd00394 100644 --- a/lib/pages/wallet_view/sub_widgets/transactions_list.dart +++ b/lib/pages/wallet_view/sub_widgets/transactions_list.dart @@ -252,6 +252,7 @@ class _TransactionsListState extends ConsumerState { }, child: Util.isDesktop ? ListView.separated( + shrinkWrap: true, itemBuilder: (context, index) { BorderRadius? radius; if (_transactions2.length == 1) { diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart index d268474d3..469aeed71 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart @@ -39,6 +39,8 @@ class DesktopTokenView extends ConsumerStatefulWidget { } class _DesktopTokenViewState extends ConsumerState { + static const double sendReceiveColumnWidth = 460; + late final WalletSyncStatus initialSyncStatus; @override @@ -168,11 +170,58 @@ class _DesktopTokenViewState extends ConsumerState { const SizedBox( height: 24, ), + Row( + children: [ + SizedBox( + width: sendReceiveColumnWidth, + child: Text( + "My wallet", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, + ), + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Recent transactions", + style: + STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, + ), + ), + CustomTextButton( + text: "See all", + onTap: () { + Navigator.of(context).pushNamed( + AllTransactionsView.routeName, + arguments: widget.walletId, + ); + }, + ), + ], + ), + ), + ], + ), + const SizedBox( + height: 14, + ), Expanded( child: Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - width: 450, + width: sendReceiveColumnWidth, child: MyWallet( walletId: widget.walletId, contractAddress: ref.watch( @@ -186,40 +235,8 @@ class _DesktopTokenViewState extends ConsumerState { width: 16, ), Expanded( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Recent transactions", - style: STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconLeft, - ), - ), - CustomTextButton( - text: "See all", - onTap: () { - Navigator.of(context).pushNamed( - AllTransactionsView.routeName, - arguments: widget.walletId, - ); - }, - ), - ], - ), - const SizedBox( - height: 16, - ), - Expanded( - child: TokenTransactionsList( - walletId: widget.walletId, - ), - ), - ], + child: TokenTransactionsList( + walletId: widget.walletId, ), ), ], diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart index 18d211297..edfb0a1cc 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -309,6 +309,7 @@ class _DesktopWalletViewState extends ConsumerState { ), Expanded( child: Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: sendReceiveColumnWidth, diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart index b82aa3d02..f57ad8c2b 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/my_wallet.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/pages/wallet_view/sub_widgets/transactions_list.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_receive.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart'; -import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/send_receive_tab_menu.dart'; -import 'package:stackwallet/utilities/constants.dart'; -import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/providers/global/wallets_provider.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/widgets/custom_tab_view.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; -class MyWallet extends StatefulWidget { +class MyWallet extends ConsumerStatefulWidget { const MyWallet({ Key? key, required this.walletId, @@ -17,67 +20,82 @@ class MyWallet extends StatefulWidget { final String? contractAddress; @override - State createState() => _MyWalletState(); + ConsumerState createState() => _MyWalletState(); } -class _MyWalletState extends State { - int _selectedIndex = 0; +class _MyWalletState extends ConsumerState { + final titles = [ + "Send", + "Receive", + ]; + + late final bool isEth; + + @override + void initState() { + isEth = ref + .read(walletsChangeNotifierProvider) + .getManager(widget.walletId) + .coin == + Coin.ethereum; + + if (isEth && widget.contractAddress == null) { + titles.add("Transactions"); + } + + super.initState(); + } @override Widget build(BuildContext context) { return ListView( primary: false, children: [ - Container( - decoration: BoxDecoration( - color: Theme.of(context).extension()!.popupBG, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, - ), - ), - ), - child: SendReceiveTabMenu( - onChanged: (index) { - setState(() { - _selectedIndex = index; - }); - }, - ), - ), - Container( - decoration: BoxDecoration( - color: Theme.of(context).extension()!.popupBG, - borderRadius: BorderRadius.vertical( - bottom: Radius.circular( - Constants.size.circularBorderRadius, - ), - ), - ), - child: AnimatedCrossFade( - firstChild: Padding( - key: const Key("desktopSendViewPortKey"), - padding: const EdgeInsets.all(20), - child: widget.contractAddress == null - ? DesktopSend( - walletId: widget.walletId, + RoundedWhiteContainer( + padding: EdgeInsets.zero, + child: CustomTabView( + titles: titles, + children: [ + widget.contractAddress == null + ? Padding( + padding: const EdgeInsets.all(20), + child: DesktopSend( + walletId: widget.walletId, + ), ) - : DesktopTokenSend( - walletId: widget.walletId, + : Padding( + padding: const EdgeInsets.all(20), + child: DesktopTokenSend( + walletId: widget.walletId, + ), ), - ), - secondChild: Padding( - key: const Key("desktopReceiveViewPortKey"), - padding: const EdgeInsets.all(20), - child: DesktopReceive( - walletId: widget.walletId, - contractAddress: widget.contractAddress, + Padding( + padding: const EdgeInsets.all(20), + child: DesktopReceive( + walletId: widget.walletId, + contractAddress: widget.contractAddress, + ), ), - ), - crossFadeState: _selectedIndex == 0 - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - duration: const Duration(milliseconds: 250), + if (isEth && widget.contractAddress == null) + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height - 362, + ), + child: TransactionsList( + walletId: widget.walletId, + managerProvider: ref.watch( + walletsChangeNotifierProvider.select( + (value) => value.getManagerProvider( + widget.walletId, + ), + ), + ), + ), + ), + ), + ], ), ), ], diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/send_receive_tab_menu.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/send_receive_tab_menu.dart deleted file mode 100644 index f42ed297d..000000000 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/send_receive_tab_menu.dart +++ /dev/null @@ -1,165 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:stackwallet/utilities/text_styles.dart'; -import 'package:stackwallet/utilities/theme/stack_colors.dart'; - -class SendReceiveTabMenu extends StatefulWidget { - const SendReceiveTabMenu({ - Key? key, - this.initialIndex = 0, - this.onChanged, - }) : super(key: key); - - final int initialIndex; - final void Function(int)? onChanged; - - @override - State createState() => _SendReceiveTabMenuState(); -} - -class _SendReceiveTabMenuState extends State { - late int _selectedIndex; - - void _onChanged(int newIndex) { - if (_selectedIndex != newIndex) { - setState(() { - _selectedIndex = newIndex; - }); - widget.onChanged?.call(_selectedIndex); - } - } - - @override - void initState() { - _selectedIndex = widget.initialIndex; - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () => _onChanged(0), - child: Container( - color: Colors.transparent, - child: Column( - children: [ - const SizedBox( - height: 16, - ), - AnimatedCrossFade( - firstChild: Text( - "Send", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorBlue, - ), - ), - secondChild: Text( - "Send", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ), - crossFadeState: _selectedIndex == 0 - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - duration: const Duration(milliseconds: 250), - ), - const SizedBox( - height: 19, - ), - Container( - height: 2, - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .backgroundAppBar, - ), - ), - ], - ), - ), - ), - ), - ), - Expanded( - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () => _onChanged(1), - child: Container( - color: Colors.transparent, - child: Column( - children: [ - const SizedBox( - height: 16, - ), - AnimatedCrossFade( - firstChild: Text( - "Receive", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorBlue, - ), - ), - secondChild: Text( - "Receive", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ), - crossFadeState: _selectedIndex == 1 - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - duration: const Duration(milliseconds: 250), - ), - const SizedBox( - height: 19, - ), - Stack( - children: [ - Container( - height: 2, - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .backgroundAppBar, - ), - ), - AnimatedSlide( - offset: Offset(_selectedIndex == 0 ? -1 : 0, 0), - duration: const Duration(milliseconds: 250), - child: Container( - height: 2, - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .accentColorBlue), - ), - ), - ], - ), - ], - ), - ), - ), - ), - ), - ], - ); - } -} diff --git a/lib/widgets/custom_tab_view.dart b/lib/widgets/custom_tab_view.dart new file mode 100644 index 000000000..49fd81d18 --- /dev/null +++ b/lib/widgets/custom_tab_view.dart @@ -0,0 +1,151 @@ +import 'package:flutter/material.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; + +class CustomTabView extends StatefulWidget { + const CustomTabView({ + Key? key, + required this.titles, + required this.children, + this.initialIndex = 0, + this.childPadding, + }) : assert(titles.length == children.length), + super(key: key); + + final List titles; + final List children; + final int initialIndex; + final EdgeInsets? childPadding; + + @override + State createState() => _CustomTabViewState(); +} + +class _CustomTabViewState extends State { + final _key = GlobalKey(); + late int _selectedIndex; + + static const duration = Duration(milliseconds: 250); + + @override + void initState() { + _selectedIndex = widget.initialIndex; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + for (int i = 0; i < widget.titles.length; i++) + Expanded( + child: MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () => setState(() => _selectedIndex = i), + child: Container( + color: Colors.transparent, + child: Column( + children: [ + const SizedBox( + height: 16, + ), + AnimatedCrossFade( + firstChild: Text( + widget.titles[i], + style: + STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .accentColorBlue, + ), + ), + secondChild: Text( + widget.titles[i], + style: + STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + crossFadeState: _selectedIndex == i + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + duration: const Duration(milliseconds: 250), + ), + ], + ), + ), + ), + ), + ), + ], + ), + const SizedBox( + height: 19, + ), + Stack( + children: [ + Container( + height: 2, + decoration: BoxDecoration( + color: Theme.of(context) + .extension()! + .backgroundAppBar, + ), + ), + AnimatedSlide( + offset: Offset(_selectedIndex.toDouble(), 0), + duration: duration, + child: Container( + height: 2, + width: constraints.maxWidth / widget.titles.length, + decoration: BoxDecoration( + color: Theme.of(context) + .extension()! + .accentColorBlue, + ), + ), + ), + ], + ), + AnimatedSwitcher( + key: _key, + duration: duration, + transitionBuilder: (child, animation) { + return FadeTransition( + opacity: animation, + child: child, + ); + }, + layoutBuilder: (currentChild, prevChildren) { + return Stack( + alignment: Alignment.topCenter, + children: [ + ...prevChildren, + if (currentChild != null) currentChild, + ], + ); + }, + child: AnimatedAlign( + key: Key(widget.titles[_selectedIndex]), + alignment: Alignment.topCenter, + duration: duration, + child: Padding( + padding: widget.childPadding ?? EdgeInsets.zero, + child: widget.children[_selectedIndex], + ), + ), + ), + ], + ), + ); + } +}