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 e3d7bf0b6..7122f5379 100644 --- a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart +++ b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart @@ -306,7 +306,7 @@ class _TransactionDetailsViewState extends ConsumerState { "Search", searchFieldFocusNode, context, - desktopMed: true, + desktopMed: isDesktop, ).copyWith( prefixIcon: Padding( padding: EdgeInsets.symmetric( @@ -330,6 +330,7 @@ class _TransactionDetailsViewState extends ConsumerState { onTap: () async { setState(() { _searchController.text = ""; + _searchString = ""; }); }, ), @@ -342,31 +343,45 @@ class _TransactionDetailsViewState extends ConsumerState { ), ), ), - const SizedBox( - width: 20, - ), - SecondaryButton( - desktopMed: true, - width: 200, - label: "Filter", - icon: SvgPicture.asset( - Assets.svg.filter, - color: Theme.of(context) - .extension()! - .accentColorDark, + if (isDesktop) + const SizedBox( width: 20, - height: 20, ), - onPressed: () { - Navigator.of(context).pushNamed( - TransactionSearchFilterView.routeName, - arguments: ref + if (isDesktop) + SecondaryButton( + desktopMed: isDesktop, + width: 200, + label: "Filter", + icon: SvgPicture.asset( + Assets.svg.filter, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 20, + height: 20, + ), + onPressed: () { + final coin = ref .read(walletsChangeNotifierProvider) .getManager(walletId) - .coin, - ); - }, - ), + .coin; + if (isDesktop) { + showDialog( + context: context, + builder: (context) { + return TransactionSearchFilterView( + coin: coin, + ); + }, + ); + } else { + Navigator.of(context).pushNamed( + TransactionSearchFilterView.routeName, + arguments: coin, + ); + } + }, + ), ], ), ), @@ -402,6 +417,7 @@ class _TransactionDetailsViewState extends ConsumerState { final monthlyList = groupTransactionsByMonth(searched); return ListView.builder( + primary: isDesktop ? false : null, itemCount: monthlyList.length, itemBuilder: (_, index) { final month = monthlyList[index]; diff --git a/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart b/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart index f9932c672..7d18d4428 100644 --- a/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart +++ b/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart @@ -16,6 +16,10 @@ 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/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; @@ -43,6 +47,7 @@ class _TransactionSearchViewState bool _isActiveReceivedCheckbox = false; bool _isActiveSentCheckbox = false; + bool _isActiveTradeCheckbox = false; String _fromDateString = ""; String _toDateString = ""; @@ -63,6 +68,9 @@ class _TransactionSearchViewState _selectedFromDate = filterState.from; _keywordTextEditingController.text = filterState.keyword; + _fromDateString = Format.formatDate(_selectedFromDate); + _toDateString = Format.formatDate(_selectedToDate); + // TODO: Fix XMR (modify Format.funcs to take optional Coin parameter) // final amt = Format.satoshisToAmount(widget.coin == Coin.monero ? ) String amount = ""; @@ -166,104 +174,113 @@ class _TransactionSearchViewState Widget _buildDateRangePicker() { const middleSeparatorPadding = 2.0; const middleSeparatorWidth = 12.0; - final width = (MediaQuery.of(context).size.width - - (middleSeparatorWidth + - (2 * middleSeparatorPadding) + - (2 * Constants.size.standardPadding))) / - 2; + final isDesktop = Util.isDesktop; + + final width = isDesktop + ? null + : (MediaQuery.of(context).size.width - + (middleSeparatorWidth + + (2 * middleSeparatorPadding) + + (2 * Constants.size.standardPadding))) / + 2; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - GestureDetector( - key: const Key("transactionSearchViewFromDatePickerKey"), - onTap: () async { - final color = - Theme.of(context).extension()!.accentColorDark; - final height = MediaQuery.of(context).size.height; - // check and hide keyboard - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 125)); - } - - final date = await showRoundedDatePicker( - // This doesn't change statusbar color... - // background: CFColors.starryNight.withOpacity(0.8), - context: context, - initialDate: DateTime.now(), - height: height * 0.5, - theme: ThemeData( - primarySwatch: Util.createMaterialColor( - color, - ), - ), - //TODO pick a better initial date - // 2007 chosen as that is just before bitcoin launched - firstDate: DateTime(2007), - lastDate: DateTime.now(), - borderRadius: Constants.size.circularBorderRadius * 2, - - textPositiveButton: "SELECT", - - styleDatePicker: _buildDatePickerStyle(), - styleYearPicker: _buildYearPickerStyle(), - ); - if (date != null) { - _selectedFromDate = date; - - // flag to adjust date so from date is always before to date - final flag = !_selectedFromDate.isBefore(_selectedToDate); - if (flag) { - _selectedToDate = DateTime.fromMillisecondsSinceEpoch( - _selectedFromDate.millisecondsSinceEpoch); + Expanded( + child: GestureDetector( + key: const Key("transactionSearchViewFromDatePickerKey"), + onTap: () async { + final color = + Theme.of(context).extension()!.accentColorDark; + final height = MediaQuery.of(context).size.height; + // check and hide keyboard + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed(const Duration(milliseconds: 125)); } - setState(() { + final date = await showRoundedDatePicker( + // This doesn't change statusbar color... + // background: CFColors.starryNight.withOpacity(0.8), + context: context, + initialDate: DateTime.now(), + height: height * 0.5, + theme: ThemeData( + primarySwatch: Util.createMaterialColor( + color, + ), + ), + //TODO pick a better initial date + // 2007 chosen as that is just before bitcoin launched + firstDate: DateTime(2007), + lastDate: DateTime.now(), + borderRadius: Constants.size.circularBorderRadius * 2, + + textPositiveButton: "SELECT", + + styleDatePicker: _buildDatePickerStyle(), + styleYearPicker: _buildYearPickerStyle(), + ); + if (date != null) { + _selectedFromDate = date; + + // flag to adjust date so from date is always before to date + final flag = !_selectedFromDate.isBefore(_selectedToDate); if (flag) { - _toDateString = Format.formatDate(_selectedToDate); + _selectedToDate = DateTime.fromMillisecondsSinceEpoch( + _selectedFromDate.millisecondsSinceEpoch); } - _fromDateString = Format.formatDate(_selectedFromDate); - }); - } - }, - child: Container( - width: width, - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), - border: Border.all( + + setState(() { + if (flag) { + _toDateString = Format.formatDate(_selectedToDate); + } + _fromDateString = Format.formatDate(_selectedFromDate); + }); + } + }, + child: Container( + width: width, + decoration: BoxDecoration( color: Theme.of(context) .extension()! .textFieldDefaultBG, - width: 1, + borderRadius: + BorderRadius.circular(Constants.size.circularBorderRadius), + border: Border.all( + color: Theme.of(context) + .extension()! + .textFieldDefaultBG, + width: 1, + ), ), - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.calendar, - height: 20, - width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, - ), - Align( - alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateFromText, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: 12, + vertical: isDesktop ? 17 : 12, + ), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.calendar, + height: 20, + width: 20, + color: Theme.of(context) + .extension()! + .textSubtitle2, ), - ) - ], + const SizedBox( + width: 10, + ), + Align( + alignment: Alignment.centerLeft, + child: FittedBox( + child: _dateFromText, + ), + ) + ], + ), ), ), ), @@ -277,470 +294,653 @@ class _TransactionSearchViewState // color: CFColors.smoke, ), ), - GestureDetector( - key: const Key("transactionSearchViewToDatePickerKey"), - onTap: () async { - final color = - Theme.of(context).extension()!.accentColorDark; - final height = MediaQuery.of(context).size.height; - // check and hide keyboard - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 125)); - } - - final date = await showRoundedDatePicker( - // This doesn't change statusbar color... - // background: CFColors.starryNight.withOpacity(0.8), - context: context, - height: height * 0.5, - theme: ThemeData( - primarySwatch: Util.createMaterialColor( - color, - ), - ), - //TODO pick a better initial date - // 2007 chosen as that is just before bitcoin launched - initialDate: DateTime.now(), - firstDate: DateTime(2007), - lastDate: DateTime.now(), - borderRadius: Constants.size.circularBorderRadius * 2, - - textPositiveButton: "SELECT", - - styleDatePicker: _buildDatePickerStyle(), - styleYearPicker: _buildYearPickerStyle(), - ); - if (date != null) { - _selectedToDate = date; - - // flag to adjust date so from date is always before to date - final flag = !_selectedToDate.isAfter(_selectedFromDate); - if (flag) { - _selectedFromDate = DateTime.fromMillisecondsSinceEpoch( - _selectedToDate.millisecondsSinceEpoch); + Expanded( + child: GestureDetector( + key: const Key("transactionSearchViewToDatePickerKey"), + onTap: () async { + final color = + Theme.of(context).extension()!.accentColorDark; + final height = MediaQuery.of(context).size.height; + // check and hide keyboard + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed(const Duration(milliseconds: 125)); } - setState(() { + final date = await showRoundedDatePicker( + // This doesn't change statusbar color... + // background: CFColors.starryNight.withOpacity(0.8), + context: context, + height: height * 0.5, + theme: ThemeData( + primarySwatch: Util.createMaterialColor( + color, + ), + ), + //TODO pick a better initial date + // 2007 chosen as that is just before bitcoin launched + initialDate: DateTime.now(), + firstDate: DateTime(2007), + lastDate: DateTime.now(), + borderRadius: Constants.size.circularBorderRadius * 2, + + textPositiveButton: "SELECT", + + styleDatePicker: _buildDatePickerStyle(), + styleYearPicker: _buildYearPickerStyle(), + ); + if (date != null) { + _selectedToDate = date; + + // flag to adjust date so from date is always before to date + final flag = !_selectedToDate.isAfter(_selectedFromDate); if (flag) { - _fromDateString = Format.formatDate(_selectedFromDate); + _selectedFromDate = DateTime.fromMillisecondsSinceEpoch( + _selectedToDate.millisecondsSinceEpoch); } - _toDateString = Format.formatDate(_selectedToDate); - }); - } - }, - child: Container( - width: width, - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), - border: Border.all( + + setState(() { + if (flag) { + _fromDateString = Format.formatDate(_selectedFromDate); + } + _toDateString = Format.formatDate(_selectedToDate); + }); + } + }, + child: Container( + width: width, + decoration: BoxDecoration( color: Theme.of(context) .extension()! .textFieldDefaultBG, - width: 1, + borderRadius: + BorderRadius.circular(Constants.size.circularBorderRadius), + border: Border.all( + color: Theme.of(context) + .extension()! + .textFieldDefaultBG, + width: 1, + ), ), - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.calendar, - height: 20, - width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, - ), - Align( - alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateToText, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: 12, + vertical: isDesktop ? 17 : 12, + ), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.calendar, + height: 20, + width: 20, + color: Theme.of(context) + .extension()! + .textSubtitle2, ), - ) - ], + const SizedBox( + width: 10, + ), + Align( + alignment: Alignment.centerLeft, + child: FittedBox( + child: _dateToText, + ), + ) + ], + ), ), ), ), ), + if (isDesktop) + const SizedBox( + width: 24, + ), ], ); } @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( + if (Util.isDesktop) { + return DesktopDialog( + maxWidth: 576, + maxHeight: double.infinity, + child: Padding( + padding: const EdgeInsets.only( + left: 32, + bottom: 32, + ), + child: _buildContent(context), + ), + ); + } else { + return Scaffold( backgroundColor: Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed(const Duration(milliseconds: 75)); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Transactions filter", + style: STextStyles.navBarTitle(context), + ), ), - title: Text( - "Transactions filter", - style: STextStyles.navBarTitle(context), + body: Padding( + padding: EdgeInsets.symmetric( + horizontal: Constants.size.standardPadding, + ), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: constraints.maxHeight), + child: IntrinsicHeight( + child: _buildContent(context), + ), + ), + ); + }, + ), ), - ), - body: Padding( - padding: EdgeInsets.symmetric( - horizontal: Constants.size.standardPadding, + ); + } + } + + Widget _buildContent(BuildContext context) { + final isDesktop = Util.isDesktop; + + return Column( + children: [ + if (isDesktop) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction filter", + style: STextStyles.desktopH3(context), + textAlign: TextAlign.center, + ), + const DesktopDialogCloseButton(), + ], + ), + SizedBox( + height: isDesktop ? 14 : 10, ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: Column( - children: [ - const SizedBox( - height: 10, - ), - Align( - alignment: Alignment.centerLeft, - child: FittedBox( - child: Text( - "Transactions", - style: STextStyles.smallMed12(context), - ), - ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - GestureDetector( - onTap: () { - setState(() { - _isActiveSentCheckbox = - !_isActiveSentCheckbox; - }); - }, - child: Container( - color: Colors.transparent, - child: Row( - children: [ - SizedBox( - height: 20, - width: 20, - child: Checkbox( - key: const Key( - "transactionSearchViewSentCheckboxKey"), - materialTapTargetSize: - MaterialTapTargetSize - .shrinkWrap, - value: _isActiveSentCheckbox, - onChanged: (newValue) { - setState(() { - _isActiveSentCheckbox = - newValue!; - }); - }, - ), - ), - const SizedBox( - width: 14, - ), - Align( - alignment: Alignment.centerLeft, - child: FittedBox( - child: Text( - "Sent", - style: STextStyles.itemSubtitle12( - context), - ), - ), - ) - ], - ), - ), - ), - ], - ), - const SizedBox( - height: 10, - ), - Row( - children: [ - GestureDetector( - onTap: () { - setState(() { - _isActiveReceivedCheckbox = - !_isActiveReceivedCheckbox; - }); - }, - child: Container( - color: Colors.transparent, - child: Row( - children: [ - SizedBox( - height: 20, - width: 20, - child: Checkbox( - key: const Key( - "transactionSearchViewReceivedCheckboxKey"), - materialTapTargetSize: - MaterialTapTargetSize - .shrinkWrap, - value: _isActiveReceivedCheckbox, - onChanged: (newValue) { - setState(() { - _isActiveReceivedCheckbox = - newValue!; - }); - }, - ), - ), - const SizedBox( - width: 14, - ), - Align( - alignment: Alignment.centerLeft, - child: FittedBox( - child: Text( - "Received", - style: STextStyles.itemSubtitle12( - context), - ), - ), - ) - ], - ), - ), - ), - ], - ), - ], - ), - ), - const SizedBox( - height: 24, - ), - Align( - alignment: Alignment.centerLeft, - child: FittedBox( - child: Text( - "Date", - style: STextStyles.smallMed12(context), - ), - ), - ), - const SizedBox( - height: 8, - ), - _buildDateRangePicker(), - const SizedBox( - height: 24, - ), - Align( - alignment: Alignment.centerLeft, - child: FittedBox( - child: Text( - "Amount", - style: STextStyles.smallMed12(context), - ), - ), - ), - const SizedBox( - height: 8, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - key: const Key("transactionSearchViewAmountFieldKey"), - controller: _amountTextEditingController, - focusNode: amountTextFieldFocusNode, - onChanged: (_) => setState(() {}), - keyboardType: const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), - inputFormatters: [ - // regex to validate a crypto amount with 8 decimal places - TextInputFormatter.withFunction((oldValue, - newValue) => - RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') - .hasMatch(newValue.text) - ? newValue - : oldValue), - ], - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter ${widget.coin.ticker} amount...", - keywordTextFieldFocusNode, - context, - ).copyWith( - suffixIcon: _amountTextEditingController - .text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _amountTextEditingController - .text = ""; - }); - }, - ), - ], - ), - ), - ) - : null, - ), - ), - ), - const SizedBox( - height: 24, - ), - Align( - alignment: Alignment.centerLeft, - child: FittedBox( - child: Text( - "Keyword", - style: STextStyles.smallMed12(context), - ), - ), - ), - const SizedBox( - height: 8, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - key: - const Key("transactionSearchViewKeywordFieldKey"), - controller: _keywordTextEditingController, - focusNode: keywordTextFieldFocusNode, - style: STextStyles.field(context), - onChanged: (_) => setState(() {}), - decoration: standardInputDecoration( - "Type keyword...", - keywordTextFieldFocusNode, - context, - ).copyWith( - suffixIcon: _keywordTextEditingController - .text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _keywordTextEditingController - .text = ""; - }); - }, - ), - ], - ), - ), - ) - : null, - ), - ), - ), - const Spacer(), - const SizedBox( - height: 20, - ), - Row( + if (!isDesktop) + Align( + alignment: Alignment.centerLeft, + child: FittedBox( + child: Text( + "Transactions", + style: STextStyles.smallMed12(context), + ), + ), + ), + if (!isDesktop) + const SizedBox( + height: 12, + ), + RoundedWhiteContainer( + padding: EdgeInsets.all(isDesktop ? 0 : 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + GestureDetector( + onTap: () { + setState(() { + _isActiveSentCheckbox = !_isActiveSentCheckbox; + }); + }, + child: Container( + color: Colors.transparent, + child: Row( children: [ - Expanded( - child: SizedBox( - height: 48, - child: TextButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75)); - } - if (mounted) { - 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), - ), - ), + SizedBox( + height: 20, + width: 20, + child: Checkbox( + key: const Key( + "transactionSearchViewSentCheckboxKey"), + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + value: _isActiveSentCheckbox, + onChanged: (newValue) { + setState(() { + _isActiveSentCheckbox = newValue!; + }); + }, ), ), const SizedBox( - width: 16, + width: 14, ), - Expanded( - child: SizedBox( - height: 48, - child: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonColor(context), - onPressed: () async { - _onApplyPressed(); - }, - child: Text( - "Save", - style: STextStyles.button(context), - ), + Align( + alignment: Alignment.centerLeft, + child: FittedBox( + child: Column( + children: [ + Text( + "Sent", + style: isDesktop + ? STextStyles.desktopTextSmall(context) + : STextStyles.itemSubtitle12(context), + ), + if (isDesktop) + const SizedBox( + height: 4, + ), + ], ), ), - ), + ) ], ), - const SizedBox( - height: 20, - ), - ], + ), ), - ), + ], ), - ); - }, + SizedBox( + height: isDesktop ? 4 : 10, + ), + Row( + children: [ + GestureDetector( + onTap: () { + setState(() { + _isActiveReceivedCheckbox = !_isActiveReceivedCheckbox; + }); + }, + child: Container( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + height: 20, + width: 20, + child: Checkbox( + key: const Key( + "transactionSearchViewReceivedCheckboxKey"), + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + value: _isActiveReceivedCheckbox, + onChanged: (newValue) { + setState(() { + _isActiveReceivedCheckbox = newValue!; + }); + }, + ), + ), + const SizedBox( + width: 14, + ), + Align( + alignment: Alignment.centerLeft, + child: FittedBox( + child: Column( + children: [ + Text( + "Received", + style: isDesktop + ? STextStyles.desktopTextSmall(context) + : STextStyles.itemSubtitle12(context), + ), + if (isDesktop) + const SizedBox( + height: 4, + ), + ], + ), + ), + ) + ], + ), + ), + ), + ], + ), + SizedBox( + height: isDesktop ? 4 : 10, + ), + Row( + children: [ + GestureDetector( + onTap: () { + setState(() { + _isActiveTradeCheckbox = !_isActiveTradeCheckbox; + }); + }, + child: Container( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + height: 20, + width: 20, + child: Checkbox( + key: const Key( + "transactionSearchViewSentCheckboxKey"), + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + value: _isActiveTradeCheckbox, + onChanged: (newValue) { + setState(() { + _isActiveTradeCheckbox = newValue!; + }); + }, + ), + ), + const SizedBox( + width: 14, + ), + Align( + alignment: Alignment.centerLeft, + child: FittedBox( + child: Column( + children: [ + Text( + "Trades", + style: isDesktop + ? STextStyles.desktopTextSmall(context) + : STextStyles.itemSubtitle12(context), + ), + if (isDesktop) + const SizedBox( + height: 4, + ), + ], + ), + ), + ) + ], + ), + ), + ), + ], + ), + ], + ), ), - ), + SizedBox( + height: isDesktop ? 32 : 24, + ), + Align( + alignment: Alignment.centerLeft, + child: FittedBox( + child: Text( + "Date", + style: isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), + ), + ), + ), + SizedBox( + height: isDesktop ? 10 : 8, + ), + _buildDateRangePicker(), + SizedBox( + height: isDesktop ? 32 : 24, + ), + Align( + alignment: Alignment.centerLeft, + child: FittedBox( + child: Text( + "Amount", + style: isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), + ), + ), + ), + SizedBox( + height: isDesktop ? 10 : 8, + ), + Padding( + padding: EdgeInsets.only(right: isDesktop ? 32 : 0), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + key: const Key("transactionSearchViewAmountFieldKey"), + controller: _amountTextEditingController, + focusNode: amountTextFieldFocusNode, + onChanged: (_) => setState(() {}), + keyboardType: const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), + inputFormatters: [ + // regex to validate a crypto amount with 8 decimal places + TextInputFormatter.withFunction((oldValue, newValue) => + RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') + .hasMatch(newValue.text) + ? newValue + : oldValue), + ], + style: isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), + decoration: standardInputDecoration( + "Enter ${widget.coin.ticker} amount...", + keywordTextFieldFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + contentPadding: isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: _amountTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _amountTextEditingController.text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, + ), + ), + ), + ), + SizedBox( + height: isDesktop ? 32 : 24, + ), + Align( + alignment: Alignment.centerLeft, + child: FittedBox( + child: Text( + "Keyword", + style: isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), + ), + ), + ), + SizedBox( + height: isDesktop ? 10 : 8, + ), + Padding( + padding: EdgeInsets.only(right: isDesktop ? 32 : 0), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + key: const Key("transactionSearchViewKeywordFieldKey"), + controller: _keywordTextEditingController, + focusNode: keywordTextFieldFocusNode, + style: isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Type keyword...", + keywordTextFieldFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + contentPadding: isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: _keywordTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _keywordTextEditingController.text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, + ), + ), + ), + ), + if (!isDesktop) const Spacer(), + SizedBox( + height: isDesktop ? 32 : 20, + ), + Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + desktopMed: isDesktop, + onPressed: () async { + if (!isDesktop) { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration( + milliseconds: 75, + ), + ); + } + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + ), + // Expanded( + // child: SizedBox( + // height: 48, + // child: TextButton( + // onPressed: () async { + // if (FocusScope.of(context).hasFocus) { + // FocusScope.of(context).unfocus(); + // await Future.delayed( + // const Duration(milliseconds: 75)); + // } + // if (mounted) { + // 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( + width: 16, + ), + Expanded( + child: PrimaryButton( + desktopMed: isDesktop, + onPressed: () async { + await _onApplyPressed(); + }, + label: "Save", + ), + ), + // Expanded( + // child: SizedBox( + // height: 48, + // child: TextButton( + // style: Theme.of(context) + // .extension()! + // .getPrimaryEnabledButtonColor(context), + // onPressed: () async { + // await _onApplyPressed(); + // }, + // child: Text( + // "Save", + // style: STextStyles.button(context), + // ), + // ), + // ), + // ), + if (isDesktop) + const SizedBox( + width: 32, + ), + ], + ), + if (!isDesktop) + const SizedBox( + height: 20, + ), + ], ); } diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart index 9d0d9ed64..35b63174c 100644 --- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -359,6 +359,7 @@ class _MyWalletState extends State { @override Widget build(BuildContext context) { return ListView( + primary: false, children: [ Text( "My wallet", diff --git a/lib/utilities/text_styles.dart b/lib/utilities/text_styles.dart index 82e2ad349..b583dba98 100644 --- a/lib/utilities/text_styles.dart +++ b/lib/utilities/text_styles.dart @@ -228,6 +228,25 @@ class STextStyles { } } + static TextStyle labelExtraExtraSmall(BuildContext context) { + switch (_theme(context).themeType) { + case ThemeType.light: + return GoogleFonts.inter( + color: _theme(context).textFieldActiveSearchIconRight, + fontWeight: FontWeight.w500, + fontSize: 14, + height: 14 / 14, + ); + case ThemeType.dark: + return GoogleFonts.inter( + color: _theme(context).textFieldActiveSearchIconRight, + fontWeight: FontWeight.w500, + fontSize: 14, + height: 14 / 14, + ); + } + } + static TextStyle label700(BuildContext context) { switch (_theme(context).themeType) { case ThemeType.light: