desktop send/receive + transactions for eth view

This commit is contained in:
julian 2023-04-07 13:38:55 -06:00
parent b820b113e4
commit 387e2d8403
6 changed files with 277 additions and 254 deletions

View file

@ -252,6 +252,7 @@ class _TransactionsListState extends ConsumerState<TransactionsList> {
}, },
child: Util.isDesktop child: Util.isDesktop
? ListView.separated( ? ListView.separated(
shrinkWrap: true,
itemBuilder: (context, index) { itemBuilder: (context, index) {
BorderRadius? radius; BorderRadius? radius;
if (_transactions2.length == 1) { if (_transactions2.length == 1) {

View file

@ -39,6 +39,8 @@ class DesktopTokenView extends ConsumerStatefulWidget {
} }
class _DesktopTokenViewState extends ConsumerState<DesktopTokenView> { class _DesktopTokenViewState extends ConsumerState<DesktopTokenView> {
static const double sendReceiveColumnWidth = 460;
late final WalletSyncStatus initialSyncStatus; late final WalletSyncStatus initialSyncStatus;
@override @override
@ -168,11 +170,58 @@ class _DesktopTokenViewState extends ConsumerState<DesktopTokenView> {
const SizedBox( const SizedBox(
height: 24, height: 24,
), ),
Row(
children: [
SizedBox(
width: sendReceiveColumnWidth,
child: Text(
"My wallet",
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.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<StackColors>()!
.textFieldActiveSearchIconLeft,
),
),
CustomTextButton(
text: "See all",
onTap: () {
Navigator.of(context).pushNamed(
AllTransactionsView.routeName,
arguments: widget.walletId,
);
},
),
],
),
),
],
),
const SizedBox(
height: 14,
),
Expanded( Expanded(
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox( SizedBox(
width: 450, width: sendReceiveColumnWidth,
child: MyWallet( child: MyWallet(
walletId: widget.walletId, walletId: widget.walletId,
contractAddress: ref.watch( contractAddress: ref.watch(
@ -186,40 +235,8 @@ class _DesktopTokenViewState extends ConsumerState<DesktopTokenView> {
width: 16, width: 16,
), ),
Expanded( Expanded(
child: Column( child: TokenTransactionsList(
children: [ walletId: widget.walletId,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Recent transactions",
style: STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.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,
),
),
],
), ),
), ),
], ],

View file

@ -309,6 +309,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
), ),
Expanded( Expanded(
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox( SizedBox(
width: sendReceiveColumnWidth, width: sendReceiveColumnWidth,

View file

@ -1,12 +1,15 @@
import 'package:flutter/material.dart'; 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_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_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/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/providers/global/wallets_provider.dart';
import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/theme/stack_colors.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({ const MyWallet({
Key? key, Key? key,
required this.walletId, required this.walletId,
@ -17,67 +20,82 @@ class MyWallet extends StatefulWidget {
final String? contractAddress; final String? contractAddress;
@override @override
State<MyWallet> createState() => _MyWalletState(); ConsumerState<MyWallet> createState() => _MyWalletState();
} }
class _MyWalletState extends State<MyWallet> { class _MyWalletState extends ConsumerState<MyWallet> {
int _selectedIndex = 0; 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListView( return ListView(
primary: false, primary: false,
children: [ children: [
Container( RoundedWhiteContainer(
decoration: BoxDecoration( padding: EdgeInsets.zero,
color: Theme.of(context).extension<StackColors>()!.popupBG, child: CustomTabView(
borderRadius: BorderRadius.vertical( titles: titles,
top: Radius.circular( children: [
Constants.size.circularBorderRadius, widget.contractAddress == null
), ? Padding(
), padding: const EdgeInsets.all(20),
), child: DesktopSend(
child: SendReceiveTabMenu( walletId: widget.walletId,
onChanged: (index) { ),
setState(() {
_selectedIndex = index;
});
},
),
),
Container(
decoration: BoxDecoration(
color: Theme.of(context).extension<StackColors>()!.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,
) )
: DesktopTokenSend( : Padding(
walletId: widget.walletId, padding: const EdgeInsets.all(20),
child: DesktopTokenSend(
walletId: widget.walletId,
),
), ),
), Padding(
secondChild: Padding( padding: const EdgeInsets.all(20),
key: const Key("desktopReceiveViewPortKey"), child: DesktopReceive(
padding: const EdgeInsets.all(20), walletId: widget.walletId,
child: DesktopReceive( contractAddress: widget.contractAddress,
walletId: widget.walletId, ),
contractAddress: widget.contractAddress,
), ),
), if (isEth && widget.contractAddress == null)
crossFadeState: _selectedIndex == 0 Padding(
? CrossFadeState.showFirst padding: const EdgeInsets.only(top: 8.0),
: CrossFadeState.showSecond, child: ConstrainedBox(
duration: const Duration(milliseconds: 250), constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height - 362,
),
child: TransactionsList(
walletId: widget.walletId,
managerProvider: ref.watch(
walletsChangeNotifierProvider.select(
(value) => value.getManagerProvider(
widget.walletId,
),
),
),
),
),
),
],
), ),
), ),
], ],

View file

@ -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<SendReceiveTabMenu> createState() => _SendReceiveTabMenuState();
}
class _SendReceiveTabMenuState extends State<SendReceiveTabMenu> {
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<StackColors>()!
.accentColorBlue,
),
),
secondChild: Text(
"Send",
style:
STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.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<StackColors>()!
.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<StackColors>()!
.accentColorBlue,
),
),
secondChild: Text(
"Receive",
style:
STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.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<StackColors>()!
.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<StackColors>()!
.accentColorBlue),
),
),
],
),
],
),
),
),
),
),
],
);
}
}

View file

@ -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<String> titles;
final List<Widget> children;
final int initialIndex;
final EdgeInsets? childPadding;
@override
State<CustomTabView> createState() => _CustomTabViewState();
}
class _CustomTabViewState extends State<CustomTabView> {
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<StackColors>()!
.accentColorBlue,
),
),
secondChild: Text(
widget.titles[i],
style:
STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.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<StackColors>()!
.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<StackColors>()!
.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],
),
),
),
],
),
);
}
}